aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadaf Ebrahimi <sadafebrahimi@google.com>2024-02-20 18:53:58 +0000
committerSadaf Ebrahimi <sadafebrahimi@google.com>2024-02-20 18:55:51 +0000
commit94577271ee81d3399bec0328cc6a27688029edec (patch)
tree1b01132e15db02538dcf10922559df5a286d1cd6
parent97598f1763810e446ff21ec60fb0b222097b32c6 (diff)
parent5ce164e0e9290c96eb7d502173426c0a135ec008 (diff)
downloadcurl-94577271ee81d3399bec0328cc6a27688029edec.tar.gz
Upgrade curl to curl-8_6_0
This project was upgraded with external_updater. Usage: tools/external_updater/updater.sh update external/curl For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md Test: TreeHugger Change-Id: I083147dff18fe11adc3131953c5ad4a3e14433fe
-rw-r--r--.azure-pipelines.yml406
-rw-r--r--.circleci/config.yml17
-rw-r--r--.cirrus.yml22
-rw-r--r--.github/dependabot.yml6
-rw-r--r--.github/labeler.yml585
-rwxr-xr-x.github/scripts/badwords.pl67
-rw-r--r--.github/scripts/badwords.txt46
-rwxr-xr-x.github/scripts/cleancmd.pl52
-rwxr-xr-x.github/scripts/cleanspell.pl1
-rw-r--r--.github/scripts/codespell-ignore.txt15
-rw-r--r--.github/scripts/spellcheck.words19
-rw-r--r--.github/scripts/spellcheck.yaml52
-rwxr-xr-x.github/scripts/verify-examples.pl110
-rwxr-xr-x.github/scripts/verify-synopsis.pl80
-rw-r--r--.github/workflows/awslc.yml226
-rw-r--r--.github/workflows/badwords.yml27
-rw-r--r--.github/workflows/codeql-analysis.yml94
-rw-r--r--.github/workflows/codespell.yml36
-rw-r--r--.github/workflows/configure-vs-cmake.yml44
-rw-r--r--.github/workflows/distcheck.yml157
-rw-r--r--.github/workflows/fuzz.yml54
-rw-r--r--.github/workflows/hacktoberfest-accepted.yml2
-rw-r--r--.github/workflows/label.yml8
-rw-r--r--.github/workflows/linkcheck.yml27
-rw-r--r--.github/workflows/linux.yml786
-rw-r--r--.github/workflows/linux32.yml102
-rw-r--r--.github/workflows/macos.yml375
-rw-r--r--.github/workflows/man-examples.yml35
-rw-r--r--.github/workflows/ngtcp2-linux.yml468
-rw-r--r--.github/workflows/osslq-linux.yml233
-rw-r--r--.github/workflows/proselint.yml75
-rw-r--r--.github/workflows/quiche-linux.yml350
-rw-r--r--.github/workflows/reuse.yml12
-rw-r--r--.github/workflows/spellcheck.yml84
-rw-r--r--.github/workflows/synopsis.yml28
-rw-r--r--.github/workflows/torture.yml102
-rw-r--r--.github/workflows/wolfssl.yml124
-rw-r--r--.reuse/dep54
-rw-r--r--CMake/CurlTests.c271
-rw-r--r--CMake/FindZstd.cmake7
-rw-r--r--CMake/Macros.cmake23
-rw-r--r--CMake/OtherTests.cmake175
-rw-r--r--CMake/PickyWarnings.cmake65
-rw-r--r--CMake/Platforms/WindowsCache.cmake255
-rw-r--r--CMake/curl-config.cmake.in4
-rw-r--r--CMakeLists.txt715
-rw-r--r--COPYING2
-rw-r--r--METADATA23
-rw-r--r--Makefile.am139
-rw-r--r--Makefile.dist21
-rw-r--r--RELEASE-NOTES619
-rw-r--r--acinclude.m4303
-rw-r--r--appveyor.sh160
-rw-r--r--appveyor.yml227
-rwxr-xr-xconfigure2083
-rw-r--r--configure.ac280
-rw-r--r--docs/.gitignore6
-rw-r--r--docs/ALTSVC.md6
-rw-r--r--docs/BINDINGS.md2
-rw-r--r--docs/BUFQ.md17
-rw-r--r--docs/BUGS.md2
-rw-r--r--docs/CIPHERS.md8
-rw-r--r--docs/CLIENT-WRITERS.md104
-rw-r--r--docs/CMakeLists.txt8
-rw-r--r--docs/CODE_STYLE.md2
-rw-r--r--docs/CONNECTION-FILTERS.md149
-rw-r--r--docs/CONTRIBUTE.md16
-rw-r--r--docs/CURLDOWN.md125
-rw-r--r--docs/DEPRECATE.md15
-rw-r--r--docs/EXPERIMENTAL.md2
-rw-r--r--docs/FEATURES.md10
-rw-r--r--docs/GOVERNANCE.md2
-rw-r--r--docs/HISTORY.md2
-rw-r--r--docs/HSTS.md4
-rw-r--r--docs/HTTP-COOKIES.md19
-rw-r--r--docs/HTTP3.md86
-rw-r--r--docs/HYPER.md4
-rw-r--r--docs/INSTALL-CMAKE.md133
-rw-r--r--docs/INSTALL.cmake89
-rw-r--r--docs/INSTALL.md131
-rw-r--r--docs/IPFS.md93
-rw-r--r--docs/KNOWN_BUGS41
-rw-r--r--docs/MANUAL.md32
-rw-r--r--docs/Makefile.am50
-rw-r--r--docs/NEW-PROTOCOL.md2
-rw-r--r--docs/PARALLEL-TRANSFERS.md6
-rw-r--r--docs/SECURITY-ADVISORY.md2
-rw-r--r--docs/SSLCERTS.md14
-rw-r--r--docs/THANKS81
-rw-r--r--docs/TODO25
-rw-r--r--docs/TheArtOfHttpScripting.md43
-rw-r--r--docs/URL-SYNTAX.md8
-rw-r--r--docs/VULN-DISCLOSURE-POLICY.md14
-rw-r--r--docs/WEBSOCKET.md7
-rw-r--r--docs/cmdline-opts/CMakeLists.txt8
-rw-r--r--docs/cmdline-opts/MANPAGE.md59
-rw-r--r--docs/cmdline-opts/Makefile.am7
-rw-r--r--docs/cmdline-opts/Makefile.inc539
-rw-r--r--docs/cmdline-opts/_AUTHORS.md5
-rw-r--r--docs/cmdline-opts/_BUGS.md5
-rw-r--r--docs/cmdline-opts/_DESCRIPTION.md11
-rw-r--r--docs/cmdline-opts/_ENVIRONMENT.md114
-rw-r--r--docs/cmdline-opts/_EXITCODES.md201
-rw-r--r--docs/cmdline-opts/_FILES.md6
-rw-r--r--docs/cmdline-opts/_GLOBBING.md40
-rw-r--r--docs/cmdline-opts/_NAME.md4
-rw-r--r--docs/cmdline-opts/_OPTIONS.md26
-rw-r--r--docs/cmdline-opts/_OUTPUT.md11
-rw-r--r--docs/cmdline-opts/_PROGRESS.md25
-rw-r--r--docs/cmdline-opts/_PROTOCOLS.md51
-rw-r--r--docs/cmdline-opts/_PROXYPREFIX.md22
-rw-r--r--docs/cmdline-opts/_SEEALSO.md5
-rw-r--r--docs/cmdline-opts/_SYNOPSIS.md5
-rw-r--r--docs/cmdline-opts/_URL.md28
-rw-r--r--docs/cmdline-opts/_VARIABLES.md44
-rw-r--r--docs/cmdline-opts/_VERSION.md15
-rw-r--r--docs/cmdline-opts/_WWW.md4
-rw-r--r--docs/cmdline-opts/abstract-unix-socket.d15
-rw-r--r--docs/cmdline-opts/abstract-unix-socket.md21
-rw-r--r--docs/cmdline-opts/alt-svc.d21
-rw-r--r--docs/cmdline-opts/alt-svc.md28
-rw-r--r--docs/cmdline-opts/anyauth.d22
-rw-r--r--docs/cmdline-opts/anyauth.md30
-rw-r--r--docs/cmdline-opts/append.d16
-rw-r--r--docs/cmdline-opts/append.md23
-rw-r--r--docs/cmdline-opts/aws-sigv4.d22
-rw-r--r--docs/cmdline-opts/aws-sigv4.md30
-rw-r--r--docs/cmdline-opts/basic.d17
-rw-r--r--docs/cmdline-opts/basic.md23
-rw-r--r--docs/cmdline-opts/ca-native.d21
-rw-r--r--docs/cmdline-opts/ca-native.md28
-rw-r--r--docs/cmdline-opts/cacert.d35
-rw-r--r--docs/cmdline-opts/cacert.md42
-rw-r--r--docs/cmdline-opts/capath.d21
-rw-r--r--docs/cmdline-opts/capath.md28
-rw-r--r--docs/cmdline-opts/cert-status.d19
-rw-r--r--docs/cmdline-opts/cert-status.md25
-rw-r--r--docs/cmdline-opts/cert-type.d18
-rw-r--r--docs/cmdline-opts/cert-type.md26
-rw-r--r--docs/cmdline-opts/cert.d49
-rw-r--r--docs/cmdline-opts/cert.md56
-rw-r--r--docs/cmdline-opts/ciphers.d16
-rw-r--r--docs/cmdline-opts/ciphers.md24
-rw-r--r--docs/cmdline-opts/compressed-ssh.d13
-rw-r--r--docs/cmdline-opts/compressed-ssh.md19
-rw-r--r--docs/cmdline-opts/compressed.d21
-rw-r--r--docs/cmdline-opts/compressed.md27
-rw-r--r--docs/cmdline-opts/config.d77
-rw-r--r--docs/cmdline-opts/config.md83
-rw-r--r--docs/cmdline-opts/connect-timeout.d22
-rw-r--r--docs/cmdline-opts/connect-timeout.md28
-rw-r--r--docs/cmdline-opts/connect-to.d24
-rw-r--r--docs/cmdline-opts/connect-to.md30
-rw-r--r--docs/cmdline-opts/continue-at.d20
-rw-r--r--docs/cmdline-opts/continue-at.md26
-rw-r--r--docs/cmdline-opts/cookie-jar.d31
-rw-r--r--docs/cmdline-opts/cookie-jar.md37
-rw-r--r--docs/cmdline-opts/cookie.d42
-rw-r--r--docs/cmdline-opts/cookie.md58
-rw-r--r--docs/cmdline-opts/create-dirs.d19
-rw-r--r--docs/cmdline-opts/create-dirs.md26
-rw-r--r--docs/cmdline-opts/create-file-mode.d17
-rw-r--r--docs/cmdline-opts/create-file-mode.md23
-rw-r--r--docs/cmdline-opts/crlf.d15
-rw-r--r--docs/cmdline-opts/crlf.md21
-rw-r--r--docs/cmdline-opts/crlfile.d14
-rw-r--r--docs/cmdline-opts/crlfile.md21
-rw-r--r--docs/cmdline-opts/curves.d22
-rw-r--r--docs/cmdline-opts/curves.md28
-rw-r--r--docs/cmdline-opts/data-ascii.d13
-rw-r--r--docs/cmdline-opts/data-ascii.md21
-rw-r--r--docs/cmdline-opts/data-binary.d25
-rw-r--r--docs/cmdline-opts/data-binary.md31
-rw-r--r--docs/cmdline-opts/data-raw.d15
-rw-r--r--docs/cmdline-opts/data-raw.md21
-rw-r--r--docs/cmdline-opts/data-urlencode.d42
-rw-r--r--docs/cmdline-opts/data-urlencode.md51
-rw-r--r--docs/cmdline-opts/data.d41
-rw-r--r--docs/cmdline-opts/data.md49
-rw-r--r--docs/cmdline-opts/delegation.d24
-rw-r--r--docs/cmdline-opts/delegation.md31
-rw-r--r--docs/cmdline-opts/digest.d15
-rw-r--r--docs/cmdline-opts/digest.md23
-rw-r--r--docs/cmdline-opts/disable-eprt.d25
-rw-r--r--docs/cmdline-opts/disable-eprt.md32
-rw-r--r--docs/cmdline-opts/disable-epsv.d23
-rw-r--r--docs/cmdline-opts/disable-epsv.md30
-rw-r--r--docs/cmdline-opts/disable.d17
-rw-r--r--docs/cmdline-opts/disable.md23
-rw-r--r--docs/cmdline-opts/disallow-username-in-url.d13
-rw-r--r--docs/cmdline-opts/disallow-username-in-url.md18
-rw-r--r--docs/cmdline-opts/dns-interface.d16
-rw-r--r--docs/cmdline-opts/dns-interface.md23
-rw-r--r--docs/cmdline-opts/dns-ipv4-addr.d16
-rw-r--r--docs/cmdline-opts/dns-ipv4-addr.md23
-rw-r--r--docs/cmdline-opts/dns-ipv6-addr.d16
-rw-r--r--docs/cmdline-opts/dns-ipv6-addr.md23
-rw-r--r--docs/cmdline-opts/dns-servers.d16
-rw-r--r--docs/cmdline-opts/dns-servers.md24
-rw-r--r--docs/cmdline-opts/doh-cert-status.d11
-rw-r--r--docs/cmdline-opts/doh-cert-status.md17
-rw-r--r--docs/cmdline-opts/doh-insecure.d11
-rw-r--r--docs/cmdline-opts/doh-insecure.md17
-rw-r--r--docs/cmdline-opts/doh-url.d21
-rw-r--r--docs/cmdline-opts/doh-url.md27
-rw-r--r--docs/cmdline-opts/dump-header.d21
-rw-r--r--docs/cmdline-opts/dump-header.md27
-rw-r--r--docs/cmdline-opts/egd-file.d17
-rw-r--r--docs/cmdline-opts/egd-file.md23
-rw-r--r--docs/cmdline-opts/engine.d15
-rw-r--r--docs/cmdline-opts/engine.md22
-rw-r--r--docs/cmdline-opts/etag-compare.d23
-rw-r--r--docs/cmdline-opts/etag-compare.md30
-rw-r--r--docs/cmdline-opts/etag-save.d16
-rw-r--r--docs/cmdline-opts/etag-save.md22
-rw-r--r--docs/cmdline-opts/expect100-timeout.d19
-rw-r--r--docs/cmdline-opts/expect100-timeout.md25
-rw-r--r--docs/cmdline-opts/fail-early.d25
-rw-r--r--docs/cmdline-opts/fail-early.md32
-rw-r--r--docs/cmdline-opts/fail-with-body.d20
-rw-r--r--docs/cmdline-opts/fail-with-body.md27
-rw-r--r--docs/cmdline-opts/fail.d22
-rw-r--r--docs/cmdline-opts/fail.md29
-rw-r--r--docs/cmdline-opts/false-start.d18
-rw-r--r--docs/cmdline-opts/false-start.md24
-rw-r--r--docs/cmdline-opts/form-escape.d13
-rw-r--r--docs/cmdline-opts/form-escape.md19
-rw-r--r--docs/cmdline-opts/form-string.d17
-rw-r--r--docs/cmdline-opts/form-string.md23
-rw-r--r--docs/cmdline-opts/form.d134
-rw-r--r--docs/cmdline-opts/form.md142
-rw-r--r--docs/cmdline-opts/ftp-account.d14
-rw-r--r--docs/cmdline-opts/ftp-account.md20
-rw-r--r--docs/cmdline-opts/ftp-alternative-to-user.d16
-rw-r--r--docs/cmdline-opts/ftp-alternative-to-user.md23
-rw-r--r--docs/cmdline-opts/ftp-create-dirs.d14
-rw-r--r--docs/cmdline-opts/ftp-create-dirs.md20
-rw-r--r--docs/cmdline-opts/ftp-method.d30
-rw-r--r--docs/cmdline-opts/ftp-method.md36
-rw-r--r--docs/cmdline-opts/ftp-pasv.d20
-rw-r--r--docs/cmdline-opts/ftp-pasv.md26
-rw-r--r--docs/cmdline-opts/ftp-port.d41
-rw-r--r--docs/cmdline-opts/ftp-port.md51
-rw-r--r--docs/cmdline-opts/ftp-pret.d14
-rw-r--r--docs/cmdline-opts/ftp-pret.md21
-rw-r--r--docs/cmdline-opts/ftp-skip-pasv-ip.d18
-rw-r--r--docs/cmdline-opts/ftp-skip-pasv-ip.md24
-rw-r--r--docs/cmdline-opts/ftp-ssl-ccc-mode.d16
-rw-r--r--docs/cmdline-opts/ftp-ssl-ccc-mode.md22
-rw-r--r--docs/cmdline-opts/ftp-ssl-ccc.d15
-rw-r--r--docs/cmdline-opts/ftp-ssl-ccc.md22
-rw-r--r--docs/cmdline-opts/ftp-ssl-control.d14
-rw-r--r--docs/cmdline-opts/ftp-ssl-control.md20
-rwxr-xr-xdocs/cmdline-opts/gen.pl431
-rw-r--r--docs/cmdline-opts/get.d20
-rw-r--r--docs/cmdline-opts/get.md28
-rw-r--r--docs/cmdline-opts/globoff.d15
-rw-r--r--docs/cmdline-opts/globoff.md22
-rw-r--r--docs/cmdline-opts/happy-eyeballs-timeout-ms.d21
-rw-r--r--docs/cmdline-opts/happy-eyeballs-timeout-ms.md28
-rw-r--r--docs/cmdline-opts/haproxy-clientip.d29
-rw-r--r--docs/cmdline-opts/haproxy-clientip.md33
-rw-r--r--docs/cmdline-opts/haproxy-protocol.d17
-rw-r--r--docs/cmdline-opts/haproxy-protocol.md23
-rw-r--r--docs/cmdline-opts/head.d15
-rw-r--r--docs/cmdline-opts/head.md23
-rw-r--r--docs/cmdline-opts/header.d56
-rw-r--r--docs/cmdline-opts/header.md64
-rw-r--r--docs/cmdline-opts/help.d21
-rw-r--r--docs/cmdline-opts/help.md27
-rw-r--r--docs/cmdline-opts/hostpubmd5.d15
-rw-r--r--docs/cmdline-opts/hostpubmd5.md21
-rw-r--r--docs/cmdline-opts/hostpubsha256.d17
-rw-r--r--docs/cmdline-opts/hostpubsha256.md23
-rw-r--r--docs/cmdline-opts/hsts.d26
-rw-r--r--docs/cmdline-opts/hsts.md32
-rw-r--r--docs/cmdline-opts/http0.9.d19
-rw-r--r--docs/cmdline-opts/http0.9.md27
-rw-r--r--docs/cmdline-opts/http1.0.d16
-rw-r--r--docs/cmdline-opts/http1.0.md23
-rw-r--r--docs/cmdline-opts/http1.1.d14
-rw-r--r--docs/cmdline-opts/http1.1.md21
-rw-r--r--docs/cmdline-opts/http2-prior-knowledge.d18
-rw-r--r--docs/cmdline-opts/http2-prior-knowledge.md25
-rw-r--r--docs/cmdline-opts/http2.d25
-rw-r--r--docs/cmdline-opts/http2.md33
-rw-r--r--docs/cmdline-opts/http3-only.d25
-rw-r--r--docs/cmdline-opts/http3-only.md32
-rw-r--r--docs/cmdline-opts/http3.d27
-rw-r--r--docs/cmdline-opts/http3.md33
-rw-r--r--docs/cmdline-opts/ignore-content-length.d19
-rw-r--r--docs/cmdline-opts/ignore-content-length.md25
-rw-r--r--docs/cmdline-opts/include.d19
-rw-r--r--docs/cmdline-opts/include.md26
-rw-r--r--docs/cmdline-opts/insecure.d33
-rw-r--r--docs/cmdline-opts/insecure.md41
-rw-r--r--docs/cmdline-opts/interface.d19
-rw-r--r--docs/cmdline-opts/interface.md25
-rw-r--r--docs/cmdline-opts/ipfs-gateway.d44
-rw-r--r--docs/cmdline-opts/ipfs-gateway.md39
-rw-r--r--docs/cmdline-opts/ipv4.d17
-rw-r--r--docs/cmdline-opts/ipv4.md24
-rw-r--r--docs/cmdline-opts/ipv6.d17
-rw-r--r--docs/cmdline-opts/ipv6.md24
-rw-r--r--docs/cmdline-opts/json.d35
-rw-r--r--docs/cmdline-opts/json.md42
-rw-r--r--docs/cmdline-opts/junk-session-cookies.d15
-rw-r--r--docs/cmdline-opts/junk-session-cookies.md22
-rw-r--r--docs/cmdline-opts/keepalive-time.d21
-rw-r--r--docs/cmdline-opts/keepalive-time.md28
-rw-r--r--docs/cmdline-opts/key-type.d14
-rw-r--r--docs/cmdline-opts/key-type.md20
-rw-r--r--docs/cmdline-opts/key.d27
-rw-r--r--docs/cmdline-opts/key.md34
-rw-r--r--docs/cmdline-opts/krb.d16
-rw-r--r--docs/cmdline-opts/krb.md23
-rw-r--r--docs/cmdline-opts/libcurl.d15
-rw-r--r--docs/cmdline-opts/libcurl.md21
-rw-r--r--docs/cmdline-opts/limit-rate.d29
-rw-r--r--docs/cmdline-opts/limit-rate.md37
-rw-r--r--docs/cmdline-opts/list-only.d36
-rw-r--r--docs/cmdline-opts/list-only.md43
-rw-r--r--docs/cmdline-opts/local-port.d15
-rw-r--r--docs/cmdline-opts/local-port.md21
-rw-r--r--docs/cmdline-opts/location-trusted.d15
-rw-r--r--docs/cmdline-opts/location-trusted.md21
-rw-r--r--docs/cmdline-opts/location.d33
-rw-r--r--docs/cmdline-opts/location.md40
-rw-r--r--docs/cmdline-opts/login-options.d25
-rw-r--r--docs/cmdline-opts/login-options.md32
-rw-r--r--docs/cmdline-opts/mail-auth.d14
-rw-r--r--docs/cmdline-opts/mail-auth.md21
-rw-r--r--docs/cmdline-opts/mail-from.d13
-rw-r--r--docs/cmdline-opts/mail-from.md20
-rw-r--r--docs/cmdline-opts/mail-rcpt-allowfails.d22
-rw-r--r--docs/cmdline-opts/mail-rcpt-allowfails.md28
-rw-r--r--docs/cmdline-opts/mail-rcpt.d22
-rw-r--r--docs/cmdline-opts/mail-rcpt.md28
-rw-r--r--docs/cmdline-opts/mainpage.idx43
-rw-r--r--docs/cmdline-opts/manual.d12
-rw-r--r--docs/cmdline-opts/manual.md20
-rw-r--r--docs/cmdline-opts/max-filesize.d26
-rw-r--r--docs/cmdline-opts/max-filesize.md32
-rw-r--r--docs/cmdline-opts/max-redirs.d15
-rw-r--r--docs/cmdline-opts/max-redirs.md21
-rw-r--r--docs/cmdline-opts/max-time.d23
-rw-r--r--docs/cmdline-opts/max-time.md30
-rw-r--r--docs/cmdline-opts/metalink.d12
-rw-r--r--docs/cmdline-opts/metalink.md18
-rw-r--r--docs/cmdline-opts/negotiate.d19
-rw-r--r--docs/cmdline-opts/negotiate.md28
-rw-r--r--docs/cmdline-opts/netrc-file.d17
-rw-r--r--docs/cmdline-opts/netrc-file.md25
-rw-r--r--docs/cmdline-opts/netrc-optional.d13
-rw-r--r--docs/cmdline-opts/netrc-optional.md19
-rw-r--r--docs/cmdline-opts/netrc.d30
-rw-r--r--docs/cmdline-opts/netrc.md38
-rw-r--r--docs/cmdline-opts/next.d27
-rw-r--r--docs/cmdline-opts/next.md34
-rw-r--r--docs/cmdline-opts/no-alpn.d19
-rw-r--r--docs/cmdline-opts/no-alpn.md26
-rw-r--r--docs/cmdline-opts/no-buffer.d18
-rw-r--r--docs/cmdline-opts/no-buffer.md24
-rw-r--r--docs/cmdline-opts/no-clobber.d19
-rw-r--r--docs/cmdline-opts/no-clobber.md26
-rw-r--r--docs/cmdline-opts/no-keepalive.d15
-rw-r--r--docs/cmdline-opts/no-keepalive.md21
-rw-r--r--docs/cmdline-opts/no-npn.d19
-rw-r--r--docs/cmdline-opts/no-npn.md26
-rw-r--r--docs/cmdline-opts/no-progress-meter.d15
-rw-r--r--docs/cmdline-opts/no-progress-meter.md22
-rw-r--r--docs/cmdline-opts/no-sessionid.d19
-rw-r--r--docs/cmdline-opts/no-sessionid.md25
-rw-r--r--docs/cmdline-opts/noproxy.d27
-rw-r--r--docs/cmdline-opts/noproxy.md33
-rw-r--r--docs/cmdline-opts/ntlm-wb.d13
-rw-r--r--docs/cmdline-opts/ntlm-wb.md20
-rw-r--r--docs/cmdline-opts/ntlm.d22
-rw-r--r--docs/cmdline-opts/ntlm.md28
-rw-r--r--docs/cmdline-opts/oauth2-bearer.d17
-rw-r--r--docs/cmdline-opts/oauth2-bearer.md25
-rw-r--r--docs/cmdline-opts/output-dir.d19
-rw-r--r--docs/cmdline-opts/output-dir.md26
-rw-r--r--docs/cmdline-opts/output.d49
-rw-r--r--docs/cmdline-opts/output.md57
-rw-r--r--docs/cmdline-opts/page-footer322
-rw-r--r--docs/cmdline-opts/page-header258
-rw-r--r--docs/cmdline-opts/parallel-immediate.d15
-rw-r--r--docs/cmdline-opts/parallel-immediate.md22
-rw-r--r--docs/cmdline-opts/parallel-max.d18
-rw-r--r--docs/cmdline-opts/parallel-max.md24
-rw-r--r--docs/cmdline-opts/parallel.d14
-rw-r--r--docs/cmdline-opts/parallel.md21
-rw-r--r--docs/cmdline-opts/pass.d13
-rw-r--r--docs/cmdline-opts/pass.md20
-rw-r--r--docs/cmdline-opts/path-as-is.d13
-rw-r--r--docs/cmdline-opts/path-as-is.md19
-rw-r--r--docs/cmdline-opts/pinnedpubkey.d38
-rw-r--r--docs/cmdline-opts/pinnedpubkey.md44
-rw-r--r--docs/cmdline-opts/post301.d16
-rw-r--r--docs/cmdline-opts/post301.md24
-rw-r--r--docs/cmdline-opts/post302.d16
-rw-r--r--docs/cmdline-opts/post302.md24
-rw-r--r--docs/cmdline-opts/post303.d15
-rw-r--r--docs/cmdline-opts/post303.md23
-rw-r--r--docs/cmdline-opts/preproxy.d26
-rw-r--r--docs/cmdline-opts/preproxy.md33
-rw-r--r--docs/cmdline-opts/progress-bar.d20
-rw-r--r--docs/cmdline-opts/progress-bar.md26
-rw-r--r--docs/cmdline-opts/proto-default.d20
-rw-r--r--docs/cmdline-opts/proto-default.md27
-rw-r--r--docs/cmdline-opts/proto-redir.d22
-rw-r--r--docs/cmdline-opts/proto-redir.md28
-rw-r--r--docs/cmdline-opts/proto.d48
-rw-r--r--docs/cmdline-opts/proto.md48
-rw-r--r--docs/cmdline-opts/proxy-anyauth.d12
-rw-r--r--docs/cmdline-opts/proxy-anyauth.md20
-rw-r--r--docs/cmdline-opts/proxy-basic.d13
-rw-r--r--docs/cmdline-opts/proxy-basic.md21
-rw-r--r--docs/cmdline-opts/proxy-ca-native.d21
-rw-r--r--docs/cmdline-opts/proxy-ca-native.md28
-rw-r--r--docs/cmdline-opts/proxy-cacert.d12
-rw-r--r--docs/cmdline-opts/proxy-cacert.md21
-rw-r--r--docs/cmdline-opts/proxy-capath.d12
-rw-r--r--docs/cmdline-opts/proxy-capath.md20
-rw-r--r--docs/cmdline-opts/proxy-cert-type.d12
-rw-r--r--docs/cmdline-opts/proxy-cert-type.md18
-rw-r--r--docs/cmdline-opts/proxy-cert.d12
-rw-r--r--docs/cmdline-opts/proxy-cert.md18
-rw-r--r--docs/cmdline-opts/proxy-ciphers.d18
-rw-r--r--docs/cmdline-opts/proxy-ciphers.md26
-rw-r--r--docs/cmdline-opts/proxy-crlfile.d12
-rw-r--r--docs/cmdline-opts/proxy-crlfile.md19
-rw-r--r--docs/cmdline-opts/proxy-digest.d12
-rw-r--r--docs/cmdline-opts/proxy-digest.md20
-rw-r--r--docs/cmdline-opts/proxy-header.d32
-rw-r--r--docs/cmdline-opts/proxy-header.md38
-rw-r--r--docs/cmdline-opts/proxy-http2.d18
-rw-r--r--docs/cmdline-opts/proxy-http2.md24
-rw-r--r--docs/cmdline-opts/proxy-insecure.d11
-rw-r--r--docs/cmdline-opts/proxy-insecure.md18
-rw-r--r--docs/cmdline-opts/proxy-key-type.d12
-rw-r--r--docs/cmdline-opts/proxy-key-type.md19
-rw-r--r--docs/cmdline-opts/proxy-key.d12
-rw-r--r--docs/cmdline-opts/proxy-key.md19
-rw-r--r--docs/cmdline-opts/proxy-negotiate.d13
-rw-r--r--docs/cmdline-opts/proxy-negotiate.md20
-rw-r--r--docs/cmdline-opts/proxy-ntlm.d12
-rw-r--r--docs/cmdline-opts/proxy-ntlm.md19
-rw-r--r--docs/cmdline-opts/proxy-pass.d12
-rw-r--r--docs/cmdline-opts/proxy-pass.md19
-rw-r--r--docs/cmdline-opts/proxy-pinnedpubkey.d22
-rw-r--r--docs/cmdline-opts/proxy-pinnedpubkey.md29
-rw-r--r--docs/cmdline-opts/proxy-service-name.d12
-rw-r--r--docs/cmdline-opts/proxy-service-name.md19
-rw-r--r--docs/cmdline-opts/proxy-ssl-allow-beast.d11
-rw-r--r--docs/cmdline-opts/proxy-ssl-allow-beast.md18
-rw-r--r--docs/cmdline-opts/proxy-ssl-auto-client-cert.d11
-rw-r--r--docs/cmdline-opts/proxy-ssl-auto-client-cert.md18
-rw-r--r--docs/cmdline-opts/proxy-tls13-ciphers.d21
-rw-r--r--docs/cmdline-opts/proxy-tls13-ciphers.md29
-rw-r--r--docs/cmdline-opts/proxy-tlsauthtype.d12
-rw-r--r--docs/cmdline-opts/proxy-tlsauthtype.md19
-rw-r--r--docs/cmdline-opts/proxy-tlspassword.d12
-rw-r--r--docs/cmdline-opts/proxy-tlspassword.md19
-rw-r--r--docs/cmdline-opts/proxy-tlsuser.d12
-rw-r--r--docs/cmdline-opts/proxy-tlsuser.md19
-rw-r--r--docs/cmdline-opts/proxy-tlsv1.d11
-rw-r--r--docs/cmdline-opts/proxy-tlsv1.md17
-rw-r--r--docs/cmdline-opts/proxy-user.d23
-rw-r--r--docs/cmdline-opts/proxy-user.md29
-rw-r--r--docs/cmdline-opts/proxy.d51
-rw-r--r--docs/cmdline-opts/proxy.md58
-rw-r--r--docs/cmdline-opts/proxy1.0.d17
-rw-r--r--docs/cmdline-opts/proxy1.0.md25
-rw-r--r--docs/cmdline-opts/proxytunnel.d18
-rw-r--r--docs/cmdline-opts/proxytunnel.md24
-rw-r--r--docs/cmdline-opts/pubkey.d19
-rw-r--r--docs/cmdline-opts/pubkey.md25
-rw-r--r--docs/cmdline-opts/quote.d87
-rw-r--r--docs/cmdline-opts/quote.md90
-rw-r--r--docs/cmdline-opts/random-file.d16
-rw-r--r--docs/cmdline-opts/random-file.md22
-rw-r--r--docs/cmdline-opts/range.d50
-rw-r--r--docs/cmdline-opts/range.md57
-rw-r--r--docs/cmdline-opts/rate.d35
-rw-r--r--docs/cmdline-opts/rate.md42
-rw-r--r--docs/cmdline-opts/raw.d13
-rw-r--r--docs/cmdline-opts/raw.md19
-rw-r--r--docs/cmdline-opts/referer.d20
-rw-r--r--docs/cmdline-opts/referer.md27
-rw-r--r--docs/cmdline-opts/remote-header-name.d34
-rw-r--r--docs/cmdline-opts/remote-header-name.md40
-rw-r--r--docs/cmdline-opts/remote-name-all.d14
-rw-r--r--docs/cmdline-opts/remote-name-all.md20
-rw-r--r--docs/cmdline-opts/remote-name.d28
-rw-r--r--docs/cmdline-opts/remote-name.md36
-rw-r--r--docs/cmdline-opts/remote-time.d14
-rw-r--r--docs/cmdline-opts/remote-time.md21
-rw-r--r--docs/cmdline-opts/remove-on-error.d15
-rw-r--r--docs/cmdline-opts/remove-on-error.md21
-rw-r--r--docs/cmdline-opts/request-target.d16
-rw-r--r--docs/cmdline-opts/request-target.md25
-rw-r--r--docs/cmdline-opts/request.d51
-rw-r--r--docs/cmdline-opts/request.md57
-rw-r--r--docs/cmdline-opts/resolve.d41
-rw-r--r--docs/cmdline-opts/resolve.md46
-rw-r--r--docs/cmdline-opts/retry-all-errors.d34
-rw-r--r--docs/cmdline-opts/retry-all-errors.md40
-rw-r--r--docs/cmdline-opts/retry-connrefused.d12
-rw-r--r--docs/cmdline-opts/retry-connrefused.md19
-rw-r--r--docs/cmdline-opts/retry-delay.d15
-rw-r--r--docs/cmdline-opts/retry-delay.md21
-rw-r--r--docs/cmdline-opts/retry-max-time.d17
-rw-r--r--docs/cmdline-opts/retry-max-time.md23
-rw-r--r--docs/cmdline-opts/retry.d25
-rw-r--r--docs/cmdline-opts/retry.md31
-rw-r--r--docs/cmdline-opts/sasl-authzid.d19
-rw-r--r--docs/cmdline-opts/sasl-authzid.md25
-rw-r--r--docs/cmdline-opts/sasl-ir.d11
-rw-r--r--docs/cmdline-opts/sasl-ir.md17
-rw-r--r--docs/cmdline-opts/service-name.d12
-rw-r--r--docs/cmdline-opts/service-name.md19
-rw-r--r--docs/cmdline-opts/show-error.d13
-rw-r--r--docs/cmdline-opts/show-error.md19
-rw-r--r--docs/cmdline-opts/silent.d17
-rw-r--r--docs/cmdline-opts/silent.md25
-rw-r--r--docs/cmdline-opts/socks4.d28
-rw-r--r--docs/cmdline-opts/socks4.md36
-rw-r--r--docs/cmdline-opts/socks4a.d27
-rw-r--r--docs/cmdline-opts/socks4a.md35
-rw-r--r--docs/cmdline-opts/socks5-basic.d13
-rw-r--r--docs/cmdline-opts/socks5-basic.md19
-rw-r--r--docs/cmdline-opts/socks5-gssapi-nec.d14
-rw-r--r--docs/cmdline-opts/socks5-gssapi-nec.md20
-rw-r--r--docs/cmdline-opts/socks5-gssapi-service.d13
-rw-r--r--docs/cmdline-opts/socks5-gssapi-service.md19
-rw-r--r--docs/cmdline-opts/socks5-gssapi.d14
-rw-r--r--docs/cmdline-opts/socks5-gssapi.md20
-rw-r--r--docs/cmdline-opts/socks5-hostname.d27
-rw-r--r--docs/cmdline-opts/socks5-hostname.md34
-rw-r--r--docs/cmdline-opts/socks5.d29
-rw-r--r--docs/cmdline-opts/socks5.md36
-rw-r--r--docs/cmdline-opts/speed-limit.d15
-rw-r--r--docs/cmdline-opts/speed-limit.md23
-rw-r--r--docs/cmdline-opts/speed-time.d18
-rw-r--r--docs/cmdline-opts/speed-time.md25
-rw-r--r--docs/cmdline-opts/ssl-allow-beast.d17
-rw-r--r--docs/cmdline-opts/ssl-allow-beast.md25
-rw-r--r--docs/cmdline-opts/ssl-auto-client-cert.d14
-rw-r--r--docs/cmdline-opts/ssl-auto-client-cert.md21
-rw-r--r--docs/cmdline-opts/ssl-no-revoke.d13
-rw-r--r--docs/cmdline-opts/ssl-no-revoke.md20
-rw-r--r--docs/cmdline-opts/ssl-reqd.d23
-rw-r--r--docs/cmdline-opts/ssl-reqd.md30
-rw-r--r--docs/cmdline-opts/ssl-revoke-best-effort.d13
-rw-r--r--docs/cmdline-opts/ssl-revoke-best-effort.md21
-rw-r--r--docs/cmdline-opts/ssl.d26
-rw-r--r--docs/cmdline-opts/ssl.md34
-rw-r--r--docs/cmdline-opts/sslv2.d17
-rw-r--r--docs/cmdline-opts/sslv2.md24
-rw-r--r--docs/cmdline-opts/sslv3.d17
-rw-r--r--docs/cmdline-opts/sslv3.md24
-rw-r--r--docs/cmdline-opts/stderr.d14
-rw-r--r--docs/cmdline-opts/stderr.md21
-rw-r--r--docs/cmdline-opts/styled-output.d16
-rw-r--r--docs/cmdline-opts/styled-output.md23
-rw-r--r--docs/cmdline-opts/suppress-connect-headers.d14
-rw-r--r--docs/cmdline-opts/suppress-connect-headers.md22
-rw-r--r--docs/cmdline-opts/tcp-fastopen.d14
-rw-r--r--docs/cmdline-opts/tcp-fastopen.md19
-rw-r--r--docs/cmdline-opts/tcp-nodelay.d15
-rw-r--r--docs/cmdline-opts/tcp-nodelay.md21
-rw-r--r--docs/cmdline-opts/telnet-option.d23
-rw-r--r--docs/cmdline-opts/telnet-option.md28
-rw-r--r--docs/cmdline-opts/tftp-blksize.d15
-rw-r--r--docs/cmdline-opts/tftp-blksize.md21
-rw-r--r--docs/cmdline-opts/tftp-no-options.d16
-rw-r--r--docs/cmdline-opts/tftp-no-options.md22
-rw-r--r--docs/cmdline-opts/time-cond.d27
-rw-r--r--docs/cmdline-opts/time-cond.md34
-rw-r--r--docs/cmdline-opts/tls-max.d34
-rw-r--r--docs/cmdline-opts/tls-max.md44
-rw-r--r--docs/cmdline-opts/tls13-ciphers.d21
-rw-r--r--docs/cmdline-opts/tls13-ciphers.md29
-rw-r--r--docs/cmdline-opts/tlsauthtype.d16
-rw-r--r--docs/cmdline-opts/tlsauthtype.md23
-rw-r--r--docs/cmdline-opts/tlspassword.d15
-rw-r--r--docs/cmdline-opts/tlspassword.md22
-rw-r--r--docs/cmdline-opts/tlsuser.d15
-rw-r--r--docs/cmdline-opts/tlsuser.md22
-rw-r--r--docs/cmdline-opts/tlsv1.0.d16
-rw-r--r--docs/cmdline-opts/tlsv1.0.md22
-rw-r--r--docs/cmdline-opts/tlsv1.1.d16
-rw-r--r--docs/cmdline-opts/tlsv1.1.md23
-rw-r--r--docs/cmdline-opts/tlsv1.2.d16
-rw-r--r--docs/cmdline-opts/tlsv1.2.md23
-rw-r--r--docs/cmdline-opts/tlsv1.3.d18
-rw-r--r--docs/cmdline-opts/tlsv1.3.md25
-rw-r--r--docs/cmdline-opts/tlsv1.d17
-rw-r--r--docs/cmdline-opts/tlsv1.md24
-rw-r--r--docs/cmdline-opts/tr-encoding.d13
-rw-r--r--docs/cmdline-opts/tr-encoding.md19
-rw-r--r--docs/cmdline-opts/trace-ascii.d24
-rw-r--r--docs/cmdline-opts/trace-ascii.md31
-rw-r--r--docs/cmdline-opts/trace-config.d21
-rw-r--r--docs/cmdline-opts/trace-config.md28
-rw-r--r--docs/cmdline-opts/trace-ids.d12
-rw-r--r--docs/cmdline-opts/trace-ids.md19
-rw-r--r--docs/cmdline-opts/trace-time.d12
-rw-r--r--docs/cmdline-opts/trace-time.md19
-rw-r--r--docs/cmdline-opts/trace.d21
-rw-r--r--docs/cmdline-opts/trace.md30
-rw-r--r--docs/cmdline-opts/unix-socket.d13
-rw-r--r--docs/cmdline-opts/unix-socket.md19
-rw-r--r--docs/cmdline-opts/upload-file.d43
-rw-r--r--docs/cmdline-opts/upload-file.md52
-rw-r--r--docs/cmdline-opts/url-query.d25
-rw-r--r--docs/cmdline-opts/url-query.md32
-rw-r--r--docs/cmdline-opts/url.d26
-rw-r--r--docs/cmdline-opts/url.md33
-rw-r--r--docs/cmdline-opts/use-ascii.d15
-rw-r--r--docs/cmdline-opts/use-ascii.md22
-rw-r--r--docs/cmdline-opts/user-agent.d20
-rw-r--r--docs/cmdline-opts/user-agent.md27
-rw-r--r--docs/cmdline-opts/user.d44
-rw-r--r--docs/cmdline-opts/user.md51
-rw-r--r--docs/cmdline-opts/variable.d55
-rw-r--r--docs/cmdline-opts/variable.md58
-rw-r--r--docs/cmdline-opts/verbose.d28
-rw-r--r--docs/cmdline-opts/verbose.md37
-rw-r--r--docs/cmdline-opts/version.d88
-rw-r--r--docs/cmdline-opts/version.md120
-rw-r--r--docs/cmdline-opts/write-out.d292
-rw-r--r--docs/cmdline-opts/write-out.md296
-rw-r--r--docs/cmdline-opts/xattr.d15
-rw-r--r--docs/cmdline-opts/xattr.md23
-rw-r--r--docs/curl-config.1105
-rw-r--r--docs/curl-config.md124
-rw-r--r--docs/examples/10-at-a-time.c4
-rw-r--r--docs/examples/Makefile.inc7
-rw-r--r--docs/examples/Makefile.mk26
-rw-r--r--docs/examples/address-scope.c62
-rw-r--r--docs/examples/anyauthput.c14
-rw-r--r--docs/examples/chkspeed.c8
-rw-r--r--docs/examples/cookie_interface.c2
-rw-r--r--docs/examples/debug.c5
-rw-r--r--docs/examples/externalsocket.c8
-rw-r--r--docs/examples/ftpget.c2
-rw-r--r--docs/examples/ftpsget.c2
-rw-r--r--docs/examples/ftpupload.c2
-rw-r--r--docs/examples/http2-download.c9
-rw-r--r--docs/examples/http2-serverpush.c5
-rw-r--r--docs/examples/http2-upload.c5
-rw-r--r--docs/examples/interface.c52
-rw-r--r--docs/examples/ipv6.c26
-rw-r--r--docs/examples/keepalive.c55
-rw-r--r--docs/examples/localport.c53
-rw-r--r--docs/examples/multi-debugcallback.c5
-rw-r--r--docs/examples/netrc.c49
-rw-r--r--docs/examples/range.c45
-rw-r--r--docs/examples/rtsp-options.c55
-rw-r--r--docs/examples/sendrecv.c11
-rw-r--r--docs/examples/sftpget.c2
-rw-r--r--docs/examples/synctime.c6
-rw-r--r--docs/libcurl/.gitignore5
-rw-r--r--docs/libcurl/CMakeLists.txt49
-rw-r--r--docs/libcurl/Makefile.am54
-rw-r--r--docs/libcurl/curl_easy_cleanup.377
-rw-r--r--docs/libcurl/curl_easy_cleanup.md76
-rw-r--r--docs/libcurl/curl_easy_duphandle.372
-rw-r--r--docs/libcurl/curl_easy_duphandle.md72
-rw-r--r--docs/libcurl/curl_easy_escape.376
-rw-r--r--docs/libcurl/curl_easy_escape.md75
-rw-r--r--docs/libcurl/curl_easy_getinfo.3325
-rw-r--r--docs/libcurl/curl_easy_getinfo.md483
-rw-r--r--docs/libcurl/curl_easy_header.3142
-rw-r--r--docs/libcurl/curl_easy_header.md160
-rw-r--r--docs/libcurl/curl_easy_init.379
-rw-r--r--docs/libcurl/curl_easy_init.md73
-rw-r--r--docs/libcurl/curl_easy_nextheader.397
-rw-r--r--docs/libcurl/curl_easy_nextheader.md100
-rw-r--r--docs/libcurl/curl_easy_option_by_id.356
-rw-r--r--docs/libcurl/curl_easy_option_by_id.md54
-rw-r--r--docs/libcurl/curl_easy_option_by_name.355
-rw-r--r--docs/libcurl/curl_easy_option_by_name.md53
-rw-r--r--docs/libcurl/curl_easy_option_next.387
-rw-r--r--docs/libcurl/curl_easy_option_next.md89
-rw-r--r--docs/libcurl/curl_easy_pause.3124
-rw-r--r--docs/libcurl/curl_easy_pause.md140
-rw-r--r--docs/libcurl/curl_easy_perform.387
-rw-r--r--docs/libcurl/curl_easy_perform.md83
-rw-r--r--docs/libcurl/curl_easy_recv.398
-rw-r--r--docs/libcurl/curl_easy_recv.md103
-rw-r--r--docs/libcurl/curl_easy_reset.357
-rw-r--r--docs/libcurl/curl_easy_reset.md56
-rw-r--r--docs/libcurl/curl_easy_send.392
-rw-r--r--docs/libcurl/curl_easy_send.md95
-rw-r--r--docs/libcurl/curl_easy_setopt.3746
-rw-r--r--docs/libcurl/curl_easy_setopt.md1381
-rw-r--r--docs/libcurl/curl_easy_strerror.356
-rw-r--r--docs/libcurl/curl_easy_strerror.md59
-rw-r--r--docs/libcurl/curl_easy_unescape.376
-rw-r--r--docs/libcurl/curl_easy_unescape.md73
-rw-r--r--docs/libcurl/curl_easy_upkeep.381
-rw-r--r--docs/libcurl/curl_easy_upkeep.md77
-rw-r--r--docs/libcurl/curl_escape.360
-rw-r--r--docs/libcurl/curl_escape.md58
-rw-r--r--docs/libcurl/curl_formadd.3268
-rw-r--r--docs/libcurl/curl_formadd.md313
-rw-r--r--docs/libcurl/curl_formfree.372
-rw-r--r--docs/libcurl/curl_formfree.md76
-rw-r--r--docs/libcurl/curl_formget.374
-rw-r--r--docs/libcurl/curl_formget.md72
-rw-r--r--docs/libcurl/curl_free.354
-rw-r--r--docs/libcurl/curl_free.md52
-rw-r--r--docs/libcurl/curl_getdate.3122
-rw-r--r--docs/libcurl/curl_getdate.md128
-rw-r--r--docs/libcurl/curl_getenv.357
-rw-r--r--docs/libcurl/curl_getenv.md57
-rw-r--r--docs/libcurl/curl_global_cleanup.374
-rw-r--r--docs/libcurl/curl_global_cleanup.md74
-rw-r--r--docs/libcurl/curl_global_init.3121
-rw-r--r--docs/libcurl/curl_global_init.md131
-rw-r--r--docs/libcurl/curl_global_init_mem.379
-rw-r--r--docs/libcurl/curl_global_init_mem.md95
-rw-r--r--docs/libcurl/curl_global_sslset.3133
-rw-r--r--docs/libcurl/curl_global_sslset.md138
-rw-r--r--docs/libcurl/curl_global_trace.3118
-rw-r--r--docs/libcurl/curl_global_trace.md124
-rw-r--r--docs/libcurl/curl_mime_addpart.369
-rw-r--r--docs/libcurl/curl_mime_addpart.md70
-rw-r--r--docs/libcurl/curl_mime_data.375
-rw-r--r--docs/libcurl/curl_mime_data.md76
-rw-r--r--docs/libcurl/curl_mime_data_cb.3168
-rw-r--r--docs/libcurl/curl_mime_data_cb.md168
-rw-r--r--docs/libcurl/curl_mime_encoder.399
-rw-r--r--docs/libcurl/curl_mime_encoder.md100
-rw-r--r--docs/libcurl/curl_mime_filedata.387
-rw-r--r--docs/libcurl/curl_mime_filedata.md88
-rw-r--r--docs/libcurl/curl_mime_filename.375
-rw-r--r--docs/libcurl/curl_mime_filename.md79
-rw-r--r--docs/libcurl/curl_mime_free.364
-rw-r--r--docs/libcurl/curl_mime_free.md65
-rw-r--r--docs/libcurl/curl_mime_headers.370
-rw-r--r--docs/libcurl/curl_mime_headers.md78
-rw-r--r--docs/libcurl/curl_mime_init.373
-rw-r--r--docs/libcurl/curl_mime_init.md72
-rw-r--r--docs/libcurl/curl_mime_name.366
-rw-r--r--docs/libcurl/curl_mime_name.md67
-rw-r--r--docs/libcurl/curl_mime_subparts.375
-rw-r--r--docs/libcurl/curl_mime_subparts.md83
-rw-r--r--docs/libcurl/curl_mime_type.385
-rw-r--r--docs/libcurl/curl_mime_type.md86
-rw-r--r--docs/libcurl/curl_mprintf.3254
-rw-r--r--docs/libcurl/curl_mprintf.md288
-rw-r--r--docs/libcurl/curl_multi_add_handle.386
-rw-r--r--docs/libcurl/curl_multi_add_handle.md88
-rw-r--r--docs/libcurl/curl_multi_assign.375
-rw-r--r--docs/libcurl/curl_multi_assign.md81
-rw-r--r--docs/libcurl/curl_multi_cleanup.366
-rw-r--r--docs/libcurl/curl_multi_cleanup.md65
-rw-r--r--docs/libcurl/curl_multi_fdset.3105
-rw-r--r--docs/libcurl/curl_multi_fdset.md119
-rw-r--r--docs/libcurl/curl_multi_get_handles.375
-rw-r--r--docs/libcurl/curl_multi_get_handles.md77
-rw-r--r--docs/libcurl/curl_multi_info_read.3100
-rw-r--r--docs/libcurl/curl_multi_info_read.md102
-rw-r--r--docs/libcurl/curl_multi_init.358
-rw-r--r--docs/libcurl/curl_multi_init.md57
-rw-r--r--docs/libcurl/curl_multi_perform.3102
-rw-r--r--docs/libcurl/curl_multi_perform.md107
-rw-r--r--docs/libcurl/curl_multi_poll.3121
-rw-r--r--docs/libcurl/curl_multi_poll.md128
-rw-r--r--docs/libcurl/curl_multi_remove_handle.372
-rw-r--r--docs/libcurl/curl_multi_remove_handle.md73
-rw-r--r--docs/libcurl/curl_multi_setopt.391
-rw-r--r--docs/libcurl/curl_multi_setopt.md125
-rw-r--r--docs/libcurl/curl_multi_socket.394
-rw-r--r--docs/libcurl/curl_multi_socket.md95
-rw-r--r--docs/libcurl/curl_multi_socket_action.3116
-rw-r--r--docs/libcurl/curl_multi_socket_action.md120
-rw-r--r--docs/libcurl/curl_multi_socket_all.31
-rw-r--r--docs/libcurl/curl_multi_socket_all.md95
-rw-r--r--docs/libcurl/curl_multi_strerror.350
-rw-r--r--docs/libcurl/curl_multi_strerror.md51
-rw-r--r--docs/libcurl/curl_multi_timeout.385
-rw-r--r--docs/libcurl/curl_multi_timeout.md89
-rw-r--r--docs/libcurl/curl_multi_wait.3128
-rw-r--r--docs/libcurl/curl_multi_wait.md121
-rw-r--r--docs/libcurl/curl_multi_wakeup.389
-rw-r--r--docs/libcurl/curl_multi_wakeup.md91
-rw-r--r--docs/libcurl/curl_pushheader_byname.381
-rw-r--r--docs/libcurl/curl_pushheader_byname.md82
-rw-r--r--docs/libcurl/curl_pushheader_bynum.371
-rw-r--r--docs/libcurl/curl_pushheader_bynum.md69
-rw-r--r--docs/libcurl/curl_share_cleanup.356
-rw-r--r--docs/libcurl/curl_share_cleanup.md54
-rw-r--r--docs/libcurl/curl_share_init.358
-rw-r--r--docs/libcurl/curl_share_init.md56
-rw-r--r--docs/libcurl/curl_share_setopt.362
-rw-r--r--docs/libcurl/curl_share_setopt.md71
-rw-r--r--docs/libcurl/curl_share_strerror.350
-rw-r--r--docs/libcurl/curl_share_strerror.md50
-rw-r--r--docs/libcurl/curl_slist_append.377
-rw-r--r--docs/libcurl/curl_slist_append.md75
-rw-r--r--docs/libcurl/curl_slist_free_all.360
-rw-r--r--docs/libcurl/curl_slist_free_all.md58
-rw-r--r--docs/libcurl/curl_strequal.359
-rw-r--r--docs/libcurl/curl_strequal.md57
-rw-r--r--docs/libcurl/curl_strnequal.31
-rw-r--r--docs/libcurl/curl_strnequal.md57
-rw-r--r--docs/libcurl/curl_unescape.368
-rw-r--r--docs/libcurl/curl_unescape.md65
-rw-r--r--docs/libcurl/curl_url.366
-rw-r--r--docs/libcurl/curl_url.md64
-rw-r--r--docs/libcurl/curl_url_cleanup.353
-rw-r--r--docs/libcurl/curl_url_cleanup.md51
-rw-r--r--docs/libcurl/curl_url_dup.358
-rw-r--r--docs/libcurl/curl_url_dup.md56
-rw-r--r--docs/libcurl/curl_url_get.3175
-rw-r--r--docs/libcurl/curl_url_get.md210
-rw-r--r--docs/libcurl/curl_url_set.3209
-rw-r--r--docs/libcurl/curl_url_set.md247
-rw-r--r--docs/libcurl/curl_url_strerror.354
-rw-r--r--docs/libcurl/curl_url_strerror.md53
-rw-r--r--docs/libcurl/curl_version.349
-rw-r--r--docs/libcurl/curl_version.md46
-rw-r--r--docs/libcurl/curl_version_info.3320
-rw-r--r--docs/libcurl/curl_version_info.md381
-rw-r--r--docs/libcurl/curl_ws_meta.3121
-rw-r--r--docs/libcurl/curl_ws_meta.md143
-rw-r--r--docs/libcurl/curl_ws_recv.371
-rw-r--r--docs/libcurl/curl_ws_recv.md73
-rw-r--r--docs/libcurl/curl_ws_send.3102
-rw-r--r--docs/libcurl/curl_ws_send.md120
-rw-r--r--docs/libcurl/libcurl-easy.365
-rw-r--r--docs/libcurl/libcurl-easy.md52
-rw-r--r--docs/libcurl/libcurl-env-dbg.397
-rw-r--r--docs/libcurl/libcurl-env-dbg.md118
-rw-r--r--docs/libcurl/libcurl-env.392
-rw-r--r--docs/libcurl/libcurl-env.md99
-rw-r--r--docs/libcurl/libcurl-errors.3441
-rw-r--r--docs/libcurl/libcurl-errors.md757
-rw-r--r--docs/libcurl/libcurl-multi.3184
-rw-r--r--docs/libcurl/libcurl-multi.md178
-rw-r--r--docs/libcurl/libcurl-security.3426
-rw-r--r--docs/libcurl/libcurl-security.md487
-rw-r--r--docs/libcurl/libcurl-share.371
-rw-r--r--docs/libcurl/libcurl-share.md62
-rw-r--r--docs/libcurl/libcurl-thread.3123
-rw-r--r--docs/libcurl/libcurl-thread.md99
-rw-r--r--docs/libcurl/libcurl-tutorial.31398
-rw-r--r--docs/libcurl/libcurl-tutorial.md1451
-rw-r--r--docs/libcurl/libcurl-url.3151
-rw-r--r--docs/libcurl/libcurl-url.md162
-rw-r--r--docs/libcurl/libcurl-ws.3118
-rw-r--r--docs/libcurl/libcurl-ws.md123
-rw-r--r--docs/libcurl/libcurl.3228
-rw-r--r--docs/libcurl/libcurl.md247
-rwxr-xr-xdocs/libcurl/mksymbolsmanpage.pl286
-rw-r--r--docs/libcurl/opts/CMakeLists.txt13
-rw-r--r--docs/libcurl/opts/CURLINFO_ACTIVESOCKET.377
-rw-r--r--docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md77
-rw-r--r--docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.371
-rw-r--r--docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md71
-rw-r--r--docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.373
-rw-r--r--docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md73
-rw-r--r--docs/libcurl/opts/CURLINFO_CAINFO.368
-rw-r--r--docs/libcurl/opts/CURLINFO_CAINFO.md66
-rw-r--r--docs/libcurl/opts/CURLINFO_CAPATH.368
-rw-r--r--docs/libcurl/opts/CURLINFO_CAPATH.md66
-rw-r--r--docs/libcurl/opts/CURLINFO_CERTINFO.3100
-rw-r--r--docs/libcurl/opts/CURLINFO_CERTINFO.md101
-rw-r--r--docs/libcurl/opts/CURLINFO_CONDITION_UNMET.379
-rw-r--r--docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md80
-rw-r--r--docs/libcurl/opts/CURLINFO_CONNECT_TIME.367
-rw-r--r--docs/libcurl/opts/CURLINFO_CONNECT_TIME.md67
-rw-r--r--docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.370
-rw-r--r--docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md70
-rw-r--r--docs/libcurl/opts/CURLINFO_CONN_ID.370
-rw-r--r--docs/libcurl/opts/CURLINFO_CONN_ID.md70
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.370
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md70
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.367
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md67
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.369
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md69
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.366
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md66
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_TYPE.375
-rw-r--r--docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md75
-rw-r--r--docs/libcurl/opts/CURLINFO_COOKIELIST.382
-rw-r--r--docs/libcurl/opts/CURLINFO_COOKIELIST.md82
-rw-r--r--docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.373
-rw-r--r--docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md72
-rw-r--r--docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.369
-rw-r--r--docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md68
-rw-r--r--docs/libcurl/opts/CURLINFO_FILETIME.375
-rw-r--r--docs/libcurl/opts/CURLINFO_FILETIME.md76
-rw-r--r--docs/libcurl/opts/CURLINFO_FILETIME_T.378
-rw-r--r--docs/libcurl/opts/CURLINFO_FILETIME_T.md78
-rw-r--r--docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.370
-rw-r--r--docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md70
-rw-r--r--docs/libcurl/opts/CURLINFO_HEADER_SIZE.366
-rw-r--r--docs/libcurl/opts/CURLINFO_HEADER_SIZE.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.377
-rw-r--r--docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md77
-rw-r--r--docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.366
-rw-r--r--docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_HTTP_VERSION.362
-rw-r--r--docs/libcurl/opts/CURLINFO_HTTP_VERSION.md61
-rw-r--r--docs/libcurl/opts/CURLINFO_LASTSOCKET.377
-rw-r--r--docs/libcurl/opts/CURLINFO_LASTSOCKET.md77
-rw-r--r--docs/libcurl/opts/CURLINFO_LOCAL_IP.373
-rw-r--r--docs/libcurl/opts/CURLINFO_LOCAL_IP.md72
-rw-r--r--docs/libcurl/opts/CURLINFO_LOCAL_PORT.371
-rw-r--r--docs/libcurl/opts/CURLINFO_LOCAL_PORT.md68
-rw-r--r--docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.368
-rw-r--r--docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md68
-rw-r--r--docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.369
-rw-r--r--docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md69
-rw-r--r--docs/libcurl/opts/CURLINFO_NUM_CONNECTS.366
-rw-r--r--docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_OS_ERRNO.363
-rw-r--r--docs/libcurl/opts/CURLINFO_OS_ERRNO.md62
-rw-r--r--docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.373
-rw-r--r--docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md73
-rw-r--r--docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.374
-rw-r--r--docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md75
-rw-r--r--docs/libcurl/opts/CURLINFO_PRIMARY_IP.374
-rw-r--r--docs/libcurl/opts/CURLINFO_PRIMARY_IP.md73
-rw-r--r--docs/libcurl/opts/CURLINFO_PRIMARY_PORT.368
-rw-r--r--docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md67
-rw-r--r--docs/libcurl/opts/CURLINFO_PRIVATE.365
-rw-r--r--docs/libcurl/opts/CURLINFO_PRIVATE.md68
-rw-r--r--docs/libcurl/opts/CURLINFO_PROTOCOL.373
-rw-r--r--docs/libcurl/opts/CURLINFO_PROTOCOL.md73
-rw-r--r--docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.378
-rw-r--r--docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md78
-rw-r--r--docs/libcurl/opts/CURLINFO_PROXY_ERROR.3106
-rw-r--r--docs/libcurl/opts/CURLINFO_PROXY_ERROR.md105
-rw-r--r--docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.363
-rw-r--r--docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md64
-rw-r--r--docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md70
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.363
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md62
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_TIME.370
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md70
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.372
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md72
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_URL.370
-rw-r--r--docs/libcurl/opts/CURLINFO_REDIRECT_URL.md69
-rw-r--r--docs/libcurl/opts/CURLINFO_REFERER.367
-rw-r--r--docs/libcurl/opts/CURLINFO_REFERER.md67
-rw-r--r--docs/libcurl/opts/CURLINFO_REQUEST_SIZE.364
-rw-r--r--docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md63
-rw-r--r--docs/libcurl/opts/CURLINFO_RESPONSE_CODE.366
-rw-r--r--docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_RETRY_AFTER.370
-rw-r--r--docs/libcurl/opts/CURLINFO_RETRY_AFTER.md71
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.362
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md61
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.362
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md61
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.366
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.367
-rw-r--r--docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md66
-rw-r--r--docs/libcurl/opts/CURLINFO_SCHEME.369
-rw-r--r--docs/libcurl/opts/CURLINFO_SCHEME.md68
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.373
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md73
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.370
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md70
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.369
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md69
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.367
-rw-r--r--docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md66
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.368
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md67
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.366
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.366
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.364
-rw-r--r--docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md63
-rw-r--r--docs/libcurl/opts/CURLINFO_SSL_ENGINES.366
-rw-r--r--docs/libcurl/opts/CURLINFO_SSL_ENGINES.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.364
-rw-r--r--docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md65
-rw-r--r--docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.371
-rw-r--r--docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md71
-rw-r--r--docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.373
-rw-r--r--docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md73
-rw-r--r--docs/libcurl/opts/CURLINFO_TLS_SESSION.373
-rw-r--r--docs/libcurl/opts/CURLINFO_TLS_SESSION.md75
-rw-r--r--docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3165
-rw-r--r--docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md174
-rw-r--r--docs/libcurl/opts/CURLINFO_TOTAL_TIME.369
-rw-r--r--docs/libcurl/opts/CURLINFO_TOTAL_TIME.md69
-rw-r--r--docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.371
-rw-r--r--docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md71
-rw-r--r--docs/libcurl/opts/CURLINFO_XFER_ID.371
-rw-r--r--docs/libcurl/opts/CURLINFO_XFER_ID.md70
-rw-r--r--docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.360
-rw-r--r--docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md61
-rw-r--r--docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.359
-rw-r--r--docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md60
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAXCONNECTS.369
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAXCONNECTS.md69
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.358
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.md59
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.371
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.md72
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.363
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.md64
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.369
-rw-r--r--docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.md70
-rw-r--r--docs/libcurl/opts/CURLMOPT_PIPELINING.371
-rw-r--r--docs/libcurl/opts/CURLMOPT_PIPELINING.md77
-rw-r--r--docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.368
-rw-r--r--docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.md68
-rw-r--r--docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.364
-rw-r--r--docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.md66
-rw-r--r--docs/libcurl/opts/CURLMOPT_PUSHDATA.382
-rw-r--r--docs/libcurl/opts/CURLMOPT_PUSHDATA.md87
-rw-r--r--docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3132
-rw-r--r--docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.md148
-rw-r--r--docs/libcurl/opts/CURLMOPT_SOCKETDATA.379
-rw-r--r--docs/libcurl/opts/CURLMOPT_SOCKETDATA.md82
-rw-r--r--docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3122
-rw-r--r--docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md135
-rw-r--r--docs/libcurl/opts/CURLMOPT_TIMERDATA.385
-rw-r--r--docs/libcurl/opts/CURLMOPT_TIMERDATA.md75
-rw-r--r--docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3113
-rw-r--r--docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.md103
-rw-r--r--docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.365
-rw-r--r--docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.360
-rw-r--r--docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.md61
-rw-r--r--docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3109
-rw-r--r--docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md110
-rw-r--r--docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.360
-rw-r--r--docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md63
-rw-r--r--docs/libcurl/opts/CURLOPT_ALTSVC.391
-rw-r--r--docs/libcurl/opts/CURLOPT_ALTSVC.md111
-rw-r--r--docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.388
-rw-r--r--docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.md97
-rw-r--r--docs/libcurl/opts/CURLOPT_APPEND.360
-rw-r--r--docs/libcurl/opts/CURLOPT_APPEND.md61
-rw-r--r--docs/libcurl/opts/CURLOPT_AUTOREFERER.371
-rw-r--r--docs/libcurl/opts/CURLOPT_AUTOREFERER.md77
-rw-r--r--docs/libcurl/opts/CURLOPT_AWS_SIGV4.3108
-rw-r--r--docs/libcurl/opts/CURLOPT_AWS_SIGV4.md118
-rw-r--r--docs/libcurl/opts/CURLOPT_BUFFERSIZE.378
-rw-r--r--docs/libcurl/opts/CURLOPT_BUFFERSIZE.md79
-rw-r--r--docs/libcurl/opts/CURLOPT_CAINFO.386
-rw-r--r--docs/libcurl/opts/CURLOPT_CAINFO.md87
-rw-r--r--docs/libcurl/opts/CURLOPT_CAINFO_BLOB.375
-rw-r--r--docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md84
-rw-r--r--docs/libcurl/opts/CURLOPT_CAPATH.377
-rw-r--r--docs/libcurl/opts/CURLOPT_CAPATH.md79
-rw-r--r--docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.380
-rw-r--r--docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.md82
-rw-r--r--docs/libcurl/opts/CURLOPT_CERTINFO.387
-rw-r--r--docs/libcurl/opts/CURLOPT_CERTINFO.md90
-rw-r--r--docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3144
-rw-r--r--docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.md152
-rw-r--r--docs/libcurl/opts/CURLOPT_CHUNK_DATA.395
-rw-r--r--docs/libcurl/opts/CURLOPT_CHUNK_DATA.md102
-rw-r--r--docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.374
-rw-r--r--docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.md82
-rw-r--r--docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.361
-rw-r--r--docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.372
-rw-r--r--docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.md86
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.388
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.md89
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.363
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECT_ONLY.382
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md83
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECT_TO.3116
-rw-r--r--docs/libcurl/opts/CURLOPT_CONNECT_TO.md114
-rw-r--r--docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3106
-rw-r--r--docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.md114
-rw-r--r--docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3104
-rw-r--r--docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.md107
-rw-r--r--docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3105
-rw-r--r--docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.md110
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIE.390
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIE.md97
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIEFILE.397
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIEFILE.md103
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIEJAR.384
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIEJAR.md86
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIELIST.3125
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIELIST.md136
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIESESSION.373
-rw-r--r--docs/libcurl/opts/CURLOPT_COOKIESESSION.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.377
-rw-r--r--docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_CRLF.361
-rw-r--r--docs/libcurl/opts/CURLOPT_CRLF.md62
-rw-r--r--docs/libcurl/opts/CURLOPT_CRLFILE.380
-rw-r--r--docs/libcurl/opts/CURLOPT_CRLFILE.md82
-rw-r--r--docs/libcurl/opts/CURLOPT_CURLU.378
-rw-r--r--docs/libcurl/opts/CURLOPT_CURLU.md79
-rw-r--r--docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3117
-rw-r--r--docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md130
-rw-r--r--docs/libcurl/opts/CURLOPT_DEBUGDATA.374
-rw-r--r--docs/libcurl/opts/CURLOPT_DEBUGDATA.md86
-rw-r--r--docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3205
-rw-r--r--docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md216
-rw-r--r--docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.388
-rw-r--r--docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.md89
-rw-r--r--docs/libcurl/opts/CURLOPT_DIRLISTONLY.378
-rw-r--r--docs/libcurl/opts/CURLOPT_DIRLISTONLY.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.367
-rw-r--r--docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.388
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md90
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_INTERFACE.367
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.368
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.368
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_SERVERS.373
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_SERVERS.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.374
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.366
-rw-r--r--docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.388
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.md90
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3101
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.md102
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.374
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_URL.392
-rw-r--r--docs/libcurl/opts/CURLOPT_DOH_URL.md96
-rw-r--r--docs/libcurl/opts/CURLOPT_EGDSOCKET.365
-rw-r--r--docs/libcurl/opts/CURLOPT_EGDSOCKET.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_ERRORBUFFER.399
-rw-r--r--docs/libcurl/opts/CURLOPT_ERRORBUFFER.md101
-rw-r--r--docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.362
-rw-r--r--docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_FAILONERROR.373
-rw-r--r--docs/libcurl/opts/CURLOPT_FAILONERROR.md74
-rw-r--r--docs/libcurl/opts/CURLOPT_FILETIME.369
-rw-r--r--docs/libcurl/opts/CURLOPT_FILETIME.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_FNMATCH_DATA.367
-rw-r--r--docs/libcurl/opts/CURLOPT_FNMATCH_DATA.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.378
-rw-r--r--docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.md88
-rw-r--r--docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.390
-rw-r--r--docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md93
-rw-r--r--docs/libcurl/opts/CURLOPT_FORBID_REUSE.365
-rw-r--r--docs/libcurl/opts/CURLOPT_FORBID_REUSE.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_FRESH_CONNECT.365
-rw-r--r--docs/libcurl/opts/CURLOPT_FRESH_CONNECT.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_FTPPORT.396
-rw-r--r--docs/libcurl/opts/CURLOPT_FTPPORT.md99
-rw-r--r--docs/libcurl/opts/CURLOPT_FTPSSLAUTH.368
-rw-r--r--docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.365
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.368
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.384
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md88
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.377
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md86
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.370
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.370
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.374
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md73
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.371
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md73
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_USE_PRET.363
-rw-r--r--docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.365
-rw-r--r--docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md65
-rw-r--r--docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.369
-rw-r--r--docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.363
-rw-r--r--docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.362
-rw-r--r--docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md63
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADER.375
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADER.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADERDATA.388
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADERDATA.md89
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3129
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md132
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADEROPT.380
-rw-r--r--docs/libcurl/opts/CURLOPT_HEADEROPT.md81
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTS.380
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTS.md83
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSREADDATA.367
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSREADDATA.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.390
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md106
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.367
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.394
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md110
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTS_CTRL.372
-rw-r--r--docs/libcurl/opts/CURLOPT_HSTS_CTRL.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.363
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP200ALIASES.373
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP200ALIASES.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPAUTH.3140
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPAUTH.md163
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPGET.370
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPGET.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPHEADER.3165
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPHEADER.md181
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPPOST.387
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPPOST.md100
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.374
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.360
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md62
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.359
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md61
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP_VERSION.3103
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP_VERSION.md119
-rw-r--r--docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.371
-rw-r--r--docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.md73
-rw-r--r--docs/libcurl/opts/CURLOPT_INFILESIZE.380
-rw-r--r--docs/libcurl/opts/CURLOPT_INFILESIZE.md85
-rw-r--r--docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.376
-rw-r--r--docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.md81
-rw-r--r--docs/libcurl/opts/CURLOPT_INTERFACE.381
-rw-r--r--docs/libcurl/opts/CURLOPT_INTERFACE.md83
-rw-r--r--docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.363
-rw-r--r--docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.393
-rw-r--r--docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.md102
-rw-r--r--docs/libcurl/opts/CURLOPT_IOCTLDATA.365
-rw-r--r--docs/libcurl/opts/CURLOPT_IOCTLDATA.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.395
-rw-r--r--docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.md103
-rw-r--r--docs/libcurl/opts/CURLOPT_IPRESOLVE.376
-rw-r--r--docs/libcurl/opts/CURLOPT_IPRESOLVE.md83
-rw-r--r--docs/libcurl/opts/CURLOPT_ISSUERCERT.375
-rw-r--r--docs/libcurl/opts/CURLOPT_ISSUERCERT.md77
-rw-r--r--docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.386
-rw-r--r--docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md92
-rw-r--r--docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.367
-rw-r--r--docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_KEYPASSWD.366
-rw-r--r--docs/libcurl/opts/CURLOPT_KEYPASSWD.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_KRBLEVEL.364
-rw-r--r--docs/libcurl/opts/CURLOPT_KRBLEVEL.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_LOCALPORT.362
-rw-r--r--docs/libcurl/opts/CURLOPT_LOCALPORT.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.365
-rw-r--r--docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.375
-rw-r--r--docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.368
-rw-r--r--docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.365
-rw-r--r--docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_AUTH.374
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_AUTH.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_FROM.367
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_FROM.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_RCPT.377
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_RCPT.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.378
-rw-r--r--docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md81
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXAGE_CONN.370
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXAGE_CONN.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXCONNECTS.374
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXCONNECTS.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXFILESIZE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXFILESIZE.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.372
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md73
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXREDIRS.371
-rw-r--r--docs/libcurl/opts/CURLOPT_MAXREDIRS.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.370
-rw-r--r--docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_MIMEPOST.377
-rw-r--r--docs/libcurl/opts/CURLOPT_MIMEPOST.md81
-rw-r--r--docs/libcurl/opts/CURLOPT_MIME_OPTIONS.394
-rw-r--r--docs/libcurl/opts/CURLOPT_MIME_OPTIONS.md97
-rw-r--r--docs/libcurl/opts/CURLOPT_NETRC.3123
-rw-r--r--docs/libcurl/opts/CURLOPT_NETRC.md141
-rw-r--r--docs/libcurl/opts/CURLOPT_NETRC_FILE.365
-rw-r--r--docs/libcurl/opts/CURLOPT_NETRC_FILE.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.361
-rw-r--r--docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.359
-rw-r--r--docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md60
-rw-r--r--docs/libcurl/opts/CURLOPT_NOBODY.377
-rw-r--r--docs/libcurl/opts/CURLOPT_NOBODY.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_NOPROGRESS.364
-rw-r--r--docs/libcurl/opts/CURLOPT_NOPROGRESS.md65
-rw-r--r--docs/libcurl/opts/CURLOPT_NOPROXY.388
-rw-r--r--docs/libcurl/opts/CURLOPT_NOPROXY.md91
-rw-r--r--docs/libcurl/opts/CURLOPT_NOSIGNAL.376
-rw-r--r--docs/libcurl/opts/CURLOPT_NOSIGNAL.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.388
-rw-r--r--docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md92
-rw-r--r--docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3129
-rw-r--r--docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md132
-rw-r--r--docs/libcurl/opts/CURLOPT_PASSWORD.369
-rw-r--r--docs/libcurl/opts/CURLOPT_PASSWORD.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_PATH_AS_IS.375
-rw-r--r--docs/libcurl/opts/CURLOPT_PATH_AS_IS.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3134
-rw-r--r--docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.md143
-rw-r--r--docs/libcurl/opts/CURLOPT_PIPEWAIT.377
-rw-r--r--docs/libcurl/opts/CURLOPT_PIPEWAIT.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_PORT.370
-rw-r--r--docs/libcurl/opts/CURLOPT_PORT.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_POST.3100
-rw-r--r--docs/libcurl/opts/CURLOPT_POST.md102
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTFIELDS.3123
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTFIELDS.md124
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTQUOTE.370
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTQUOTE.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTREDIR.379
-rw-r--r--docs/libcurl/opts/CURLOPT_POSTREDIR.md81
-rw-r--r--docs/libcurl/opts/CURLOPT_PREQUOTE.374
-rw-r--r--docs/libcurl/opts/CURLOPT_PREQUOTE.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_PREREQDATA.366
-rw-r--r--docs/libcurl/opts/CURLOPT_PREREQDATA.md73
-rw-r--r--docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3107
-rw-r--r--docs/libcurl/opts/CURLOPT_PREREQFUNCTION.md125
-rw-r--r--docs/libcurl/opts/CURLOPT_PRE_PROXY.384
-rw-r--r--docs/libcurl/opts/CURLOPT_PRE_PROXY.md84
-rw-r--r--docs/libcurl/opts/CURLOPT_PRIVATE.367
-rw-r--r--docs/libcurl/opts/CURLOPT_PRIVATE.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_PROGRESSDATA.374
-rw-r--r--docs/libcurl/opts/CURLOPT_PROGRESSDATA.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3119
-rw-r--r--docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.md125
-rw-r--r--docs/libcurl/opts/CURLOPT_PROTOCOLS.3103
-rw-r--r--docs/libcurl/opts/CURLOPT_PROTOCOLS.md104
-rw-r--r--docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.387
-rw-r--r--docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.md88
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY.3134
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY.md146
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYAUTH.376
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYAUTH.md77
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYHEADER.378
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYHEADER.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYPASSWORD.368
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYPORT.366
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYPORT.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYTYPE.385
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYTYPE.md99
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYUSERNAME.370
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md73
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYUSERPWD.369
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAINFO.391
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md93
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.384
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md92
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAPATH.379
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md81
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.381
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md83
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.380
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md82
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.390
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md95
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.368
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3117
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md124
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.364
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md65
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.377
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md79
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.373
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.379
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md85
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.376
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md77
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.366
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.377
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md86
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3107
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.md125
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.389
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md91
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3104
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md119
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.393
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.md94
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.394
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.md94
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.377
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.369
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.377
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.369
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.366
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_PUT.376
-rw-r--r--docs/libcurl/opts/CURLOPT_PUT.md89
-rw-r--r--docs/libcurl/opts/CURLOPT_QUICK_EXIT.360
-rw-r--r--docs/libcurl/opts/CURLOPT_QUICK_EXIT.md62
-rw-r--r--docs/libcurl/opts/CURLOPT_QUOTE.3129
-rw-r--r--docs/libcurl/opts/CURLOPT_QUOTE.md161
-rw-r--r--docs/libcurl/opts/CURLOPT_RANDOM_FILE.365
-rw-r--r--docs/libcurl/opts/CURLOPT_RANDOM_FILE.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_RANGE.383
-rw-r--r--docs/libcurl/opts/CURLOPT_RANGE.md84
-rw-r--r--docs/libcurl/opts/CURLOPT_READDATA.372
-rw-r--r--docs/libcurl/opts/CURLOPT_READDATA.md77
-rw-r--r--docs/libcurl/opts/CURLOPT_READFUNCTION.3122
-rw-r--r--docs/libcurl/opts/CURLOPT_READFUNCTION.md123
-rw-r--r--docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3114
-rw-r--r--docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.md115
-rw-r--r--docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.393
-rw-r--r--docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.md94
-rw-r--r--docs/libcurl/opts/CURLOPT_REFERER.366
-rw-r--r--docs/libcurl/opts/CURLOPT_REFERER.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_REQUEST_TARGET.363
-rw-r--r--docs/libcurl/opts/CURLOPT_REQUEST_TARGET.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_RESOLVE.3113
-rw-r--r--docs/libcurl/opts/CURLOPT_RESOLVE.md115
-rw-r--r--docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.369
-rw-r--r--docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.386
-rw-r--r--docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.md88
-rw-r--r--docs/libcurl/opts/CURLOPT_RESUME_FROM.377
-rw-r--r--docs/libcurl/opts/CURLOPT_RESUME_FROM.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.377
-rw-r--r--docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.md79
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.360
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md62
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3118
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md139
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.359
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md61
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.365
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.371
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.365
-rw-r--r--docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_SASL_AUTHZID.370
-rw-r--r--docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_SASL_IR.370
-rw-r--r--docs/libcurl/opts/CURLOPT_SASL_IR.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_SEEKDATA.363
-rw-r--r--docs/libcurl/opts/CURLOPT_SEEKDATA.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_SEEKFUNCTION.394
-rw-r--r--docs/libcurl/opts/CURLOPT_SEEKFUNCTION.md102
-rw-r--r--docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.373
-rw-r--r--docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md74
-rw-r--r--docs/libcurl/opts/CURLOPT_SERVICE_NAME.365
-rw-r--r--docs/libcurl/opts/CURLOPT_SERVICE_NAME.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_SHARE.386
-rw-r--r--docs/libcurl/opts/CURLOPT_SHARE.md88
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKOPTDATA.372
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3127
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md132
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.368
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.363
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md63
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.366
-rw-r--r--docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.365
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md67
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.363
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.365
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.md73
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.387
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.md98
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.368
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.363
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md65
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_KEYDATA.368
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_KEYDATA.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3133
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md152
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.366
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md76
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLCERT.386
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLCERT.md87
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLCERTTYPE.369
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.377
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md83
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLENGINE.372
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLENGINE.md74
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.368
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLKEY.369
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLKEY.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLKEYTYPE.370
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.378
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md87
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLVERSION.3121
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLVERSION.md143
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.390
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md92
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3126
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md124
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3168
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md167
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.360
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md61
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.358
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md60
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.360
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md62
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_FALSESTART.361
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_FALSESTART.md62
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3101
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md116
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.363
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3112
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.md114
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.397
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.md98
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.366
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_STDERR.365
-rw-r--r--docs/libcurl/opts/CURLOPT_STDERR.md65
-rw-r--r--docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.376
-rw-r--r--docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md77
-rw-r--r--docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.380
-rw-r--r--docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.380
-rw-r--r--docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.md81
-rw-r--r--docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.398
-rw-r--r--docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md103
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.363
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.370
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.369
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.368
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_NODELAY.370
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_NODELAY.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_TELNETOPTIONS.364
-rw-r--r--docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.362
-rw-r--r--docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md63
-rw-r--r--docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.377
-rw-r--r--docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMECONDITION.371
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMECONDITION.md72
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEOUT.389
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEOUT.md90
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEOUT_MS.363
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEOUT_MS.md64
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEVALUE.368
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEVALUE.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.370
-rw-r--r--docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.377
-rw-r--r--docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.368
-rw-r--r--docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md70
-rw-r--r--docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.372
-rw-r--r--docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.367
-rw-r--r--docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md69
-rw-r--r--docs/libcurl/opts/CURLOPT_TRAILERDATA.356
-rw-r--r--docs/libcurl/opts/CURLOPT_TRAILERDATA.md59
-rw-r--r--docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3110
-rw-r--r--docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md110
-rw-r--r--docs/libcurl/opts/CURLOPT_TRANSFERTEXT.364
-rw-r--r--docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md65
-rw-r--r--docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.367
-rw-r--r--docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.md68
-rw-r--r--docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.384
-rw-r--r--docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.md87
-rw-r--r--docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.377
-rw-r--r--docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.md78
-rw-r--r--docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.382
-rw-r--r--docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.md82
-rw-r--r--docs/libcurl/opts/CURLOPT_UPLOAD.383
-rw-r--r--docs/libcurl/opts/CURLOPT_UPLOAD.md97
-rw-r--r--docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.378
-rw-r--r--docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_URL.3141
-rw-r--r--docs/libcurl/opts/CURLOPT_URL.md145
-rw-r--r--docs/libcurl/opts/CURLOPT_USERAGENT.366
-rw-r--r--docs/libcurl/opts/CURLOPT_USERAGENT.md66
-rw-r--r--docs/libcurl/opts/CURLOPT_USERNAME.389
-rw-r--r--docs/libcurl/opts/CURLOPT_USERNAME.md92
-rw-r--r--docs/libcurl/opts/CURLOPT_USERPWD.396
-rw-r--r--docs/libcurl/opts/CURLOPT_USERPWD.md98
-rw-r--r--docs/libcurl/opts/CURLOPT_USE_SSL.377
-rw-r--r--docs/libcurl/opts/CURLOPT_USE_SSL.md86
-rw-r--r--docs/libcurl/opts/CURLOPT_VERBOSE.370
-rw-r--r--docs/libcurl/opts/CURLOPT_VERBOSE.md71
-rw-r--r--docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3111
-rw-r--r--docs/libcurl/opts/CURLOPT_WILDCARDMATCH.md111
-rw-r--r--docs/libcurl/opts/CURLOPT_WRITEDATA.365
-rw-r--r--docs/libcurl/opts/CURLOPT_WRITEDATA.md63
-rw-r--r--docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3133
-rw-r--r--docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md136
-rw-r--r--docs/libcurl/opts/CURLOPT_WS_OPTIONS.371
-rw-r--r--docs/libcurl/opts/CURLOPT_WS_OPTIONS.md75
-rw-r--r--docs/libcurl/opts/CURLOPT_XFERINFODATA.377
-rw-r--r--docs/libcurl/opts/CURLOPT_XFERINFODATA.md80
-rw-r--r--docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3115
-rw-r--r--docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.md120
-rw-r--r--docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.366
-rw-r--r--docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md67
-rw-r--r--docs/libcurl/opts/CURLSHOPT_LOCKFUNC.374
-rw-r--r--docs/libcurl/opts/CURLSHOPT_LOCKFUNC.md77
-rw-r--r--docs/libcurl/opts/CURLSHOPT_SHARE.3105
-rw-r--r--docs/libcurl/opts/CURLSHOPT_SHARE.md117
-rw-r--r--docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.370
-rw-r--r--docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.md72
-rw-r--r--docs/libcurl/opts/CURLSHOPT_UNSHARE.374
-rw-r--r--docs/libcurl/opts/CURLSHOPT_UNSHARE.md84
-rw-r--r--docs/libcurl/opts/CURLSHOPT_USERDATA.358
-rw-r--r--docs/libcurl/opts/CURLSHOPT_USERDATA.md62
-rw-r--r--docs/libcurl/opts/Makefile.am43
-rw-r--r--docs/libcurl/opts/Makefile.inc2
-rw-r--r--docs/libcurl/opts/template.341
-rw-r--r--docs/libcurl/symbols-in-versions18
-rw-r--r--docs/mk-ca-bundle.1120
-rw-r--r--docs/mk-ca-bundle.md128
-rw-r--r--include/curl/curl.h36
-rw-r--r--include/curl/curlver.h6
-rw-r--r--include/curl/mprintf.h18
-rw-r--r--include/curl/system.h49
-rw-r--r--include/curl/urlapi.h1
-rw-r--r--lib/CMakeLists.txt21
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/Makefile.inc8
-rw-r--r--lib/Makefile.mk186
-rw-r--r--lib/altsvc.c17
-rw-r--r--lib/arpa_telnet.h9
-rw-r--r--lib/asyn-ares.c39
-rw-r--r--lib/asyn-thread.c235
-rw-r--r--lib/base64.c1
-rw-r--r--lib/bufref.c6
-rw-r--r--lib/c-hyper.c111
-rw-r--r--lib/cf-h1-proxy.c122
-rw-r--r--lib/cf-h2-proxy.c79
-rw-r--r--lib/cf-haproxy.c24
-rw-r--r--lib/cf-https-connect.c56
-rw-r--r--lib/cf-socket.c178
-rw-r--r--lib/cf-socket.h17
-rw-r--r--lib/cfilters.c190
-rw-r--r--lib/cfilters.h108
-rw-r--r--lib/config-amigaos.h1
-rw-r--r--lib/config-dos.h1
-rw-r--r--lib/config-os400.h12
-rw-r--r--lib/config-plan9.h2
-rw-r--r--lib/config-riscos.h6
-rw-r--r--lib/config-win32.h164
-rw-r--r--lib/config-win32ce.h14
-rw-r--r--lib/conncache.c25
-rw-r--r--lib/connect.c163
-rw-r--r--lib/content_encoding.c329
-rw-r--r--lib/content_encoding.h9
-rw-r--r--lib/cookie.c40
-rw-r--r--lib/curl_config.h30
-rw-r--r--lib/curl_config.h.cmake45
-rw-r--r--lib/curl_config.h.in46
-rw-r--r--lib/curl_hmac.h3
-rw-r--r--lib/curl_memory.h6
-rw-r--r--lib/curl_multibyte.c4
-rw-r--r--lib/curl_multibyte.h8
-rw-r--r--lib/curl_ntlm_core.c9
-rw-r--r--lib/curl_ntlm_wb.c18
-rw-r--r--lib/curl_path.h2
-rw-r--r--lib/curl_printf.h4
-rw-r--r--lib/curl_rtmp.c14
-rw-r--r--lib/curl_sasl.c22
-rw-r--r--lib/curl_setup.h217
-rw-r--r--lib/curl_setup_once.h8
-rw-r--r--lib/curl_sspi.h16
-rw-r--r--lib/curl_trc.c28
-rw-r--r--lib/curl_trc.h105
-rw-r--r--lib/dict.c5
-rw-r--r--lib/doh.c60
-rw-r--r--lib/dynbuf.c13
-rw-r--r--lib/dynbuf.h4
-rw-r--r--lib/dynhds.c29
-rw-r--r--lib/dynhds.h9
-rw-r--r--lib/easy.c82
-rw-r--r--lib/easy_lock.h9
-rw-r--r--lib/easyoptions.c4
-rw-r--r--lib/file.c46
-rw-r--r--lib/fopen.c77
-rw-r--r--lib/formdata.c16
-rw-r--r--lib/ftp.c203
-rw-r--r--lib/ftplistparser.c3
-rw-r--r--lib/functypes.h2
-rw-r--r--lib/getenv.c5
-rw-r--r--lib/getinfo.c5
-rw-r--r--lib/gopher.c4
-rw-r--r--lib/headers.c35
-rw-r--r--lib/hostip.c115
-rw-r--r--lib/hostip.h4
-rw-r--r--lib/hostip6.c7
-rw-r--r--lib/hsts.c48
-rw-r--r--lib/http.c539
-rw-r--r--lib/http.h26
-rw-r--r--lib/http2.c194
-rw-r--r--lib/http_aws_sigv4.c30
-rw-r--r--lib/http_chunks.c355
-rw-r--r--lib/http_chunks.h60
-rw-r--r--lib/http_proxy.c6
-rw-r--r--lib/idn.c2
-rw-r--r--lib/imap.c97
-rw-r--r--lib/inet_pton.c3
-rw-r--r--lib/inet_pton.h3
-rw-r--r--lib/krb5.c39
-rw-r--r--lib/ldap.c26
-rw-r--r--lib/md4.c11
-rw-r--r--lib/memdebug.c39
-rw-r--r--lib/memdebug.h6
-rw-r--r--lib/mime.c26
-rw-r--r--lib/mime.h3
-rw-r--r--lib/mprintf.c1210
-rw-r--r--lib/mqtt.c38
-rw-r--r--lib/mqtt.h1
-rw-r--r--lib/multi.c415
-rw-r--r--lib/multihandle.h15
-rw-r--r--lib/netrc.c2
-rw-r--r--lib/noproxy.c1
-rw-r--r--lib/openldap.c73
-rw-r--r--lib/pingpong.c268
-rw-r--r--lib/pingpong.h20
-rw-r--r--lib/pop3.c108
-rw-r--r--lib/progress.c18
-rw-r--r--lib/progress.h3
-rw-r--r--lib/rand.c34
-rw-r--r--lib/rand.h2
-rw-r--r--lib/rename.c2
-rw-r--r--lib/rtsp.c410
-rw-r--r--lib/rtsp.h9
-rw-r--r--lib/select.c2
-rw-r--r--lib/sendf.c369
-rw-r--r--lib/sendf.h131
-rw-r--r--lib/setopt.c264
-rw-r--r--lib/setup-win32.h73
-rw-r--r--lib/share.c8
-rw-r--r--lib/share.h10
-rw-r--r--lib/smb.c13
-rw-r--r--lib/smtp.c34
-rw-r--r--lib/socketpair.c9
-rw-r--r--lib/socketpair.h17
-rw-r--r--lib/socks.c109
-rw-r--r--lib/socks_gssapi.c7
-rw-r--r--lib/socks_sspi.c12
-rw-r--r--lib/strdup.c24
-rw-r--r--lib/strdup.h3
-rw-r--r--lib/strerror.c78
-rw-r--r--lib/strerror.h2
-rw-r--r--lib/system_win32.c35
-rw-r--r--lib/system_win32.h34
-rw-r--r--lib/telnet.c117
-rw-r--r--lib/tftp.c16
-rw-r--r--lib/tftp.h3
-rw-r--r--lib/timediff.c2
-rw-r--r--lib/timeval.c7
-rw-r--r--lib/transfer.c574
-rw-r--r--lib/transfer.h21
-rw-r--r--lib/url.c1165
-rw-r--r--lib/url.h9
-rw-r--r--lib/urlapi.c204
-rw-r--r--lib/urldata.h102
-rw-r--r--lib/vauth/digest.c1
-rw-r--r--lib/vauth/digest_sspi.c4
-rw-r--r--lib/vauth/krb5_gssapi.c3
-rw-r--r--lib/vauth/krb5_sspi.c3
-rw-r--r--lib/vauth/ntlm.c6
-rw-r--r--lib/vauth/ntlm_sspi.c8
-rw-r--r--lib/version.c20
-rw-r--r--lib/version_win32.c4
-rw-r--r--lib/version_win32.h4
-rw-r--r--lib/vquic/curl_msh3.c43
-rw-r--r--lib/vquic/curl_ngtcp2.c811
-rw-r--r--lib/vquic/curl_osslq.c2237
-rw-r--r--lib/vquic/curl_osslq.h51
-rw-r--r--lib/vquic/curl_quiche.c472
-rw-r--r--lib/vquic/vquic-tls.c609
-rw-r--r--lib/vquic/vquic-tls.h98
-rw-r--r--lib/vquic/vquic.c41
-rw-r--r--lib/vquic/vquic_int.h10
-rw-r--r--lib/vssh/libssh.c96
-rw-r--r--lib/vssh/libssh2.c328
-rw-r--r--lib/vssh/ssh.h1
-rw-r--r--lib/vssh/wolfssh.c31
-rw-r--r--lib/vtls/bearssl.c86
-rw-r--r--lib/vtls/gtls.c131
-rw-r--r--lib/vtls/gtls.h6
-rw-r--r--lib/vtls/keylog.c9
-rw-r--r--lib/vtls/mbedtls.c41
-rw-r--r--lib/vtls/mbedtls_threadlock.c2
-rw-r--r--lib/vtls/openssl.c578
-rw-r--r--lib/vtls/openssl.h21
-rw-r--r--lib/vtls/rustls.c125
-rw-r--r--lib/vtls/schannel.c232
-rw-r--r--lib/vtls/schannel_int.h17
-rw-r--r--lib/vtls/schannel_verify.c68
-rw-r--r--lib/vtls/sectransp.c56
-rw-r--r--lib/vtls/vtls.c509
-rw-r--r--lib/vtls/vtls.h82
-rw-r--r--lib/vtls/vtls_int.h40
-rw-r--r--lib/vtls/wolfssl.c64
-rw-r--r--lib/vtls/x509asn1.c899
-rw-r--r--lib/warnless.c12
-rw-r--r--lib/warnless.h21
-rw-r--r--lib/ws.c344
-rw-r--r--lib/ws.h13
-rwxr-xr-xltmain.sh28
-rw-r--r--m4/curl-amissl.m42
-rw-r--r--m4/curl-compilers.m4166
-rw-r--r--m4/curl-functions.m464
-rw-r--r--m4/curl-gnutls.m41
-rw-r--r--m4/curl-openssl.m432
-rw-r--r--m4/curl-wolfssl.m41
-rwxr-xr-xmaketgz7
-rw-r--r--packages/OS400/.gitattributes6
-rw-r--r--packages/OS400/ccsidcurl.c2
-rw-r--r--packages/OS400/curl.inc.in18
-rw-r--r--packages/vms/config_h.com32
-rw-r--r--projects/Windows/VC14.20/.gitignore9
-rw-r--r--projects/Windows/VC14.20/curl-all.sln298
-rw-r--r--projects/Windows/VC14.20/lib/.gitignore10
-rw-r--r--projects/Windows/VC14.20/lib/libcurl.sln181
-rw-r--r--projects/Windows/VC14.20/lib/libcurl.tmpl2381
-rw-r--r--projects/Windows/VC14.20/lib/libcurl.vcxproj.filters17
-rw-r--r--projects/Windows/VC14.20/src/.gitignore10
-rw-r--r--projects/Windows/VC14.20/src/curl.sln181
-rw-r--r--projects/Windows/VC14.20/src/curl.tmpl2671
-rw-r--r--projects/Windows/VC14.20/src/curl.vcxproj.filters17
-rw-r--r--projects/Windows/VC14.30/src/curl.sln2
-rw-r--r--projects/generate.bat23
-rw-r--r--scripts/Makefile.am4
-rwxr-xr-xscripts/cd2cd226
-rwxr-xr-xscripts/cd2nroff373
-rwxr-xr-xscripts/cdall44
-rwxr-xr-xscripts/checksrc.pl20
-rwxr-xr-xscripts/ciconfig.pl7
-rwxr-xr-xscripts/cijobs.pl24
-rwxr-xr-xscripts/cmp-config.pl2
-rwxr-xr-xscripts/nroff2cd193
-rw-r--r--scripts/schemetable.c207
-rwxr-xr-xscripts/singleuse.pl1
-rwxr-xr-xscripts/updatemanpages.pl357
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/Makefile.am6
-rw-r--r--src/Makefile.inc2
-rw-r--r--src/Makefile.mk29
-rw-r--r--src/curl.rc2
-rw-r--r--src/tool_cb_dbg.c2
-rw-r--r--src/tool_cb_hdr.c37
-rw-r--r--src/tool_cb_prg.c22
-rw-r--r--src/tool_cb_rea.c2
-rw-r--r--src/tool_cb_see.c15
-rw-r--r--src/tool_cb_see.h4
-rw-r--r--src/tool_cb_wrt.c26
-rw-r--r--src/tool_cfgable.c5
-rw-r--r--src/tool_cfgable.h2
-rw-r--r--src/tool_dirhie.c8
-rw-r--r--src/tool_doswin.c36
-rw-r--r--src/tool_doswin.h8
-rw-r--r--src/tool_easysrc.h2
-rw-r--r--src/tool_filetime.c8
-rw-r--r--src/tool_filetime.h4
-rw-r--r--src/tool_findfile.c2
-rw-r--r--src/tool_findfile.h2
-rw-r--r--src/tool_formparse.c2
-rw-r--r--src/tool_getparam.c3474
-rw-r--r--src/tool_getparam.h1
-rw-r--r--src/tool_getpass.c6
-rw-r--r--src/tool_help.c20
-rw-r--r--src/tool_helpers.c2
-rw-r--r--src/tool_ipfs.c293
-rw-r--r--src/tool_ipfs.h33
-rw-r--r--src/tool_listhelp.c12
-rw-r--r--src/tool_main.c13
-rw-r--r--src/tool_msgs.c7
-rw-r--r--src/tool_msgs.h12
-rw-r--r--src/tool_operate.c255
-rw-r--r--src/tool_operate.h2
-rw-r--r--src/tool_operhlp.c4
-rw-r--r--src/tool_paramhlp.c6
-rw-r--r--src/tool_paramhlp.h2
-rw-r--r--src/tool_parsecfg.c9
-rw-r--r--src/tool_sdecls.h2
-rw-r--r--src/tool_setopt.c16
-rw-r--r--src/tool_setup.h4
-rw-r--r--src/tool_sleep.c2
-rw-r--r--src/tool_urlglob.c30
-rw-r--r--src/tool_util.c2
-rw-r--r--src/tool_writeout_json.c4
-rw-r--r--src/tool_xattr.c4
-rw-r--r--src/var.c2
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/FILEFORMAT.md11
-rw-r--r--tests/Makefile.am50
-rw-r--r--tests/README.md81
-rwxr-xr-xtests/convsrctest.pl263
-rw-r--r--tests/data/DISABLED5
-rw-r--r--tests/data/Makefile.inc21
-rw-r--r--tests/data/test10262
-rw-r--r--tests/data/test11192
-rw-r--r--tests/data/test11322
-rw-r--r--tests/data/test11352
-rw-r--r--tests/data/test11392
-rw-r--r--tests/data/test11402
-rw-r--r--tests/data/test11544
-rw-r--r--tests/data/test11652
-rw-r--r--tests/data/test11672
-rw-r--r--tests/data/test11732
-rw-r--r--tests/data/test11752
-rw-r--r--tests/data/test11772
-rw-r--r--tests/data/test12222
-rw-r--r--tests/data/test12542
-rw-r--r--tests/data/test12682
-rw-r--r--tests/data/test12752
-rw-r--r--tests/data/test12762
-rw-r--r--tests/data/test12792
-rw-r--r--tests/data/test1474121
-rw-r--r--tests/data/test147583
-rw-r--r--tests/data/test147659
-rw-r--r--tests/data/test147730
-rw-r--r--tests/data/test147832
-rw-r--r--tests/data/test15061
-rw-r--r--tests/data/test15386
-rw-r--r--tests/data/test15442
-rw-r--r--tests/data/test154538
-rw-r--r--tests/data/test16832
-rw-r--r--tests/data/test170466
-rw-r--r--tests/data/test192
-rw-r--r--tests/data/test190038
-rw-r--r--tests/data/test1943
-rw-r--r--tests/data/test19404
-rw-r--r--tests/data/test230771
-rw-r--r--tests/data/test2502
-rw-r--r--tests/data/test26859
-rw-r--r--tests/data/test2852
-rw-r--r--tests/data/test30125
-rw-r--r--tests/data/test31032
-rw-r--r--tests/data/test4212
-rw-r--r--tests/data/test4396
-rw-r--r--tests/data/test4575
-rw-r--r--tests/data/test45963
-rw-r--r--tests/data/test46028
-rw-r--r--tests/data/test46148
-rw-r--r--tests/data/test4982
-rw-r--r--tests/data/test68953
-rw-r--r--tests/data/test7226
-rw-r--r--tests/data/test7232
-rw-r--r--tests/data/test7248
-rw-r--r--tests/data/test7254
-rw-r--r--tests/data/test7262
-rw-r--r--tests/data/test7276
-rw-r--r--tests/data/test72941
-rw-r--r--tests/data/test73052
-rw-r--r--tests/data/test73158
-rw-r--r--tests/data/test73252
-rw-r--r--tests/data/test73352
-rw-r--r--tests/data/test73452
-rw-r--r--tests/data/test73552
-rw-r--r--tests/data/test73658
-rw-r--r--tests/data/test73758
-rw-r--r--tests/data/test73837
-rw-r--r--tests/data/test73934
-rw-r--r--tests/data/test74060
-rw-r--r--tests/data/test74142
-rw-r--r--tests/data/test74266
-rw-r--r--tests/data/test804
-rw-r--r--tests/data/test9712
-rw-r--r--tests/data/test99252
-rwxr-xr-xtests/disable-scan.pl148
-rwxr-xr-xtests/ftpserver.pl3
-rw-r--r--tests/http/clients/.gitignore2
-rw-r--r--tests/http/clients/h2-download.c22
-rw-r--r--tests/http/clients/h2-serverpush.c5
-rw-r--r--tests/http/requirements.txt1
-rw-r--r--tests/http/scorecard.py247
-rw-r--r--tests/http/test_01_basic.py15
-rw-r--r--tests/http/test_02_download.py32
-rw-r--r--tests/http/test_07_upload.py65
-rw-r--r--tests/http/test_08_caddy.py17
-rw-r--r--tests/http/test_10_proxy.py102
-rw-r--r--tests/http/test_14_auth.py6
-rw-r--r--tests/http/testenv/__init__.py2
-rw-r--r--tests/http/testenv/curl.py160
-rw-r--r--tests/http/testenv/mod_curltest/mod_curltest.c5
-rw-r--r--tests/http/testenv/nghttpx.py8
-rw-r--r--tests/libtest/CMakeLists.txt2
-rw-r--r--tests/libtest/Makefile.am2
-rw-r--r--tests/libtest/Makefile.inc8
-rw-r--r--tests/libtest/first.c14
-rw-r--r--tests/libtest/lib1156.c2
-rw-r--r--tests/libtest/lib1517.c2
-rw-r--r--tests/libtest/lib1531.c2
-rw-r--r--tests/libtest/lib1545.c56
-rw-r--r--tests/libtest/lib1560.c22
-rw-r--r--tests/libtest/lib1900.c55
-rw-r--r--tests/libtest/lib1940.c2
-rw-r--r--tests/libtest/lib1947.c2
-rw-r--r--tests/libtest/lib1960.c6
-rw-r--r--tests/libtest/lib2305.c2
-rw-r--r--tests/libtest/lib3026.c4
-rw-r--r--tests/libtest/lib517.c2
-rw-r--r--tests/libtest/lib518.c108
-rw-r--r--tests/libtest/lib537.c91
-rw-r--r--tests/libtest/lib544.c2
-rw-r--r--tests/libtest/lib552.c5
-rw-r--r--tests/libtest/lib557.c56
-rw-r--r--tests/libtest/lib567.c1
-rw-r--r--tests/libtest/lib568.c1
-rw-r--r--tests/libtest/lib670.c2
-rw-r--r--tests/libtest/sethostname.c2
-rw-r--r--tests/libtest/sethostname.h42
-rw-r--r--tests/libtest/stub_gssapi.c10
-rw-r--r--tests/libtest/test.h2
-rwxr-xr-xtests/libtest/test613.pl2
-rw-r--r--tests/libtest/testtrace.c5
-rw-r--r--tests/libtest/testutil.c8
-rw-r--r--tests/libtest/testutil.h2
-rwxr-xr-xtests/manpage-scan.pl305
-rwxr-xr-xtests/markdown-uppercase.pl100
-rwxr-xr-xtests/nroff-scan.pl112
-rwxr-xr-xtests/options-scan.pl125
-rw-r--r--tests/pathhelp.pm1
-rw-r--r--tests/runner.pm24
-rw-r--r--tests/runtests.140
-rwxr-xr-xtests/runtests.pl10
-rw-r--r--tests/server/getpart.c4
-rw-r--r--tests/server/mqttd.c55
-rw-r--r--tests/server/resolve.c2
-rw-r--r--tests/server/rtspd.c2
-rw-r--r--tests/server/sockfilt.c14
-rw-r--r--tests/server/socksd.c66
-rw-r--r--tests/server/sws.c19
-rw-r--r--tests/server/tftpd.c6
-rw-r--r--tests/server/util.c52
-rw-r--r--tests/server/util.h11
-rw-r--r--tests/servers.pm38
-rwxr-xr-xtests/test1119.pl (renamed from tests/symbol-scan.pl)0
-rwxr-xr-xtests/test1132.pl (renamed from tests/mem-include-scan.pl)0
-rwxr-xr-xtests/test1135.pl (renamed from tests/extern-scan.pl)0
-rwxr-xr-xtests/test1139.pl312
-rwxr-xr-xtests/test1140.pl114
-rwxr-xr-xtests/test1165.pl189
-rwxr-xr-xtests/test1167.pl (renamed from tests/badsymbols.pl)0
-rwxr-xr-xtests/test1173.pl (renamed from tests/manpage-syntax.pl)0
-rwxr-xr-xtests/test1175.pl (renamed from tests/error-codes.pl)0
-rwxr-xr-xtests/test1177.pl94
-rwxr-xr-xtests/test1222.pl (renamed from tests/check-deprecated.pl)0
-rwxr-xr-xtests/test1275.pl117
-rwxr-xr-xtests/test1276.pl (renamed from tests/option-check.pl)0
-rwxr-xr-xtests/test1477.pl100
-rwxr-xr-xtests/test1544.pl (renamed from tests/check-translatable-options.pl)0
-rwxr-xr-xtests/test971.pl125
-rw-r--r--tests/testutil.pm13
-rw-r--r--tests/unit/curlcheck.h2
-rw-r--r--tests/unit/unit1394.c2
-rw-r--r--tests/unit/unit1395.c10
-rw-r--r--tests/unit/unit1398.c2
-rw-r--r--tests/unit/unit1604.c4
-rw-r--r--tests/unit/unit1651.c2
-rw-r--r--tests/unit/unit1652.c4
-rw-r--r--tests/unit/unit2600.c8
-rw-r--r--tests/unit/unit3200.c5
-rwxr-xr-xtests/version-scan.pl94
2107 files changed, 87211 insertions, 68116 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index bc3c98cf0..5c789637c 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -29,221 +29,221 @@
trigger:
branches:
include:
- - 'master'
- - '*/ci'
+ - 'master'
+ - '*/ci'
paths:
exclude:
- - '.circleci/*'
- - '.cirrus.yml'
- - '.github/*'
- - '.github/workflows/*'
- - 'appveyor.yml'
- - 'packages/*'
- - 'plan9/*'
+ - '.circleci/*'
+ - '.cirrus.yml'
+ - '.github/*'
+ - '.github/workflows/*'
+ - 'appveyor.*'
+ - 'packages/*'
+ - 'plan9/*'
pr:
branches:
include:
- - 'master'
+ - 'master'
paths:
exclude:
- - '.circleci/*'
- - '.cirrus.yml'
- - '.github/*'
- - '.github/workflows/*'
- - 'appveyor.yml'
- - 'packages/*'
- - 'plan9/*'
+ - '.circleci/*'
+ - '.cirrus.yml'
+ - '.github/*'
+ - '.github/workflows/*'
+ - 'appveyor.*'
+ - 'packages/*'
+ - 'plan9/*'
variables:
MAKEFLAGS: '-j 2'
stages:
-##########################################
-### Linux jobs first
-##########################################
-
-- stage: linux
- dependsOn: []
- jobs:
- - job: ubuntu
- # define defaults to make sure variables are always expanded/replaced
- variables:
- install: ''
- configure: ''
- tests: '!433'
- timeoutInMinutes: 60
- pool:
- vmImage: 'ubuntu-latest'
- strategy:
- matrix:
- default:
- name: default
- install:
- configure: --enable-debug --with-openssl
- disable_ipv6:
- name: w/o IPv6
- configure: --disable-ipv6 --with-openssl
- disable_http_smtp_imap:
- name: w/o HTTP/SMTP/IMAP
- configure: --disable-http --disable-smtp --disable-imap --without-ssl
- disable_thredres:
- name: sync resolver
- configure: --disable-threaded-resolver --with-openssl
- https_only:
- name: HTTPS 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 --with-openssl
- torture:
- name: torture
- install: libnghttp2-dev
- configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl
- tests: -n -t --shallow=25 !FTP
- steps:
- - script: sudo apt-get update && sudo apt-get install -y stunnel4 python3-impacket libzstd-dev libbrotli-dev $(install)
- displayName: 'apt install'
- retryCountOnTaskFailure: 3
-
- - script: autoreconf -fi && ./configure --enable-warnings --enable-werror $(configure)
- displayName: 'configure $(name)'
-
- - script: make V=1 && make V=1 examples && cd tests && make V=1
- displayName: 'compile'
-
- - script: make V=1 test-ci
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "-ac /usr/bin/curl -r $(tests)"
-
-- stage: scanbuild
- dependsOn: []
- jobs:
- - job: ubuntu
- timeoutInMinutes: 30
- pool:
- vmImage: 'ubuntu-latest'
- steps:
- - script: sudo apt-get update && sudo apt-get install -y clang-tools clang libssl-dev libssh2-1-dev libpsl-dev libbrotli-dev libzstd-dev
- displayName: 'apt install'
- retryCountOnTaskFailure: 3
-
- - script: autoreconf -fi
- displayName: 'autoreconf'
-
- - script: scan-build ./configure --enable-debug --enable-werror --with-openssl --with-libssh2
- displayName: 'configure'
- env:
- CC: "clang"
- CCX: "clang++"
-
- - script: scan-build --status-bugs make
- displayName: 'make'
-
- - script: scan-build --status-bugs make examples
- displayName: 'make examples'
-
-##########################################
-### Windows jobs below
-##########################################
-
-- stage: windows
- dependsOn: []
- variables:
- agent.preferPowerShellOnContainers: true
- jobs:
- - job: msys2
- # define defaults to make sure variables are always expanded/replaced
+ ##########################################
+ ### Linux jobs first
+ ##########################################
+
+ - stage: linux
+ dependsOn: []
+ jobs:
+ - job: ubuntu
+ # define defaults to make sure variables are always expanded/replaced
+ variables:
+ install: ''
+ configure: ''
+ tests: '!433'
+ timeoutInMinutes: 60
+ pool:
+ vmImage: 'ubuntu-latest'
+ strategy:
+ matrix:
+ default:
+ name: default
+ install:
+ configure: --enable-debug --with-openssl
+ disable_ipv6:
+ name: w/o IPv6
+ configure: --disable-ipv6 --with-openssl
+ disable_http_smtp_imap:
+ name: w/o HTTP/SMTP/IMAP
+ configure: --disable-http --disable-smtp --disable-imap --without-ssl
+ disable_thredres:
+ name: sync resolver
+ configure: --disable-threaded-resolver --with-openssl
+ https_only:
+ name: HTTPS 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 --with-openssl
+ torture:
+ name: torture
+ install: libnghttp2-dev
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl
+ tests: -n -t --shallow=25 !FTP
+ steps:
+ - script: sudo apt-get update && sudo apt-get install -y stunnel4 python3-impacket libzstd-dev libbrotli-dev libpsl-dev $(install)
+ displayName: 'apt install'
+ retryCountOnTaskFailure: 3
+
+ - script: autoreconf -fi && ./configure --enable-warnings --enable-werror $(configure)
+ displayName: 'configure $(name)'
+
+ - script: make V=1 && make V=1 examples && cd tests && make V=1
+ displayName: 'compile'
+
+ - script: make V=1 test-ci
+ displayName: 'test'
+ env:
+ AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+ TFLAGS: "-ac /usr/bin/curl -r $(tests)"
+
+ - stage: scanbuild
+ dependsOn: []
+ jobs:
+ - job: ubuntu
+ timeoutInMinutes: 30
+ pool:
+ vmImage: 'ubuntu-latest'
+ steps:
+ - script: sudo apt-get update && sudo apt-get install -y clang-tools clang libssl-dev libssh2-1-dev libpsl-dev libbrotli-dev libzstd-dev
+ displayName: 'apt install'
+ retryCountOnTaskFailure: 3
+
+ - script: autoreconf -fi
+ displayName: 'autoreconf'
+
+ - script: scan-build ./configure --enable-debug --enable-werror --with-openssl --with-libssh2
+ displayName: 'configure'
+ env:
+ CC: "clang"
+ CCX: "clang++"
+
+ - script: scan-build --status-bugs make
+ displayName: 'make'
+
+ - script: scan-build --status-bugs make examples
+ displayName: 'make examples'
+
+ ##########################################
+ ### Windows jobs below
+ ##########################################
+
+ - stage: windows
+ dependsOn: []
variables:
- container_img: ''
- container_cmd: ''
- configure: ''
- tests: ''
- timeoutInMinutes: 120
- pool:
- vmImage: 'windows-2019'
- strategy:
- matrix:
- mingw32_openssl:
- name: 32-bit OpenSSL/libssh2
- container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw32:ltsc2019
- container_cmd: C:\msys64\usr\bin\sh
- prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-i686-libssh2
- configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --with-libssh2 --with-openssl
- tests: "~571"
- mingw64_openssl:
- name: 64-bit OpenSSL/libssh2
- container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
- container_cmd: C:\msys64\usr\bin\sh
- prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-x86_64-libssh2
- configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --with-libssh2 --with-openssl
- tests: "~571"
- mingw64_libssh:
- name: 64-bit OpenSSL/libssh
- container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
- container_cmd: C:\msys64\usr\bin\sh
- prepare: pacman -S --needed --noconfirm --noprogressbar libssh-devel mingw-w64-x86_64-libssh
- configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --with-libssh --with-openssl
- tests: "~571 ~614"
- mingw32:
- name: 32-bit w/o zlib
- container_img: ghcr.io/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 --without-zlib --without-ssl
- tests: "!203 !1143"
- mingw64:
- name: 64-bit w/o zlib
- container_img: ghcr.io/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 --without-zlib --without-ssl
- tests: "!203 !1143"
- mingw32_schannel:
- name: 32-bit Schannel/SSPI/WinIDN/libssh2
- container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw32:ltsc2019
- container_cmd: C:\msys64\usr\bin\sh
- prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-i686-libssh2
- configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2
- tests: "~571"
- mingw64_schannel:
- name: 64-bit Schannel/SSPI/WinIDN/libssh2
- container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
- container_cmd: C:\msys64\usr\bin\sh
- prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-x86_64-libssh2
- configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2
- tests: "~571"
- mingw32_schannel_nozlib:
- name: 32-bit Schannel/SSPI/WinIDN w/o zlib
- container_img: ghcr.io/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 --with-schannel --with-winidn --without-zlib
- tests: "!203 !1143"
- mingw64_schannel_nozlib:
- name: 64-bit Schannel/SSPI/WinIDN w/o zlib
- container_img: ghcr.io/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 --with-schannel --with-winidn --without-zlib
- tests: "!203 !1143"
- container:
- image: $(container_img)
- env:
- MSYS2_PATH_TYPE: inherit
- steps:
- - script: $(container_cmd) -l -c "cd $(echo '%cd%') && $(prepare)"
- displayName: 'prepare'
- condition: variables.prepare
- retryCountOnTaskFailure: 3
-
- - script: $(container_cmd) -l -c "cd $(echo '%cd%') && autoreconf -fi && ./configure $(configure)"
- displayName: 'configure $(name)'
-
- - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make V=1 && make V=1 examples && cd tests && make V=1"
- displayName: 'compile'
-
- - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make V=1 install && PATH=/usr/bin:/bin find . -type f -path '*/.libs/*.exe' -print -execdir mv -t .. {} \;"
- displayName: 'install'
-
- - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make V=1 test-ci"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "-ac /usr/bin/curl.exe !IDN !SCP ~612 $(tests)"
+ agent.preferPowerShellOnContainers: true
+ jobs:
+ - job: msys2
+ # define defaults to make sure variables are always expanded/replaced
+ variables:
+ container_img: ''
+ container_cmd: ''
+ configure: ''
+ tests: ''
+ timeoutInMinutes: 120
+ pool:
+ vmImage: 'windows-2019'
+ strategy:
+ matrix:
+ mingw32_openssl:
+ name: 32-bit OpenSSL/libssh2
+ container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw32:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-i686-libssh2
+ configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --with-libssh2 --with-openssl --without-libpsl
+ tests: "~571"
+ mingw64_openssl:
+ name: 64-bit OpenSSL/libssh2
+ container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-x86_64-libssh2
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --with-libssh2 --with-openssl --without-libpsl
+ tests: "~571"
+ mingw64_libssh:
+ name: 64-bit OpenSSL/libssh
+ container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ prepare: pacman -S --needed --noconfirm --noprogressbar libssh-devel mingw-w64-x86_64-libssh
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --with-libssh --with-openssl --without-libpsl
+ tests: "~571 ~614"
+ mingw32:
+ name: 32-bit w/o zlib
+ container_img: ghcr.io/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 --without-zlib --without-ssl --without-libpsl
+ tests: "!203 !1143"
+ mingw64:
+ name: 64-bit w/o zlib
+ container_img: ghcr.io/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 --without-zlib --without-ssl --without-libpsl
+ tests: "!203 !1143"
+ mingw32_schannel:
+ name: 32-bit Schannel/SSPI/WinIDN/libssh2
+ container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw32:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-i686-libssh2
+ configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --without-libpsl
+ tests: "~571"
+ mingw64_schannel:
+ name: 64-bit Schannel/SSPI/WinIDN/libssh2
+ container_img: ghcr.io/mback2k/curl-docker-winbuildenv/msys2-mingw64:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ prepare: pacman -S --needed --noconfirm --noprogressbar libssh2-devel mingw-w64-x86_64-libssh2
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --enable-sspi --with-schannel --with-winidn --with-libssh2 --without-libpsl
+ tests: "~571"
+ mingw32_schannel_nozlib:
+ name: 32-bit Schannel/SSPI/WinIDN w/o zlib
+ container_img: ghcr.io/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 --with-schannel --with-winidn --without-zlib --without-libpsl
+ tests: "!203 !1143"
+ mingw64_schannel_nozlib:
+ name: 64-bit Schannel/SSPI/WinIDN w/o zlib
+ container_img: ghcr.io/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 --with-schannel --with-winidn --without-zlib --without-libpsl
+ tests: "!203 !1143"
+ container:
+ image: $(container_img)
+ env:
+ MSYS2_PATH_TYPE: inherit
+ steps:
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && $(prepare)"
+ displayName: 'prepare'
+ condition: variables.prepare
+ retryCountOnTaskFailure: 3
+
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && autoreconf -fi && ./configure $(configure)"
+ displayName: 'configure $(name)'
+
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make V=1 && make V=1 examples && cd tests && make V=1"
+ displayName: 'compile'
+
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make V=1 install && PATH=/usr/bin:/bin find . -type f -path '*/.libs/*.exe' -print -execdir mv -t .. {} \;"
+ displayName: 'install'
+
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make V=1 test-ci"
+ displayName: 'test'
+ env:
+ AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+ TFLAGS: "-ac /usr/bin/curl.exe !IDN !SCP ~612 $(tests)"
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 11bb0ef7b..e7ddc27d1 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -96,7 +96,7 @@ commands:
- run:
command: |
autoreconf -fi
- ./configure --enable-warnings --enable-maintainer-mode --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 --disable-unix-sockets --disable-shared --without-brotli --without-gssapi --without-libidn2 --without-libpsl --without-librtmp --without-libssh2 --without-nghttp2 --without-ntlm-auth --without-ssl --without-zlib --enable-debug CFLAGS='-Wno-vla -mmacosx-version-min=10.15'
+ ./configure --enable-warnings --enable-maintainer-mode --disable-dict --disable-file --disable-ftp --disable-gopher --disable-imap --disable-ldap --disable-mqtt --disable-pop3 --disable-rtsp --disable-smb --disable-smtp --disable-telnet --disable-tftp --disable-unix-sockets --disable-shared --without-brotli --without-gssapi --without-libidn2 --without-libpsl --without-librtmp --without-libssh2 --without-nghttp2 --without-ssl --without-zlib --enable-debug CFLAGS='-Wno-vla -mmacosx-version-min=10.15'
configure-macos-securetransport-http2:
steps:
@@ -149,7 +149,7 @@ commands:
steps:
- run:
command: |
- sudo apt-get update && sudo apt-get install -y libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev python3-pip
+ sudo apt-get update && sudo apt-get install -y libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev python3-pip libpsl-dev
sudo python3 -m pip install impacket
install-deps-brew:
@@ -157,7 +157,7 @@ commands:
- run:
command: |
# Drop libressl as long as we're not trying to build it
- echo libtool autoconf automake pkg-config nghttp2 libssh2 openssl libssh c-ares | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
+ echo libtool autoconf automake pkg-config nghttp2 libssh2 openssl libssh c-ares libpsl | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
while [ $? -eq 0 ]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
sudo python3 -m pip install impacket
@@ -249,6 +249,7 @@ jobs:
executor: ubuntu
steps:
- checkout
+ - install-deps
- configure
- build
- test
@@ -284,6 +285,7 @@ jobs:
executor: ubuntu
steps:
- checkout
+ - install-deps
- install-cares
- configure-cares
- build
@@ -293,6 +295,7 @@ jobs:
executor: ubuntu
steps:
- checkout
+ - install-deps
- install-libssh
- configure-libssh
- build
@@ -304,6 +307,7 @@ jobs:
resource_class: arm.medium
steps:
- checkout
+ - install-deps
- configure
- build
- test
@@ -314,6 +318,7 @@ jobs:
resource_class: arm.medium
steps:
- checkout
+ - install-deps
- install-cares
- configure-cares-debug
- build
@@ -527,9 +532,9 @@ workflows:
# There are problem linking with LibreSSL on the CI boxes that prevent this
# from working.
- #macos-x86-http-libressl-http2:
- # jobs:
- # - macos-x86-http-libressl-http2
+ # macos-x86-http-libressl-http2:
+ # jobs:
+ # - macos-x86-http-libressl-http2
macos-x86-http-torture:
jobs:
diff --git a/.cirrus.yml b/.cirrus.yml
index ae7d8591d..05c92756a 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -32,7 +32,7 @@ freebsd_task:
'.azure-pipelines.yml',
'.circleci/**',
'.github/**',
- 'appveyor.yml',
+ 'appveyor.*',
'CMake/**',
'packages/**',
'plan9/**',
@@ -43,9 +43,9 @@ freebsd_task:
name: FreeBSD
matrix:
- - name: FreeBSD 13.2
+ - name: FreeBSD 14.0
freebsd_instance:
- image_family: freebsd-13-2
+ image_family: freebsd-14-0
env:
CIRRUS_CLONE_DEPTH: 10
@@ -54,18 +54,18 @@ freebsd_task:
pkginstall_script:
- pkg update -f
- - pkg install -y autoconf automake libtool pkgconf brotli openldap26-client heimdal libpsl libssh2 openssh-portable libidn2 librtmp libnghttp2 nghttp2 stunnel py39-openssl py39-impacket py39-cryptography
+ - pkg install -y autoconf automake libtool pkgconf brotli openldap26-client heimdal libpsl libssh2 libidn2 librtmp libnghttp2 nghttp2 stunnel py39-openssl py39-impacket py39-cryptography libpsl
- pkg delete -y curl
configure_script:
- autoreconf -fi
# Building with the address sanitizer is causing unexplainable test issues due to timeouts
- #- case `uname -r` in
- # 12.2*)
- # export CC=clang;
- # export CFLAGS="-fsanitize=address,undefined,signed-integer-overflow -fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security -Werror=array-bounds -g";
- # export CXXFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security -Werror=array-bounds -g";
- # export LDFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined,integer" ;;
- # esac
+ # - case `uname -r` in
+ # 12.2*)
+ # export CC=clang;
+ # export CFLAGS="-fsanitize=address,undefined,signed-integer-overflow -fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security -Werror=array-bounds -g";
+ # export CXXFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security -Werror=array-bounds -g";
+ # export LDFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined,integer" ;;
+ # esac
- ./configure --prefix="${HOME}"/install --enable-debug --with-openssl --with-libssh2 --with-brotli --with-gssapi --with-libidn2 --enable-manual --enable-ldap --enable-ldaps --with-librtmp --with-libpsl --with-nghttp2 || { tail -300 config.log; false; }
compile_script:
- make V=1 && make V=1 examples && cd tests && make V=1
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..5ace4600a
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 31198b476..cef2789d8 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -7,487 +7,252 @@
# triaging, but is intended to add labels to the easy cases. If the matching
# language becomes more powerful, more cases should be able to be handled.
#
-# Labels are added in two ways: the AnyGlobToAllFiles ones are added if all the
-# files fit into the category, and the AnyGlobToAnyFile ones are added as long
-# as any file matches. The first ones are for "major" categories (the PR is all
-# about that one topic, like HTTP/3), while the second ones are "addendums"
-# that give useful information about a PR that's really mostly something else
-# (e.g. CI if the PR also touches CI jobs).
+# Labels are added in two ways: the any-glob-to-all-files ones are added if all
+# the files fit into the category, and the any-glob-to-any-file ones are added
+# as long as any file matches. The first ones are for "major" categories (the
+# PR is all about that one topic, like HTTP/3), while the second ones are
+# "addendums" that give useful information about a PR that's really mostly
+# something else (e.g. CI if the PR also touches CI jobs).
+#
+# N.B. any-glob-to-all-files is misnamed; it acts like one-glob-to-all-files.
+# Therefore, to get any-glob-to-all-files semantics, there must be a single glob
+# with all matching patterns within braces.
+#
+# See https://github.com/actions/labeler/ for documentation on this file.
appleOS:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - '.github/workflows/macos.yml'
- - 'lib/config-mac.h'
- - 'lib/macos*'
- - 'lib/vtls/sectransp*'
- - 'm4/curl-sectransp.m4'
- - 'MacOSX-Framework'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{.github/workflows/macos.yml,lib/config-mac.h,lib/macos*,lib/vtls/sectransp*,m4/curl-sectransp.m4,MacOSX-Framework}'
authentication:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/mk-ca-bundle.1'
- - 'docs/libcurl/opts/CURLINFO_HTTPAUTH*'
- - 'docs/libcurl/opts/CURLINFO_PROXYAUTH*'
- - 'docs/libcurl/opts/CURLOPT_KRB*'
- - 'docs/libcurl/opts/CURLOPT_SASL*'
- - 'docs/libcurl/opts/CURLOPT_SERVICE_NAME*'
- - 'docs/libcurl/opts/CURLOPT_USERNAME*'
- - 'docs/libcurl/opts/CURLOPT_USERPWD*'
- - 'docs/libcurl/opts/CURLOPT_XOAUTH*'
- - 'lib/*gssapi*'
- - 'lib/*krb5*'
- - 'lib/*ntlm*'
- - 'lib/curl_sasl.*'
- - 'lib/http_aws*'
- - 'lib/http_digest.*'
- - 'lib/http_negotiate.*'
- - 'lib/vauth/**'
- - 'tests/server/fake_ntlm.c'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/mk-ca-bundle.1,docs/libcurl/opts/CURLINFO_HTTPAUTH*,docs/libcurl/opts/CURLINFO_PROXYAUTH*,docs/libcurl/opts/CURLOPT_KRB*,docs/libcurl/opts/CURLOPT_SASL*,docs/libcurl/opts/CURLOPT_SERVICE_NAME*,docs/libcurl/opts/CURLOPT_USERNAME*,docs/libcurl/opts/CURLOPT_USERPWD*,docs/libcurl/opts/CURLOPT_XOAUTH*,lib/*gssapi*,lib/*krb5*,lib/*ntlm*,lib/curl_sasl.*,lib/http_aws*,lib/http_digest.*,lib/http_negotiate.*,lib/vauth/**,tests/server/fake_ntlm.c}'
build:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - '**/CMakeLists.txt'
- - '**/Makefile.am'
- - '**/Makefile.inc'
- - '**/Makefile.mk'
- - '**/*.m4'
- - '**/*.mk'
- - '*.m4'
- - 'docs/INSTALL.cmake'
- - 'lib/curl_config.h.cmake'
- - 'lib/libcurl*.in'
- - 'CMake/**'
- - 'CMakeLists.txt'
- - 'configure.ac'
- - 'm4/**'
- - 'MacOSX-Framework'
- - 'Makefile.*'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
- - 'libcurl.def'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{**/CMakeLists.txt,**/Makefile.am,**/Makefile.inc,**/Makefile.mk,**/*.m4,**/*.mk,*.m4,docs/INSTALL.cmake,lib/curl_config.h.cmake,lib/libcurl*.in,CMake/**,CMakeLists.txt,configure.ac,m4/**,MacOSX-Framework,Makefile.*,packages/**,plan9/**,projects/**,winbuild/**,libcurl.def}'
CI:
-- all:
- - changed-files:
- - AnyGlobToAnyFile:
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - '.github/**'
- - 'appveyor.yml'
- - 'scripts/ci*'
- - 'tests/azure.pm'
- - 'tests/appveyor.pm'
- - 'tests/CI.md'
+ - all:
+ - changed-files:
+ - any-glob-to-any-file:
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - '.github/**'
+ - 'appveyor.*'
+ - 'scripts/ci*'
+ - 'tests/azure.pm'
+ - 'tests/appveyor.pm'
+ - 'tests/CI.md'
cmake:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - '**/CMakeLists.txt'
- - 'CMake/**'
- - 'docs/INSTALL.cmake'
- - 'lib/curl_config.h.cmake'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{**/CMakeLists.txt,CMake/**,docs/INSTALL.cmake,lib/curl_config.h.cmake}'
cmdline tool:
-- all:
- - changed-files:
- - AnyGlobToAnyFile:
- - 'docs/cmdline-opts/**'
- - 'src/**'
+ - all:
+ - changed-files:
+ - any-glob-to-any-file:
+ - 'docs/cmdline-opts/**'
+ - 'src/**'
connecting & proxies:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/CONNECTION-FILTERS.md'
- - 'docs/examples/ipv6.c'
- - 'docs/libcurl/opts/CURLINFO_CONNECT*'
- - 'docs/libcurl/opts/CURLINFO_PROXY*'
- - 'docs/libcurl/opts/CURLOPT_ADDRESS*'
- - 'docs/libcurl/opts/CURLOPT_CONNECT*'
- - 'docs/libcurl/opts/CURLOPT_HAPROXY*'
- - 'docs/libcurl/opts/CURLOPT_OPENSOCKET*'
- - 'docs/libcurl/opts/CURLOPT_PRE_PROXY*'
- - 'docs/libcurl/opts/CURLOPT_PROXY*'
- - 'docs/libcurl/opts/CURLOPT_SOCKOPT*'
- - 'docs/libcurl/opts/CURLOPT_SOCKS*'
- - 'docs/libcurl/opts/CURLOPT_TCP*'
- - 'docs/libcurl/opts/CURLOPT_TIMEOUT*'
- - 'lib/cf-*proxy.*'
- - 'lib/cf-socket.*'
- - 'lib/cfilters.*'
- - 'lib/conncache.*'
- - 'lib/connect.*'
- - 'lib/http_proxy.*'
- - 'lib/if2ip.*'
- - 'lib/noproxy.*'
- - 'lib/socks.*'
- - 'tests/server/socksd.c'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/CONNECTION-FILTERS.md,docs/examples/ipv6.c,docs/libcurl/opts/CURLINFO_CONNECT*,docs/libcurl/opts/CURLINFO_PROXY*,docs/libcurl/opts/CURLOPT_ADDRESS*,docs/libcurl/opts/CURLOPT_CONNECT*,docs/libcurl/opts/CURLOPT_HAPROXY*,docs/libcurl/opts/CURLOPT_OPENSOCKET*,docs/libcurl/opts/CURLOPT_PRE_PROXY*,docs/libcurl/opts/CURLOPT_PROXY*,docs/libcurl/opts/CURLOPT_SOCKOPT*,docs/libcurl/opts/CURLOPT_SOCKS*,docs/libcurl/opts/CURLOPT_TCP*,docs/libcurl/opts/CURLOPT_TIMEOUT*,lib/cf-*proxy.*,lib/cf-socket.*,lib/cfilters.*,lib/conncache.*,lib/connect.*,lib/http_proxy.*,lib/if2ip.*,lib/noproxy.*,lib/socks.*,tests/server/socksd.c}'
cookies:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/HTTP-COOKIES.md'
- - 'docs/cmdline-opts/cookie*'
- - 'docs/cmdline-opts/junk-session-cookies.d'
- - 'docs/libcurl/opts/CURLINFO_COOKIE*'
- - 'docs/libcurl/opts/CURLOPT_COOKIE*'
- - 'docs/examples/cookie_interface.c'
- - 'lib/cookie.*'
- - 'lib/psl.*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/HTTP-COOKIES.md,docs/cmdline-opts/cookie*,docs/cmdline-opts/junk-session-cookies.d,docs/libcurl/opts/CURLINFO_COOKIE*,docs/libcurl/opts/CURLOPT_COOKIE*,docs/examples/cookie_interface.c,lib/cookie.*,lib/psl.*}'
cryptography:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/CIPHERS.md'
- - 'docs/RUSTLS.md'
- - 'docs/libcurl/opts/CURLOPT_EGDSOCKET*'
- - 'lib/*sha256*'
- - 'lib/curl_des.*'
- - 'lib/curl_hmac.*'
- - 'lib/curl_md?.*'
- - 'lib/md?.*'
- - 'lib/rand.*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/CIPHERS.md,docs/RUSTLS.md,docs/libcurl/opts/CURLOPT_EGDSOCKET*,lib/*sha256*,lib/curl_des.*,lib/curl_hmac.*,lib/curl_md?.*,lib/md?.*,lib/rand.*}'
DICT:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'lib/dict.*'
- - 'tests/dictserver.py'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{lib/dict.*,tests/dictserver.py}'
documentation:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - '**/*.md'
- - '**/*.txt'
- - '**/*.1'
- - '**/*.3'
- - 'CHANGES'
- - 'docs/**'
- - 'GIT-INFO'
- - 'LICENSES/**'
- - 'README'
- - 'RELEASE-NOTES'
- - AllGlobsToAllFiles:
- # negative matches
- - '!**/CMakeLists.txt'
- - '!**/Makefile.am'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{**/*.md,**/*.txt,**/*.1,**/*.3,CHANGES,docs/**,GIT-INFO,LICENSES/**,README,RELEASE-NOTES}'
+ - all-globs-to-all-files:
+ # negative matches
+ - '!**/CMakeLists.txt'
+ - '!**/Makefile.am'
FTP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/libcurl/opts/CURLINFO_FTP*'
- - 'docs/libcurl/opts/CURLOPT_FTP*'
- - 'docs/libcurl/opts/CURLOPT_WILDCARDMATCH*'
- - 'docs/examples/ftp*'
- - 'lib/curl_fnmatch.*'
- - 'lib/curl_range.*'
- - 'lib/ftp*'
- - 'tests/ftp*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/libcurl/opts/CURLINFO_FTP*,docs/libcurl/opts/CURLOPT_FTP*,docs/libcurl/opts/CURLOPT_WILDCARDMATCH*,docs/examples/ftp*,lib/curl_fnmatch.*,lib/curl_range.*,lib/ftp*,tests/ftp*'
GOPHER:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'lib/gopher*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{lib/gopher*}'
HTTP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/examples/hsts*'
- - 'docs/examples/http-*'
- - 'docs/examples/httpput*'
- - 'docs/examples/https*'
- - 'docs/examples/*post*'
- - 'docs/HSTS.md'
- - 'docs/HTTP-COOKIES.md'
- - 'docs/libcurl/opts/CURLINFO_COOKIE*'
- - 'docs/libcurl/opts/CURLOPT_COOKIE*'
- - 'docs/libcurl/opts/CURLINFO_HTTP_**'
- - 'docs/libcurl/opts/CURLINFO_REDIRECT*'
- - 'docs/libcurl/opts/CURLINFO_REFER*'
- - 'docs/libcurl/opts/CURLOPT_FOLLOWLOCATION*'
- - 'docs/libcurl/opts/CURLOPT_HSTS*'
- - 'docs/libcurl/opts/CURLOPT_HTTP*'
- - 'docs/libcurl/opts/CURLOPT_POST.*'
- - 'docs/libcurl/opts/CURLOPT_POSTFIELD*'
- - 'docs/libcurl/opts/CURLOPT_POSTREDIR*'
- - 'docs/libcurl/opts/CURLOPT_REDIR*'
- - 'docs/libcurl/opts/CURLOPT_REFER*'
- - 'docs/libcurl/opts/CURLOPT_TRAILER*'
- - 'docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING*'
- - 'lib/cf-https*'
- - 'lib/cf-h1*'
- - 'lib/cf-h2*'
- - 'lib/cookie.*'
- - 'lib/http*'
- - 'tests/http*'
- - 'tests/http-server.pl'
- - 'tests/http/*'
- - 'tests/nghttp*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/examples/hsts*,docs/examples/http-*,docs/examples/httpput*,docs/examples/https*,docs/examples/*post*,docs/HSTS.md,docs/HTTP-COOKIES.md,docs/libcurl/opts/CURLINFO_COOKIE*,docs/libcurl/opts/CURLOPT_COOKIE*,docs/libcurl/opts/CURLINFO_HTTP_**,docs/libcurl/opts/CURLINFO_REDIRECT*,docs/libcurl/opts/CURLINFO_REFER*,docs/libcurl/opts/CURLOPT_FOLLOWLOCATION*,docs/libcurl/opts/CURLOPT_HSTS*,docs/libcurl/opts/CURLOPT_HTTP*,docs/libcurl/opts/CURLOPT_POST.*,docs/libcurl/opts/CURLOPT_POSTFIELD*,docs/libcurl/opts/CURLOPT_POSTREDIR*,docs/libcurl/opts/CURLOPT_REDIR*,docs/libcurl/opts/CURLOPT_REFER*,docs/libcurl/opts/CURLOPT_TRAILER*,docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING*,lib/cf-https*,lib/cf-h1*,lib/cf-h2*,lib/cookie.*,lib/http*,tests/http*,tests/http-server.pl,tests/http/*,tests/nghttp*}'
HTTP/2:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'CMake/FindNGHTTP2.cmake'
- - 'CMake/FindQUICHE.cmake'
- - 'docs/HTTP2.md'
- - 'docs/libcurl/opts/CURLOPT_STREAM*'
- - 'docs/examples/http2*'
- - 'lib/http2*'
- - 'tests/http2-server.pl'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{CMake/FindNGHTTP2.cmake,CMake/FindQUICHE.cmake,docs/HTTP2.md,docs/libcurl/opts/CURLOPT_STREAM*,docs/examples/http2*,lib/http2*,tests/http2-server.pl}'
HTTP/3:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - '.github/workflows/ngtcp2*'
- - '.github/workflows/quiche*'
- - 'CMake/FindMSH3.cmake'
- - 'CMake/FindNGHTTP3.cmake'
- - 'CMake/FindNGTCP2.cmake'
- - 'docs/HTTP3.md'
- - 'docs/examples/http3*'
- - 'lib/vquic/**'
- - 'tests/http3-server.pl'
- - 'tests/nghttpx.conf'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{.github/workflows/ngtcp2*,.github/workflows/quiche*,CMake/FindMSH3.cmake,CMake/FindNGHTTP3.cmake,CMake/FindNGTCP2.cmake,docs/HTTP3.md,docs/examples/http3*,lib/vquic/**,tests/http3-server.pl,tests/nghttpx.conf}'
Hyper:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/HYPER.md'
- - 'lib/c-hyper.*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/HYPER.md,lib/c-hyper.*}'
IMAP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'lib/imap*'
- - 'docs/examples/imap*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{lib/imap*,docs/examples/imap*}'
LDAP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'lib/*ldap*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{lib/*ldap*}'
libcurl API:
-- all:
- - changed-files:
- - AnyGlobToAnyFile:
- - 'docs/libcurl/ABI.md'
- - 'docs/libcurl/curl_*.3'
- - 'include/curl/**'
+ - all:
+ - changed-files:
+ - any-glob-to-any-file:
+ - 'docs/libcurl/ABI.md'
+ - 'docs/libcurl/curl_*.3'
+ - 'include/curl/**'
logging:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/cmdline-opts/trace*'
- - 'docs/libcurl/curl_global_trace*'
- - 'lib/curl_trc*'
- - 'tests/http/test_15_tracing.py'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/cmdline-opts/trace*,docs/libcurl/curl_global_trace*,lib/curl_trc*,tests/http/test_15_tracing.py}'
MIME:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/libcurl/curl_form*'
- - 'docs/libcurl/curl_mime_*'
- - 'docs/libcurl/opts/CURLOPT_MIME*'
- - 'docs/libcurl/opts/CURLOPT_HTTPPOST*'
- - 'lib/formdata*'
- - 'lib/mime*'
- - 'src/tool_formparse.*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/libcurl/curl_form*,docs/libcurl/curl_mime_*,docs/libcurl/opts/CURLOPT_MIME*,docs/libcurl/opts/CURLOPT_HTTPPOST*,lib/formdata*,lib/mime*,src/tool_formparse.*}'
MQTT:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/MQTT.md'
- - 'lib/mqtt*'
- - 'tests/server/mqttd.c'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/MQTT.md,lib/mqtt*,tests/server/mqttd.c}'
name lookup:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/examples/resolve.c'
- - 'docs/libcurl/opts/CURLINFO_NAMELOOKUP*'
- - 'docs/libcurl/opts/CURLOPT_DNS*'
- - 'docs/libcurl/opts/CURLOPT_DOH*'
- - 'docs/libcurl/opts/CURLOPT_RESOLVE*'
- - 'lib/asyn*'
- - 'lib/curl_gethostname.*'
- - 'lib/doh*'
- - 'lib/host*'
- - 'lib/idn*'
- - 'lib/inet_pton.*'
- - 'lib/socketpair*'
- - 'tests/server/resolve.c'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/examples/resolve.c,docs/libcurl/opts/CURLINFO_NAMELOOKUP*,docs/libcurl/opts/CURLOPT_DNS*,docs/libcurl/opts/CURLOPT_DOH*,docs/libcurl/opts/CURLOPT_RESOLVE*,lib/asyn*,lib/curl_gethostname.*,lib/doh*,lib/host*,lib/idn*,lib/inet_pton.*,lib/socketpair*,tests/server/resolve.c}'
POP3:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/examples/pop3*'
- - 'lib/pop3.*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/examples/pop3*,lib/pop3.*}'
RTMP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'lib/curl_rtmp.*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{lib/curl_rtmp.*}'
RTSP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/libcurl/opts/CURLINFO_RTSP*'
- - 'docs/libcurl/opts/CURLOPT_RTSP*'
- - 'lib/rtsp.*'
- - 'tests/rtspserver.pl'
- - 'tests/server/rtspd.c'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/libcurl/opts/CURLINFO_RTSP*,docs/libcurl/opts/CURLOPT_RTSP*,lib/rtsp.*,tests/rtspserver.pl,tests/server/rtspd.c}'
SCP/SFTP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'CMake/FindLibSSH2.cmake'
- - 'docs/libcurl/opts/CURLOPT_SSH*'
- - 'docs/examples/sftp*'
- - 'lib/vssh/**'
- - 'tests/sshhelp.pm'
- - 'tests/sshserver.pl'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{CMake/FindLibSSH2.cmake,docs/libcurl/opts/CURLOPT_SSH*,docs/examples/sftp*,lib/vssh/**,tests/sshhelp.pm,tests/sshserver.pl}'
script:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - '**/*.pl'
- - '**/*.sh'
- - 'curl-config.in'
- - 'docs/curl-config.1'
- - 'docs/mk-ca-bundle.1'
- - 'docs/THANKS-filter'
- - 'scripts/**'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{**/*.pl,**/*.sh,curl-config.in,docs/curl-config.1,docs/mk-ca-bundle.1,docs/THANKS-filter,scripts/**}'
SMB:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'lib/smb.*'
- - 'tests/smbserver.py'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{lib/smb.*,tests/smbserver.py}'
SMTP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/examples/smtp-*'
- - 'docs/libcurl/opts/CURLOPT_MAIL*'
- - 'lib/smtp.*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/examples/smtp-*,docs/libcurl/opts/CURLOPT_MAIL*,lib/smtp.*}'
tests:
-- all:
- - changed-files:
- - AnyGlobToAnyFile:
- - 'tests/**'
+ - all:
+ - changed-files:
+ - any-glob-to-any-file:
+ - 'tests/**'
TFTP:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'lib/tftp.*'
- - 'tests/tftpserver.pl'
- - 'tests/server/tftp*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{lib/tftp.*,tests/tftpserver.pl,tests/server/tftp*}'
TLS:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'CMake/FindBearSSL.cmake'
- - 'CMake/FindMbedTLS.cmake'
- - 'CMake/FindWolfSSL.cmake'
- - 'docs/examples/ssl*'
- - 'docs/examples/*ssl.*'
- - 'docs/examples/*tls.*'
- - 'docs/SSL*'
- - 'docs/libcurl/curl_global_sslset*'
- - 'docs/libcurl/opts/CURLINFO_CA*'
- - 'docs/libcurl/opts/CURLINFO_CERT*'
- - 'docs/libcurl/opts/CURLINFO_SSL*'
- - 'docs/libcurl/opts/CURLINFO_TLS*'
- - 'docs/libcurl/opts/CURLOPT_CA*'
- - 'docs/libcurl/opts/CURLOPT_CERT*'
- - 'docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY*'
- - 'docs/libcurl/opts/CURLOPT_SSL*'
- - 'docs/libcurl/opts/CURLOPT_TLS*'
- - 'docs/libcurl/opts/CURLOPT_USE_SSL*'
- - 'lib/vtls/**'
- - 'm4/curl-bearssl.m4'
- - 'm4/curl-gnutls.m4'
- - 'm4/curl-mbedtls.m4'
- - 'm4/curl-openssl.m4'
- - 'm4/curl-rustls.m4'
- - 'm4/curl-schannel.m4'
- - 'm4/curl-sectransp.m4'
- - 'm4/curl-wolfssl.m4'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{CMake/FindBearSSL.cmake,CMake/FindMbedTLS.cmake,CMake/FindWolfSSL.cmake,docs/examples/ssl*,docs/examples/*ssl.*,docs/examples/*tls.*,docs/SSL*,docs/libcurl/curl_global_sslset*,docs/libcurl/opts/CURLINFO_CA*,docs/libcurl/opts/CURLINFO_CERT*,docs/libcurl/opts/CURLINFO_SSL*,docs/libcurl/opts/CURLINFO_TLS*,docs/libcurl/opts/CURLOPT_CA*,docs/libcurl/opts/CURLOPT_CERT*,docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY*,docs/libcurl/opts/CURLOPT_SSL*,docs/libcurl/opts/CURLOPT_TLS*,docs/libcurl/opts/CURLOPT_USE_SSL*,lib/vtls/**,m4/curl-bearssl.m4,m4/curl-gnutls.m4,m4/curl-mbedtls.m4,m4/curl-openssl.m4,m4/curl-rustls.m4,m4/curl-schannel.m4,m4/curl-sectransp.m4,m4/curl-wolfssl.m4}'
URL:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/libcurl/curl_url*'
- - 'docs/URL-SYNTAX.md'
- - 'docs/examples/parseurl*'
- - 'include/curl/urlapi.h'
- - 'lib/urlapi*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/libcurl/curl_url*,docs/URL-SYNTAX.md,docs/examples/parseurl*,include/curl/urlapi.h,lib/urlapi*}'
WebSocket:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - 'docs/WEBSOCKET.md*'
- - 'docs/examples/websocket*'
- - 'docs/libcurl/curl_ws_*'
- - 'docs/libcurl/libcurl-ws*'
- - 'docs/libcurl/opts/CURLOPT_WS_*'
- - 'include/curl/websockets.h'
- - 'lib/ws.*'
- - 'tests/http/clients/ws*'
- - 'tests/http/test_20_websockets.py'
- - 'tests/http/testenv/ws*'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{docs/WEBSOCKET.md*,docs/examples/websocket*,docs/libcurl/curl_ws_*,docs/libcurl/libcurl-ws*,docs/libcurl/opts/CURLOPT_WS_*,include/curl/websockets.h,lib/ws.*,tests/http/clients/ws*,tests/http/test_20_websockets.py,tests/http/testenv/ws*}'
Windows:
-- all:
- - changed-files:
- - AnyGlobToAllFiles:
- - '**/Makefile.mk'
- - 'appveyor.yml'
- - 'CMake/Platforms/WindowsCache.cmake'
- - 'lib/*win32*'
- - 'lib/curl_multibyte.*'
- - 'lib/rename.*'
- - 'lib/vtls/schannel*'
- - 'm4/curl-schannel.m4'
- - 'projects/**'
- - 'src/tool_doswin.c'
- - 'winbuild/**'
- - 'libcurl.def'
+ - all:
+ - changed-files:
+ - any-glob-to-all-files:
+ - '{appveyor.*,CMake/Platforms/WindowsCache.cmake,lib/*win32*,lib/curl_multibyte.*,lib/rename.*,lib/vtls/schannel*,m4/curl-schannel.m4,projects/**,src/tool_doswin.c,winbuild/**,libcurl.def}'
diff --git a/.github/scripts/badwords.pl b/.github/scripts/badwords.pl
new file mode 100755
index 000000000..ffebad94e
--- /dev/null
+++ b/.github/scripts/badwords.pl
@@ -0,0 +1,67 @@
+#!/usr/bin/perl
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+#
+# bad[:=]correct
+#
+# If separator is '=', the string will be compared case sensitively.
+# If separator is ':', the check is done case insensitively.
+#
+my $w;
+while(<STDIN>) {
+ chomp;
+ if($_ =~ /^#/) {
+ next;
+ }
+ if($_ =~ /^([^:=]*)([:=])(.*)/) {
+ my ($bad, $sep, $better)=($1, $2, $3);
+ push @w, $bad;
+ $alt{$bad} = $better;
+ if($sep eq "=") {
+ $exactcase{$bad} = 1;
+ }
+ }
+}
+
+my $errors;
+
+sub file {
+ my ($f) = @_;
+ my $l = 0;
+ open(F, "<$f");
+ while(<F>) {
+ my $in = $_;
+ $l++;
+ chomp $in;
+ if($in =~ /^ /) {
+ next;
+ }
+ # remove the link part
+ $in =~ s/(\[.*\])\(.*\)/$1/g;
+ # remove backticked texts
+ $in =~ s/\`.*\`//g;
+ foreach my $w (@w) {
+ my $case = $exactcase{$w};
+ if(($in =~ /^(.*)$w/i && !$case) ||
+ ($in =~ /^(.*)$w/ && $case) ) {
+ my $p = $1;
+ my $c = length($p)+1;
+ print STDERR "$f:$l:$c: error: found bad word \"$w\"\n";
+ printf STDERR " %4d | $in\n", $l;
+ printf STDERR " | %*s^%s\n", length($p), " ",
+ "~" x (length($w)-1);
+ printf STDERR " maybe use \"%s\" instead?\n", $alt{$w};
+ $errors++;
+ }
+ }
+ }
+ close(F);
+}
+
+my @files = @ARGV;
+
+foreach my $each (@files) {
+ file($each);
+}
+exit $errors;
diff --git a/.github/scripts/badwords.txt b/.github/scripts/badwords.txt
new file mode 100644
index 000000000..0e6be76c6
--- /dev/null
+++ b/.github/scripts/badwords.txt
@@ -0,0 +1,46 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+#
+back-end:backend
+e-mail:email
+run-time:runtime
+set-up:setup
+tool chain:toolchain
+tool-chain:toolchain
+wild-card:wildcard
+wild card:wildcard
+i'm:I am
+you've:You have
+they've:They have
+they're:They are
+should've:should have
+don't:do not
+could've:could have
+doesn't:does not
+isn't:is not
+ a html: an html
+ a http: an http
+ a ftp: an ftp
+ url =URL
+internet\W=Internet
+isation:ization
+it's:it is
+there's:there is
+[^.]\. And: Rewrite it somehow?
+^(And|So|But) = Rewrite it somehow?
+\. But: Rewrite it somehow?
+file name :filename
+\. So : Rewrite without "so" ?
+ dir :directory
+you'd:you would
+you'll:you will
+can't:cannot
+that's:that is
+web page:webpage
+host name\W:hostname
+file name\W:filename
+didn't:did not
+doesn't:does not
+won't:will not
+couldn't:could not
diff --git a/.github/scripts/cleancmd.pl b/.github/scripts/cleancmd.pl
new file mode 100755
index 000000000..5d0fe2b2f
--- /dev/null
+++ b/.github/scripts/cleancmd.pl
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+#
+# Input: a cmdline docs markdown, it gets modfied *in place*
+#
+# The main purpose is to strip off the leading meta-data part, but also to
+# clean up whatever else the spell checker might have a problem with that we
+# still deem is fine.
+
+my $header = 1;
+while(1) {
+ # set this if the markdown has no meta-data header to skip
+ if($ARGV[0] eq "--no-header") {
+ shift @ARGV;
+ $header = 0;
+ }
+ else {
+ last;
+ }
+}
+
+my $f = $ARGV[0];
+
+open(F, "<$f") or die;
+
+my $ignore = $header;
+my $sepcount = 0;
+my @out;
+while(<F>) {
+ if(/^---/ && $header) {
+ if(++$sepcount == 2) {
+ $ignore = 0;
+ }
+ next;
+ }
+ next if($ignore);
+
+ # strip out all long command line options
+ $_ =~ s/--[a-z0-9-]+//g;
+
+ # strip out https URLs, we don't want them spellchecked
+ $_ =~ s!https://[a-z0-9\#_/.-]+!!gi;
+
+ push @out, $_;
+}
+close(F);
+
+open(O, ">$f") or die;
+print O @out;
+close(O);
diff --git a/.github/scripts/cleanspell.pl b/.github/scripts/cleanspell.pl
index 329a97240..06648a3f9 100755
--- a/.github/scripts/cleanspell.pl
+++ b/.github/scripts/cleanspell.pl
@@ -71,6 +71,7 @@ while(<F>) {
$_ =~ s/curl_url_(dup)//g;
$_ =~ s/curl_pushheader_by(name|num)//g;
$_ =~ s/libcurl-(env|ws)//g;
+ $_ =~ s/libcurl\\-(env|ws)//g;
$_ =~ s/(^|\W)((tftp|https|http|ftp):\/\/[a-z0-9\-._~%:\/?\#\[\]\@!\$&'()*+,;=]+)//gi;
print O $_;
}
diff --git a/.github/scripts/codespell-ignore.txt b/.github/scripts/codespell-ignore.txt
new file mode 100644
index 000000000..3832cec4d
--- /dev/null
+++ b/.github/scripts/codespell-ignore.txt
@@ -0,0 +1,15 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+clen
+te
+wont
+statics
+nome
+wast
+numer
+anull
+inout
+msdos
+ba
+fo
diff --git a/.github/scripts/spellcheck.words b/.github/scripts/spellcheck.words
index 8856afc31..4495454e1 100644
--- a/.github/scripts/spellcheck.words
+++ b/.github/scripts/spellcheck.words
@@ -50,6 +50,7 @@ backend
backends
backoff
backticks
+balancers
Baratov
basename
bashrc
@@ -83,6 +84,7 @@ CCC
CDN
CentOS
CFLAGS
+cflags
CGI's
CHACHA
chacha
@@ -109,6 +111,7 @@ clientp
cliget
closesocket
CMake
+CMake's
cmake
cmake's
CMakeLists
@@ -138,10 +141,11 @@ cshrc
CTRL
cURL
CURLcode
+curldown
CURLE
CURLH
-CURLINFO
curlimages
+CURLINFO
curlrc
curltest
customizable
@@ -161,8 +165,8 @@ deepcode
DELE
DER
deselectable
-Deserialized
deserialization
+Deserialized
destructor
detections
dev
@@ -285,6 +289,7 @@ GSS
GSSAPI
GTFO
Guenter
+GUIs
Gunderson
Gustafsson
gzip
@@ -350,11 +355,10 @@ interoperable
interoperates
IoT
ipadOS
+IPCXN
IPFS
-IPNS
ipld
-trustless
-IPCXN
+IPNS
IPv
IPv4
IPv4/6
@@ -444,6 +448,7 @@ Makefile
makefiles
malloc
mallocs
+manpage
maprintf
Marek
Mavrogiannopoulos
@@ -804,6 +809,7 @@ TPF
TrackMemory
transcode
Tru
+trustless
Tse
Tsujikawa
TTL
@@ -826,6 +832,7 @@ unencoded
unencrypted
unescape
Unglobbed
+Unicode
UNICOS
unix
UnixSockets
@@ -880,6 +887,7 @@ WB
web page
WebDAV
WebOS
+webpage
WebSocket
WEBSOCKET
WHATWG
@@ -898,6 +906,7 @@ winssl
Wireshark
wolfSSH
wolfSSL
+ws
WS
WSS
www
diff --git a/.github/scripts/spellcheck.yaml b/.github/scripts/spellcheck.yaml
index 4e4e13d48..5cf4f9a01 100644
--- a/.github/scripts/spellcheck.yaml
+++ b/.github/scripts/spellcheck.yaml
@@ -4,29 +4,29 @@
#
# Docs: https://github.com/UnicornGlobal/spellcheck-github-actions
matrix:
-- name: Markdown
- expect_match: false
- apsell:
- mode: en
- dictionary:
- wordlists:
- - wordlist.txt
- output: wordlist.dic
- encoding: utf-8
- pipeline:
- - pyspelling.filters.markdown:
- markdown_extensions:
- - markdown.extensions.extra:
- - pyspelling.filters.html:
- comments: true
- attributes:
- - title
- - alt
- ignores:
- - ':matches(code, pre)'
- - 'code'
- - 'pre'
- - 'strong'
- - 'em'
- sources:
- - '**/*.md|!docs/BINDINGS.md'
+ - name: Markdown
+ expect_match: false
+ apsell:
+ mode: en
+ dictionary:
+ wordlists:
+ - wordlist.txt
+ output: wordlist.dic
+ encoding: utf-8
+ pipeline:
+ - pyspelling.filters.markdown:
+ markdown_extensions:
+ - markdown.extensions.extra:
+ - pyspelling.filters.html:
+ comments: true
+ attributes:
+ - title
+ - alt
+ ignores:
+ - ':matches(code, pre)'
+ - 'code'
+ - 'pre'
+ - 'strong'
+ - 'em'
+ sources:
+ - '**/*.md|!docs/BINDINGS.md'
diff --git a/.github/scripts/verify-examples.pl b/.github/scripts/verify-examples.pl
new file mode 100755
index 000000000..28d24595f
--- /dev/null
+++ b/.github/scripts/verify-examples.pl
@@ -0,0 +1,110 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+my @files = @ARGV;
+my $cfile = "test.c";
+my $check = "./scripts/checksrc.pl";
+my $error;
+
+if($files[0] eq "-h") {
+ print "Usage: verify-synopsis [man pages]\n";
+ exit;
+}
+
+sub testcompile {
+ my $rc = system("gcc -c test.c -DCURL_DISABLE_TYPECHECK -DCURL_ALLOW_OLD_MULTI_SOCKET -DCURL_DISABLE_DEPRECATION -Wunused -Werror -Wno-unused-but-set-variable -I include") >> 8;
+ return $rc;
+}
+
+sub checksrc {
+ my $rc = system("$check test.c") >> 8;
+ return $rc;
+}
+
+sub extract {
+ my($f) = @_;
+ my $syn = 0;
+ my $l = 0;
+ my $iline = 0;
+ my $fail = 0;
+ open(F, "<$f") or die "failed opening input file $f : $!";
+ open(O, ">$cfile") or die "failed opening output file $cfile : $!";
+ print O "#include <curl/curl.h>\n";
+ while(<F>) {
+ $iline++;
+ if(/^.SH EXAMPLE/) {
+ $syn = 1
+ }
+ elsif($syn == 1) {
+ if(/^.nf/) {
+ $syn++;
+ print O "/* !checksrc! disable UNUSEDIGNORE all */\n";
+ print O "/* !checksrc! disable COPYRIGHT all */\n";
+ print O "/* !checksrc! disable FOPENMODE all */\n";
+ printf O "#line %d \"$f\"\n", $iline+1;
+ }
+ }
+ elsif($syn == 2) {
+ if(/^.fi/) {
+ last;
+ }
+ if(/(?<!\\)(?:\\{2})*\\(?!\\)/) {
+ print STDERR
+ "Error while processing file $f line $iline:\n$_" .
+ "Error: Single backslashes \\ are not properly shown in " .
+ "manpage EXAMPLE output unless they are escaped \\\\.\n";
+ $fail = 1;
+ $error = 1;
+ last;
+ }
+ # two backslashes become one
+ $_ =~ s/\\\\/\\/g;
+ print O $_;
+ $l++;
+ }
+ }
+ close(F);
+ close(O);
+
+ return ($fail ? 0 : $l);
+}
+
+my $count;
+for my $m (@files) {
+ #print "Verify $m\n";
+ my $out = extract($m);
+ if($out) {
+ $error |= testcompile($m);
+ $error |= checksrc($m);
+ }
+ $count++;
+}
+if(!$error) {
+ print "Verified $count man pages ok\n";
+}
+else {
+ print "Detected problems\n";
+}
+exit $error;
diff --git a/.github/scripts/verify-synopsis.pl b/.github/scripts/verify-synopsis.pl
new file mode 100755
index 000000000..9d3218503
--- /dev/null
+++ b/.github/scripts/verify-synopsis.pl
@@ -0,0 +1,80 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+my @files = @ARGV;
+my $cfile = "test.c";
+
+if($files[0] eq "-h") {
+ print "Usage: verify-synopsis [man pages]\n";
+ exit;
+}
+
+sub testcompile {
+ my $rc = system("gcc -c test.c -DCURL_DISABLE_TYPECHECK -DCURL_ALLOW_OLD_MULTI_SOCKET -I include") >> 8;
+ return $rc;
+}
+
+
+sub extract {
+ my($f) = @_;
+ my $syn = 0;
+ my $l = 0;
+ my $iline = 0;
+ open(F, "<$f");
+ open(O, ">$cfile");
+ while(<F>) {
+ $iline++;
+ if(/^.SH SYNOPSIS/) {
+ $syn = 1
+ }
+ elsif($syn == 1) {
+ if(/^.nf/) {
+ $syn++;
+ print O "#line $iline \"$f\"\n";
+ }
+ }
+ elsif($syn == 2) {
+ if(/^.fi/) {
+ last;
+ }
+ # turn the vararg argument into vararg
+ $_ =~ s/, parameter\)\;/, ...);/;
+ print O $_;
+ $l++;
+ }
+ }
+ close(F);
+ close(O);
+
+ return 0;
+}
+
+my $error;
+for my $m (@files) {
+ print "Verify $m\n";
+ extract($m);
+ $error |= testcompile($m);
+}
+exit $error;
diff --git a/.github/workflows/awslc.yml b/.github/workflows/awslc.yml
index 2c38ca0a3..485251641 100644
--- a/.github/workflows/awslc.yml
+++ b/.github/workflows/awslc.yml
@@ -7,31 +7,31 @@ name: Linux AWS-LC
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
# Hardcoded workflow filename as workflow name above is just Linux again
@@ -51,58 +51,58 @@ jobs:
timeout-minutes: 30
steps:
- - run: |
- sudo apt-get update --yes
- sudo apt-get install --yes libtool autoconf automake pkg-config stunnel4
- # ensure we don't pick up openssl in this build
- sudo apt remove --yes libssl-dev
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - name: cache awslc
- uses: actions/cache@v3
- id: cache-awslc
- env:
- cache-name: cache-awslc
- with:
- path: /home/runner/awslc
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.awslc-version }}
-
- - name: build awslc
- if: steps.cache-awslc.outputs.cache-hit != 'true'
- run: |
- curl -LOsSf --retry 6 --retry-connrefused --max-time 999 \
- https://github.com/awslabs/aws-lc/archive/refs/tags/v${{ env.awslc-version }}.tar.gz
- tar xzf v${{ env.awslc-version }}.tar.gz
- mkdir aws-lc-${{ env.awslc-version }}-build
- cd aws-lc-${{ env.awslc-version }}-build
- cmake -DCMAKE_INSTALL_PREFIX=$HOME/awslc ../aws-lc-${{ env.awslc-version }}
- cmake --build . --parallel
- cmake --install .
-
- - uses: actions/checkout@v4
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: |
- mkdir build
- cd build
- ../configure --enable-warnings --enable-werror --with-openssl=$HOME/awslc
- cd ..
- name: 'configure out-of-tree'
-
- - run: make -C build V=1
- name: 'make'
-
- - run: make -C build V=1 examples
- name: 'make examples'
-
- - run: make -C build V=1 -C tests
- name: 'make tests'
-
- - run: make -C build V=1 test-ci
- name: 'run tests'
+ - run: |
+ sudo apt-get update --yes
+ sudo apt-get install --yes libtool autoconf automake pkg-config stunnel4 libpsl-dev
+ # ensure we don't pick up openssl in this build
+ sudo apt remove --yes libssl-dev
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
+
+ - name: cache awslc
+ uses: actions/cache@v4
+ id: cache-awslc
+ env:
+ cache-name: cache-awslc
+ with:
+ path: /home/runner/awslc
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.awslc-version }}
+
+ - name: build awslc
+ if: steps.cache-awslc.outputs.cache-hit != 'true'
+ run: |
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 \
+ https://github.com/awslabs/aws-lc/archive/refs/tags/v${{ env.awslc-version }}.tar.gz
+ tar xzf v${{ env.awslc-version }}.tar.gz
+ mkdir aws-lc-${{ env.awslc-version }}-build
+ cd aws-lc-${{ env.awslc-version }}-build
+ cmake -DCMAKE_INSTALL_PREFIX=$HOME/awslc ../aws-lc-${{ env.awslc-version }}
+ cmake --build . --parallel
+ cmake --install .
+
+ - uses: actions/checkout@v4
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: |
+ mkdir build
+ cd build
+ ../configure --enable-warnings --enable-werror --with-openssl=$HOME/awslc
+ cd ..
+ name: 'configure out-of-tree'
+
+ - run: make -C build V=1
+ name: 'make'
+
+ - run: make -C build V=1 examples
+ name: 'make examples'
+
+ - run: make -C build V=1 -C tests
+ name: 'make tests'
+
+ - run: make -C build V=1 test-ci
+ name: 'run tests'
cmake:
name: awslc (cmake)
@@ -110,43 +110,43 @@ jobs:
timeout-minutes: 15
steps:
- - run: |
- sudo apt-get update
- sudo apt-get install cmake stunnel4
- # ensure we don't pick up openssl in this build
- sudo apt remove --yes libssl-dev
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - name: cache awslc
- uses: actions/cache@v3
- id: cache-awslc
- env:
- cache-name: cache-awslc
- with:
- path: /home/runner/awslc
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.awslc-version }}
-
- - name: build awslc
- if: steps.cache-awslc.outputs.cache-hit != 'true'
- run: |
- curl -LOsSf --retry 6 --retry-connrefused --max-time 999 \
- https://github.com/awslabs/aws-lc/archive/refs/tags/v${{ env.awslc-version }}.tar.gz
- tar xzf v${{ env.awslc-version }}.tar.gz
- mkdir aws-lc-${{ env.awslc-version }}-build
- cd aws-lc-${{ env.awslc-version }}-build
- cmake -DCMAKE_INSTALL_PREFIX=$HOME/awslc ../aws-lc-${{ env.awslc-version }}
- cmake --build . --parallel
- cmake --install .
-
- - uses: actions/checkout@v4
-
- # CMAKE_COMPILE_WARNING_AS_ERROR is available in cmake 3.24 or later
- - run: cmake -Bbuild -DOPENSSL_ROOT_DIR=$HOME/awslc -DBUILD_SHARED_LIBS=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=ON .
- name: 'cmake generate out-of-tree'
-
- - run: cmake --build build --parallel
- name: 'cmake build'
-
- - run: cmake --install build --prefix $HOME/curl --strip
- name: 'cmake install'
+ - run: |
+ sudo apt-get update
+ sudo apt-get install cmake stunnel4
+ # ensure we don't pick up openssl in this build
+ sudo apt remove --yes libssl-dev
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
+
+ - name: cache awslc
+ uses: actions/cache@v4
+ id: cache-awslc
+ env:
+ cache-name: cache-awslc
+ with:
+ path: /home/runner/awslc
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.awslc-version }}
+
+ - name: build awslc
+ if: steps.cache-awslc.outputs.cache-hit != 'true'
+ run: |
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 \
+ https://github.com/awslabs/aws-lc/archive/refs/tags/v${{ env.awslc-version }}.tar.gz
+ tar xzf v${{ env.awslc-version }}.tar.gz
+ mkdir aws-lc-${{ env.awslc-version }}-build
+ cd aws-lc-${{ env.awslc-version }}-build
+ cmake -DCMAKE_INSTALL_PREFIX=$HOME/awslc ../aws-lc-${{ env.awslc-version }}
+ cmake --build . --parallel
+ cmake --install .
+
+ - uses: actions/checkout@v4
+
+ # CMAKE_COMPILE_WARNING_AS_ERROR is available in cmake 3.24 or later
+ - run: cmake -Bbuild -DOPENSSL_ROOT_DIR=$HOME/awslc -DBUILD_SHARED_LIBS=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=ON .
+ name: 'cmake generate out-of-tree'
+
+ - run: cmake --build build --parallel
+ name: 'cmake build'
+
+ - run: cmake --install build --prefix $HOME/curl --strip
+ name: 'cmake install'
diff --git a/.github/workflows/badwords.yml b/.github/workflows/badwords.yml
new file mode 100644
index 000000000..fc0b52001
--- /dev/null
+++ b/.github/workflows/badwords.yml
@@ -0,0 +1,27 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: badwords
+
+on:
+ # Trigger the workflow on push or pull requests, but only for the
+ # master branch
+ push:
+ branches:
+ - master
+ - '*/ci'
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ check:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: check
+ run: ./.github/scripts/badwords.pl < .github/scripts/badwords.txt docs/*.md docs/libcurl/*.md docs/libcurl/opts/*.md
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index f5f969491..f98e4da42 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -7,35 +7,35 @@ name: CodeQL
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'docs/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'tests/data/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'docs/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'docs/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'tests/data/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'docs/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
schedule:
- cron: '0 0 * * 4'
@@ -50,31 +50,31 @@ jobs:
permissions:
security-events: write
steps:
- - name: Checkout repository
- uses: actions/checkout@v4
+ - name: Checkout repository
+ uses: actions/checkout@v4
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v2
- with:
- languages: cpp
- queries: security-extended
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: cpp
+ queries: security-extended
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v2
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v3
- # ℹ️ Command-line programs to run using the OS shell.
- # 📚 https://git.io/JvXDl
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://git.io/JvXDl
- # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
- #- run: |
- # make bootstrap
- # make release
+ # - run: |
+ # make bootstrap
+ # make release
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
new file mode 100644
index 000000000..2b095dae7
--- /dev/null
+++ b/.github/workflows/codespell.yml
@@ -0,0 +1,36 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: Codespell
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths:
+ - 'lib/**'
+ - 'src/**'
+ - 'include/**'
+ pull_request:
+ branches:
+ - master
+ - 'lib/**'
+ - 'src/**'
+ - 'include/**'
+
+jobs:
+ codespell:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: install
+ run: |
+ sudo apt-get update
+ sudo apt-get install codespell
+
+ - name: spellcheck
+ run: codespell --skip src/tool_hugehelp.c -I .github/scripts/codespell-ignore.txt include src lib
diff --git a/.github/workflows/configure-vs-cmake.yml b/.github/workflows/configure-vs-cmake.yml
index 3131bc128..dc2273f73 100644
--- a/.github/workflows/configure-vs-cmake.yml
+++ b/.github/workflows/configure-vs-cmake.yml
@@ -6,23 +6,23 @@ name: configure-vs-cmake
on:
push:
branches:
- - master
+ - master
paths:
- - '*.ac'
- - '**/*.m4'
- - '**/CMakeLists.txt'
- - 'lib/curl_config.h.cmake'
- - 'scripts/cmp-config.pl'
+ - '*.ac'
+ - '**/*.m4'
+ - '**/CMakeLists.txt'
+ - 'lib/curl_config.h.cmake'
+ - 'scripts/cmp-config.pl'
pull_request:
branches:
- - master
+ - master
paths:
- - '*.ac'
- - '**/*.m4'
- - '**/CMakeLists.txt'
- - 'lib/curl_config.h.cmake'
- - 'scripts/cmp-config.pl'
+ - '*.ac'
+ - '**/*.m4'
+ - '**/CMakeLists.txt'
+ - 'lib/curl_config.h.cmake'
+ - 'scripts/cmp-config.pl'
permissions: {}
@@ -30,16 +30,16 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - name: run configure --with-openssl
- run: |
- autoreconf -fi
- ./configure --with-openssl
+ - name: run configure --with-openssl
+ run: |
+ autoreconf -fi
+ ./configure --with-openssl --without-libpsl
- - name: run cmake
- run: |
- mkdir build && cd build && cmake ..
+ - name: run cmake
+ run: |
+ mkdir build && cd build && cmake ..
- - name: compare generated curl_config.h files
- run: ./scripts/cmp-config.pl lib/curl_config.h build/lib/curl_config.h
+ - name: compare generated curl_config.h files
+ run: ./scripts/cmp-config.pl lib/curl_config.h build/lib/curl_config.h
diff --git a/.github/workflows/distcheck.yml b/.github/workflows/distcheck.yml
index a63091bd9..15068b640 100644
--- a/.github/workflows/distcheck.yml
+++ b/.github/workflows/distcheck.yml
@@ -7,11 +7,11 @@ name: dist
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
pull_request:
branches:
- - master
+ - master
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
@@ -22,80 +22,101 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- - uses: actions/checkout@v4
-
- - run: sudo apt-get purge -y curl libcurl4 libcurl4-doc
- name: 'remove preinstalled curl libcurl4{-doc}'
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --without-ssl
- name: 'configure'
-
- - run: make V=1 && make V=1 clean
- name: 'make and clean'
-
- - run: ./maketgz 99.98.97
- name: 'maketgz'
-
- - uses: actions/upload-artifact@v3
- with:
- name: 'release-tgz'
- path: 'curl-99.98.97.tar.gz'
-
- - run: |
- echo "::stop-commands::$(uuidgen)"
- tar xvf curl-99.98.97.tar.gz
- pushd curl-99.98.97
- ./configure --prefix=$HOME/temp --without-ssl
- make
- make TFLAGS=1 test
- make install
- popd
- # basic check of the installed files
- bash scripts/installcheck.sh $HOME/temp
- rm -rf curl-99.98.97
- name: 'verify in-tree configure build including install'
+ - uses: actions/checkout@v4
+
+ - run: sudo apt-get purge -y curl libcurl4 libcurl4-doc
+ name: 'remove preinstalled curl libcurl4{-doc}'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure --without-ssl --without-libpsl
+ name: 'configure'
+
+ - run: make V=1 && make V=1 clean
+ name: 'make and clean'
+
+ - run: ./maketgz 99.98.97
+ name: 'maketgz'
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: 'release-tgz'
+ path: 'curl-99.98.97.tar.gz'
+
+ - run: |
+ echo "::stop-commands::$(uuidgen)"
+ tar xvf curl-99.98.97.tar.gz
+ pushd curl-99.98.97
+ ./configure --prefix=$HOME/temp --without-ssl --without-libpsl
+ make
+ make test-ci
+ make install
+ popd
+ # basic check of the installed files
+ bash scripts/installcheck.sh $HOME/temp
+ rm -rf curl-99.98.97
+ name: 'verify in-tree configure build including install'
verify-out-of-tree-docs:
runs-on: ubuntu-latest
timeout-minutes: 30
needs: maketgz-and-verify-in-tree
steps:
- - uses: actions/download-artifact@v3
- with:
- name: 'release-tgz'
-
- - run: |
- echo "::stop-commands::$(uuidgen)"
- tar xvf curl-99.98.97.tar.gz
- touch curl-99.98.97/docs/{cmdline-opts,libcurl}/Makefile.inc
- mkdir build
- pushd build
- ../curl-99.98.97/configure --without-ssl
- make
- make TFLAGS='-p 1 1139' test
- popd
- rm -rf build
- rm -rf curl-99.98.97
- name: 'verify out-of-tree configure build including docs'
+ - uses: actions/download-artifact@v4
+ with:
+ name: 'release-tgz'
+
+ - run: |
+ echo "::stop-commands::$(uuidgen)"
+ tar xvf curl-99.98.97.tar.gz
+ touch curl-99.98.97/docs/{cmdline-opts,libcurl}/Makefile.inc
+ mkdir build
+ pushd build
+ ../curl-99.98.97/configure --without-ssl --without-libpsl
+ make
+ make test-ci
+ popd
+ rm -rf build
+ rm -rf curl-99.98.97
+ name: 'verify out-of-tree configure build including docs'
+
+ verify-out-of-tree-autotools-debug:
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ needs: maketgz-and-verify-in-tree
+ steps:
+ - uses: actions/download-artifact@v4
+ with:
+ name: 'release-tgz'
+
+ - run: |
+ echo "::stop-commands::$(uuidgen)"
+ tar xvf curl-99.98.97.tar.gz
+ pushd curl-99.98.97
+ mkdir build
+ pushd build
+ ../configure --without-ssl --enable-debug "--prefix=${PWD}/pkg" --without-libpsl
+ make -j3
+ make -j3 test-ci
+ make -j3 install
+ name: 'verify out-of-tree autotools debug build'
verify-out-of-tree-cmake:
runs-on: ubuntu-latest
timeout-minutes: 30
needs: maketgz-and-verify-in-tree
steps:
- - uses: actions/download-artifact@v3
- with:
- name: 'release-tgz'
-
- - run: |
- echo "::stop-commands::$(uuidgen)"
- tar xvf curl-99.98.97.tar.gz
- pushd curl-99.98.97
- mkdir build
- pushd build
- cmake ..
- make
- name: 'verify out-of-tree cmake build'
+ - uses: actions/download-artifact@v4
+ with:
+ name: 'release-tgz'
+
+ - run: |
+ echo "::stop-commands::$(uuidgen)"
+ tar xvf curl-99.98.97.tar.gz
+ pushd curl-99.98.97
+ mkdir build
+ pushd build
+ cmake ..
+ make
+ name: 'verify out-of-tree cmake build'
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index 695e0def9..247a1c0ab 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -7,37 +7,37 @@ name: Fuzzer
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'tests/data/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'tests/data/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'tests/data/**'
+ - 'winbuild/**'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
diff --git a/.github/workflows/hacktoberfest-accepted.yml b/.github/workflows/hacktoberfest-accepted.yml
index 6363d1c51..3c4ecd87c 100644
--- a/.github/workflows/hacktoberfest-accepted.yml
+++ b/.github/workflows/hacktoberfest-accepted.yml
@@ -8,7 +8,7 @@ on:
# this must not ever run on any other branch than master
push:
branches:
- - master
+ - master
concurrency:
# this should not run in parallel, so just run one at a time
diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml
index 6a157d240..b874c31b5 100644
--- a/.github/workflows/label.yml
+++ b/.github/workflows/label.yml
@@ -21,8 +21,6 @@ jobs:
pull-requests: write
steps:
- - uses: actions/labeler@v5.0.0-beta.1
- with:
- repo-token: "${{ secrets.GITHUB_TOKEN }}"
- # This is documented but doesn't work yet:
- #dot: true
+ - uses: actions/labeler@v5
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml
index 2301e3019..ba92efabb 100644
--- a/.github/workflows/linkcheck.yml
+++ b/.github/workflows/linkcheck.yml
@@ -7,17 +7,17 @@ name: Markdown links
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths:
- - '.github/workflows/linkcheck.yml'
- - '**.md'
+ - '.github/workflows/linkcheck.yml'
+ - '**.md'
pull_request:
branches:
- - master
+ - master
paths:
- - '.github/workflows/linkcheck.yml'
- - '**.md'
+ - '.github/workflows/linkcheck.yml'
+ - '**.md'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
@@ -30,7 +30,12 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: gaurav-nelson/github-action-markdown-link-check@v1
- with:
- use-quiet-mode: 'yes'
+ - uses: actions/checkout@v4
+ name: checkout
+
+ - name: trim the cmdline docs markdown files
+ run: find docs/cmdline-opts -name "*.md" ! -name "_*" ! -name MANPAGE.md | xargs -n1 ./.github/scripts/cleancmd.pl
+
+ - uses: gaurav-nelson/github-action-markdown-link-check@v1
+ with:
+ use-quiet-mode: 'yes'
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 9cb9d16b2..b655c9637 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -7,31 +7,31 @@ name: Linux
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
@@ -44,10 +44,10 @@ env:
bearssl-version: 0.6
libressl-version: v3.7.3
mbedtls-version: v3.5.0
- mod_h2-version: v2.0.21
+ mod_h2-version: v2.0.26
msh3-version: v0.6.0
openssl3-version: openssl-3.1.3
- quictls-version: OpenSSL_1_1_1w+quic
+ quictls-version: 3.1.4+quic
rustls-version: v0.10.0
jobs:
@@ -60,375 +60,375 @@ jobs:
fail-fast: false
matrix:
build:
- - name: bearssl
- install_packages: zlib1g-dev valgrind
- install_steps: bearssl pytest
- configure: LDFLAGS="-Wl,-rpath,$HOME/bearssl/lib" --with-bearssl=$HOME/bearssl --enable-debug
- singleuse: --unit
-
- - name: bearssl-clang
- install_packages: zlib1g-dev clang
- install_steps: bearssl
- configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/bearssl/lib" --with-bearssl=$HOME/bearssl --enable-debug
- singleuse: --unit
-
- - name: libressl
- install_packages: zlib1g-dev valgrind
- install_steps: libressl pytest
- configure: LDFLAGS="-Wl,-rpath,$HOME/libressl/lib" --with-openssl=$HOME/libressl --enable-debug
- singleuse: --unit
-
- - name: libressl-clang
- install_packages: zlib1g-dev clang
- install_steps: libressl
- configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/libressl/lib" --with-openssl=$HOME/libressl --enable-debug
- singleuse: --unit
-
- - name: mbedtls
- install_packages: libnghttp2-dev valgrind
- install_steps: mbedtls pytest
- configure: LDFLAGS="-Wl,-rpath,$HOME/mbedtls/lib" --with-mbedtls=$HOME/mbedtls --enable-debug
- singleuse: --unit
-
- - name: mbedtls-clang
- install_packages: libnghttp2-dev clang
- install_steps: mbedtls
- configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/mbedtls/lib" --with-mbedtls=$HOME/mbedtls --enable-debug
- singleuse: --unit
-
- - name: msh3
- install_packages: zlib1g-dev valgrind
- install_steps: quictls msh3
- configure: LDFLAGS="-Wl,-rpath,$HOME/msh3/lib -Wl,-rpath,$HOME/quictls/lib" --with-msh3=$HOME/msh3 --with-openssl=$HOME/quictls --enable-debug
- singleuse: --unit
-
- - name: openssl3
- install_packages: zlib1g-dev valgrind
- install_steps: gcc-11 openssl3 pytest
- configure: LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
- singleuse: --unit
-
- - name: openssl3-O3
- install_packages: zlib1g-dev valgrind
- install_steps: gcc-11 openssl3
- configure: CFLAGS=-O3 LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
- singleuse: --unit
-
- - name: openssl3-clang
- install_packages: zlib1g-dev clang
- install_steps: openssl3
- configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib64" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
- singleuse: --unit
-
- - name: address-sanitizer
- install_packages: zlib1g-dev libssh2-1-dev clang libssl-dev libubsan1 libasan8 libtsan2
- install_steps: pytest
- configure: >
- CC=clang
- CFLAGS="-fsanitize=address,undefined,signed-integer-overflow -fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security -Werror=array-bounds -g"
- LDFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined,integer"
- LIBS="-ldl -lubsan"
- --with-openssl --enable-debug --enable-websockets
- singleuse: --unit
-
- - name: memory-sanitizer
- install_packages: clang
- install_steps:
- configure: >
- CC=clang
- CFLAGS="-fsanitize=memory -Wformat -Werror=format-security -Werror=array-bounds -g"
- LDFLAGS="-fsanitize=memory"
- LIBS="-ldl"
- --without-ssl --without-zlib --without-brotli --without-zstd --without-libpsl --without-nghttp2 --enable-debug --enable-websocketsx
- singleuse: --unit
-
- - name: event-based
- install_packages: libssh-dev valgrind
- configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl
- tflags: -n -e '!TLS-SRP'
- singleuse: --unit
-
- - name: hyper
- install_steps: rust hyper valgrind
- configure: LDFLAGS="-Wl,-rpath,$HOME/hyper/target/debug" --with-openssl --with-hyper=$HOME/hyper --enable-debug --enable-websockets
- singleuse: --unit
-
- - name: rustls
- install_steps: rust rustls pytest valgrind
- configure: --with-rustls=$HOME/rustls --enable-debug
- singleuse: --unit
-
- - name: Intel compiler - without SSL
- install_packages: zlib1g-dev valgrind
- install_steps: intel
- configure: CC=icc --enable-debug --without-ssl
- singleuse: --unit
-
- - name: Intel compiler - OpenSSL
- install_packages: zlib1g-dev libssl-dev valgrind
- install_steps: intel
- configure: CC=icc --enable-debug --with-openssl
- singleuse: --unit
-
- - name: Slackware-openssl-with-gssapi-gcc
- # These are essentially the same flags used to build the curl Slackware package
- # https://ftpmirror.infania.net/slackware/slackware64-current/source/n/curl/curl.SlackBuild
- configure: --with-openssl --with-libssh2 --with-gssapi --enable-ares --enable-static=no --without-ca-bundle --with-ca-path=/etc/ssl/certs
- # Docker Hub image that `container-job` executes in
- container: 'andy5995/slackware-build-essential:15.0'
-
- - name: Alpine MUSL
- configure: --enable-debug --enable-websockets --with-ssl --with-libssh2 --with-libidn2 --with-gssapi --enable-ldap --with-libpsl
- container: 'alpine:3.18'
- singleuse: --unit
+ - name: bearssl
+ install_packages: zlib1g-dev valgrind
+ install_steps: bearssl pytest
+ configure: LDFLAGS="-Wl,-rpath,$HOME/bearssl/lib" --with-bearssl=$HOME/bearssl --enable-debug
+ singleuse: --unit
+
+ - name: bearssl-clang
+ install_packages: zlib1g-dev clang
+ install_steps: bearssl
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/bearssl/lib" --with-bearssl=$HOME/bearssl --enable-debug
+ singleuse: --unit
+
+ - name: libressl
+ install_packages: zlib1g-dev valgrind
+ install_steps: libressl pytest
+ configure: LDFLAGS="-Wl,-rpath,$HOME/libressl/lib" --with-openssl=$HOME/libressl --enable-debug
+ singleuse: --unit
+
+ - name: libressl-clang
+ install_packages: zlib1g-dev clang
+ install_steps: libressl
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/libressl/lib" --with-openssl=$HOME/libressl --enable-debug
+ singleuse: --unit
+
+ - name: mbedtls
+ install_packages: libnghttp2-dev valgrind
+ install_steps: mbedtls pytest
+ configure: LDFLAGS="-Wl,-rpath,$HOME/mbedtls/lib" --with-mbedtls=$HOME/mbedtls --enable-debug
+ singleuse: --unit
+
+ - name: mbedtls-clang
+ install_packages: libnghttp2-dev clang
+ install_steps: mbedtls
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/mbedtls/lib" --with-mbedtls=$HOME/mbedtls --enable-debug
+ singleuse: --unit
+
+ - name: msh3
+ install_packages: zlib1g-dev valgrind
+ install_steps: quictls msh3
+ configure: LDFLAGS="-Wl,-rpath,$HOME/msh3/lib -Wl,-rpath,$HOME/quictls/lib" --with-msh3=$HOME/msh3 --with-openssl=$HOME/quictls --enable-debug
+ singleuse: --unit
+
+ - name: openssl3
+ install_packages: zlib1g-dev valgrind
+ install_steps: gcc-11 openssl3 pytest
+ configure: CFLAGS=-std=gnu89 LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
+ singleuse: --unit
+
+ - name: openssl3-O3
+ install_packages: zlib1g-dev valgrind
+ install_steps: gcc-11 openssl3
+ configure: CPPFLAGS=-DCURL_WARN_SIGN_CONVERSION CFLAGS=-O3 LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
+ singleuse: --unit
+
+ - name: openssl3-clang
+ install_packages: zlib1g-dev clang
+ install_steps: openssl3
+ configure: CC=clang LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib" --with-openssl=$HOME/openssl3 --enable-debug --enable-websockets
+ singleuse: --unit
+
+ - name: address-sanitizer
+ install_packages: zlib1g-dev libssh2-1-dev clang libssl-dev libubsan1 libasan8 libtsan2
+ install_steps: pytest
+ configure: >
+ CC=clang
+ CFLAGS="-fsanitize=address,undefined,signed-integer-overflow -fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security -Werror=array-bounds -g"
+ LDFLAGS="-fsanitize=address,undefined -fno-sanitize-recover=undefined,integer"
+ LIBS="-ldl -lubsan"
+ --with-openssl --enable-debug --enable-websockets
+ singleuse: --unit
+
+ - name: memory-sanitizer
+ install_packages: clang
+ install_steps:
+ configure: >
+ CC=clang
+ CFLAGS="-fsanitize=memory -Wformat -Werror=format-security -Werror=array-bounds -g"
+ LDFLAGS="-fsanitize=memory"
+ LIBS="-ldl"
+ --without-ssl --without-zlib --without-brotli --without-zstd --without-libpsl --without-nghttp2 --enable-debug --enable-websocketsx
+ singleuse: --unit
+
+ - name: event-based
+ install_packages: libssh-dev valgrind
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl
+ tflags: -n -e '!TLS-SRP'
+ singleuse: --unit
+
+ - name: hyper
+ install_steps: rust hyper valgrind
+ configure: LDFLAGS="-Wl,-rpath,$HOME/hyper/target/debug" --with-openssl --with-hyper=$HOME/hyper --enable-debug --enable-websockets
+ singleuse: --unit
+
+ - name: rustls
+ install_steps: rust rustls pytest valgrind libpsl-dev
+ configure: --with-rustls=$HOME/rustls --enable-debug
+ singleuse: --unit
+
+ - name: Intel compiler - without SSL
+ install_packages: zlib1g-dev valgrind
+ install_steps: intel
+ configure: CC=icc --enable-debug --without-ssl
+ singleuse: --unit
+
+ - name: Intel compiler - OpenSSL
+ install_packages: zlib1g-dev libssl-dev valgrind
+ install_steps: intel
+ configure: CC=icc --enable-debug --with-openssl
+ singleuse: --unit
+
+ - name: Slackware-openssl-with-gssapi-gcc
+ # These are essentially the same flags used to build the curl Slackware package
+ # https://ftpmirror.infania.net/slackware/slackware64-current/source/n/curl/curl.SlackBuild
+ configure: --with-openssl --with-libssh2 --with-gssapi --enable-ares --enable-static=no --without-ca-bundle --with-ca-path=/etc/ssl/certs
+ # Docker Hub image that `container-job` executes in
+ container: 'andy5995/slackware-build-essential:15.0'
+
+ - name: Alpine MUSL
+ configure: --enable-debug --enable-websockets --with-ssl --with-libssh2 --with-libidn2 --with-gssapi --enable-ldap --with-libpsl
+ container: 'alpine:3.18'
+ singleuse: --unit
steps:
- - if: matrix.build.container == null
- run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 libpsl-dev libbrotli-dev libzstd-dev ${{ matrix.build.install_packages }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
-
- - if: startsWith(matrix.build.container, 'alpine')
- run: |
- apk add --no-cache build-base autoconf automake libtool perl openssl-dev libssh2-dev zlib-dev brotli-dev zstd-dev libidn2-dev openldap-dev heimdal-dev libpsl-dev py3-impacket py3-asn1 py3-six py3-pycryptodomex perl-time-hires openssh stunnel sudo git
- name: 'install dependencies'
-
- - uses: actions/checkout@v4
-
- - if: contains(matrix.build.install_steps, 'gcc-11')
- run: |
- sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa
- sudo apt-get update
- sudo apt-get install gcc-11
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100
- sudo update-alternatives --set gcc /usr/bin/gcc-11
- gcc --version
- name: 'install gcc-11'
-
- - name: cache bearssl
- if: contains(matrix.build.install_steps, 'bearssl')
- uses: actions/cache@v3
- id: cache-bearssl
- env:
- cache-name: cache-bearssl
- with:
- path: /home/runner/bearssl
- key: ${{ runner.os }}-build-${{ env.cache-name }}-bearssl-${{ env.bearssl-version }}
-
- - name: 'build bearssl'
- if: contains(matrix.build.install_steps, 'bearssl') && steps.cache-bearssl.outputs.cache-hit != 'true'
- run: |
- curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://bearssl.org/bearssl-${{ env.bearssl-version }}.tar.gz
- tar -xzf bearssl-${{ env.bearssl-version }}.tar.gz
- cd bearssl-${{ env.bearssl-version }}
- make
- mkdir -p $HOME/bearssl/lib $HOME/bearssl/include
- cp inc/*.h $HOME/bearssl/include
- cp build/libbearssl.* $HOME/bearssl/lib
-
- - name: cache libressl
- if: contains(matrix.build.install_steps, 'libressl')
- uses: actions/cache@v3
- id: cache-libressl
- env:
- cache-name: cache-libressl
- with:
- path: /home/runner/libressl
- key: ${{ runner.os }}-build-${{ env.cache-name }}-libressl-${{ env.libressl-version }}
-
- - name: 'build libressl'
- if: contains(matrix.build.install_steps, 'libressl') && steps.cache-libressl.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.libressl-version }} https://github.com/libressl-portable/portable.git libressl-git
- cd libressl-git
- ./autogen.sh
- ./configure --prefix=$HOME/libressl
- make install
-
- - name: cache mbedtls
- if: contains(matrix.build.install_steps, 'mbedtls')
- uses: actions/cache@v3
- id: cache-mbedtls
- env:
- cache-name: cache-mbedtls
- with:
- path: /home/runner/mbedtls
- key: ${{ runner.os }}-build-${{ env.cache-name }}-mbedtls-${{ env.mbedtls-version }}
-
- - name: 'build mbedtls'
- if: contains(matrix.build.install_steps, 'mbedtls') && steps.cache-mbedtls.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.mbedtls-version }} https://github.com/ARMmbed/mbedtls
- cd mbedtls
- make DESTDIR=$HOME/mbedtls install
-
- - name: cache openssl3
- if: contains(matrix.build.install_steps, 'openssl3')
- uses: actions/cache@v3
- id: cache-openssl3
- env:
- cache-name: cache-openssl3
- with:
- path: /home/runner/openssl3
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.openssl3-version }}
-
- - name: 'install openssl3'
- if: contains(matrix.build.install_steps, 'openssl3') && steps.cache-openssl3.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.openssl3-version }} https://github.com/openssl/openssl
- cd openssl
- ./config enable-tls1_3 --prefix=$HOME/openssl3
- make -j1 install_sw
-
- - name: cache quictls
- if: contains(matrix.build.install_steps, 'quictls')
- uses: actions/cache@v3
- id: cache-quictls
- env:
- cache-name: cache-quictls
- with:
- path: /home/runner/quictls
- key: ${{ runner.os }}-build-${{ env.cache-name }}-quictls-${{ env.quictls-version }}
-
- - name: 'build quictls'
- if: contains(matrix.build.install_steps, 'quictls') && steps.cache-quictls.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.quictls-version }} https://github.com/quictls/openssl
- cd openssl
- ./config enable-tls1_3 --prefix=$HOME/quictls
- make -j1 install_sw
-
- - name: cache msh3
- if: contains(matrix.build.install_steps, 'msh3')
- uses: actions/cache@v3
- id: cache-msh3
- env:
- cache-name: cache-msh3
- with:
- path: /home/runner/msh3
- key: ${{ runner.os }}-build-${{ env.cache-name }}-msh3-${{ env.msh3-version }}
-
- - name: 'build msh3'
- if: contains(matrix.build.install_steps, 'msh3') && steps.cache-msh3.outputs.cache-hit != 'true'
- run: |
- git clone --quiet -b ${{ env.msh3-version }} --depth=1 --recursive https://github.com/nibanks/msh3
- cd msh3 && mkdir build && cd build
- cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=$HOME/msh3 ..
- cmake --build .
- cmake --install .
-
- - if: contains(matrix.build.install_steps, 'rust')
- run: |
- cd $HOME
- curl -sSf --compressed https://sh.rustup.rs/ | sh -s -- -y
- source $HOME/.cargo/env
- rustup toolchain install nightly
- name: 'install rust'
-
- - name: cache rustls
- if: contains(matrix.build.install_steps, 'rustls')
- uses: actions/cache@v3
- id: cache-rustls
- env:
- cache-name: cache-rustls
- with:
- path: /home/runner/rustls
- key: ${{ runner.os }}-build-${{ env.cache-name }}-rustls-${{ env.rustls-version }}
-
- - name: 'build rustls'
- if: contains(matrix.build.install_steps, 'rustls') && steps.cache-rustls.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.rustls-version }} --recursive https://github.com/rustls/rustls-ffi.git
- cd rustls-ffi
- make DESTDIR=$HOME/rustls install
-
- - if: contains(matrix.build.install_steps, 'hyper')
- run: |
- cd $HOME
- git clone --quiet --depth=1 https://github.com/hyperium/hyper.git
- cd $HOME/hyper
- RUSTFLAGS="--cfg hyper_unstable_ffi" cargo +nightly rustc --features client,http1,http2,ffi -Z unstable-options --crate-type cdylib
- echo "LD_LIBRARY_PATH=$HOME/hyper/target/debug:/usr/local/lib" >> $GITHUB_ENV
- name: 'install hyper'
-
- - if: contains(matrix.build.install_steps, 'intel')
- run: |
- cd /tmp
- curl -sSf --compressed https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | sudo apt-key add -
- sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main"
- sudo apt install --no-install-recommends intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
- source /opt/intel/oneapi/setvars.sh
- printenv >> $GITHUB_ENV
- name: 'install Intel compilers'
-
- - if: contains(matrix.build.install_steps, 'pytest')
- run: |
- sudo apt-get install apache2 apache2-dev libnghttp2-dev
- sudo python3 -m pip install -r tests/http/requirements.txt
- name: 'install pytest and apach2-dev'
-
- - name: cache mod_h2
- if: contains(matrix.build.install_steps, 'pytest')
- uses: actions/cache@v3
- id: cache-mod_h2
- env:
- cache-name: cache-mod_h2
- with:
- path: /home/runner/mod_h2
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.mod_h2-version }}
-
- - name: 'build mod_h2'
- if: contains(matrix.build.install_steps, 'pytest') && steps.cache-mod_h2.outputs.cache-hit != 'true'
- run: |
- cd $HOME
- git clone --quiet --depth=1 -b ${{ env.mod_h2-version }} https://github.com/icing/mod_h2
- cd mod_h2
- autoreconf -fi
- ./configure
- make
-
- - name: 'install mod_h2'
- if: contains(matrix.build.install_steps, 'pytest')
- run: |
- cd $HOME/mod_h2
- sudo make install
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: |
- git config --global --add safe.directory "*"
- ./scripts/singleuse.pl ${{ matrix.build.singleuse }} lib/.libs/libcurl.a
- name: single-use function check
-
- - run: ./src/curl -V
- name: 'check curl -V output'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 -C tests
- name: 'make tests'
-
- - run: make V=1 test-ci
- name: 'run tests'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
-
- - if: contains(matrix.build.install_steps, 'pytest')
- # run for `tests` directory, so pytest does not pick up any other
- # packages we might have built here
- run:
- pytest -v tests
- name: 'run pytest'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
- CURL_CI: github
+ - if: matrix.build.container == null
+ run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 libpsl-dev libbrotli-dev libzstd-dev ${{ matrix.build.install_packages }}
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
+
+ - if: startsWith(matrix.build.container, 'alpine')
+ run: |
+ apk add --no-cache build-base autoconf automake libtool perl openssl-dev libssh2-dev zlib-dev brotli-dev zstd-dev libidn2-dev openldap-dev heimdal-dev libpsl-dev py3-impacket py3-asn1 py3-six py3-pycryptodomex perl-time-hires openssh stunnel sudo git
+ name: 'install dependencies'
+
+ - uses: actions/checkout@v4
+
+ - if: contains(matrix.build.install_steps, 'gcc-11')
+ run: |
+ sudo add-apt-repository ppa:ubuntu-toolchain-r/ppa
+ sudo apt-get update
+ sudo apt-get install gcc-11
+ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100
+ sudo update-alternatives --set gcc /usr/bin/gcc-11
+ gcc --version
+ name: 'install gcc-11'
+
+ - name: cache bearssl
+ if: contains(matrix.build.install_steps, 'bearssl')
+ uses: actions/cache@v4
+ id: cache-bearssl
+ env:
+ cache-name: cache-bearssl
+ with:
+ path: /home/runner/bearssl
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-bearssl-${{ env.bearssl-version }}
+
+ - name: 'build bearssl'
+ if: contains(matrix.build.install_steps, 'bearssl') && steps.cache-bearssl.outputs.cache-hit != 'true'
+ run: |
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://bearssl.org/bearssl-${{ env.bearssl-version }}.tar.gz
+ tar -xzf bearssl-${{ env.bearssl-version }}.tar.gz
+ cd bearssl-${{ env.bearssl-version }}
+ make
+ mkdir -p $HOME/bearssl/lib $HOME/bearssl/include
+ cp inc/*.h $HOME/bearssl/include
+ cp build/libbearssl.* $HOME/bearssl/lib
+
+ - name: cache libressl
+ if: contains(matrix.build.install_steps, 'libressl')
+ uses: actions/cache@v4
+ id: cache-libressl
+ env:
+ cache-name: cache-libressl
+ with:
+ path: /home/runner/libressl
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-libressl-${{ env.libressl-version }}
+
+ - name: 'build libressl'
+ if: contains(matrix.build.install_steps, 'libressl') && steps.cache-libressl.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.libressl-version }} https://github.com/libressl-portable/portable.git libressl-git
+ cd libressl-git
+ ./autogen.sh
+ ./configure --prefix=$HOME/libressl
+ make install
+
+ - name: cache mbedtls
+ if: contains(matrix.build.install_steps, 'mbedtls')
+ uses: actions/cache@v4
+ id: cache-mbedtls
+ env:
+ cache-name: cache-mbedtls
+ with:
+ path: /home/runner/mbedtls
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-mbedtls-${{ env.mbedtls-version }}
+
+ - name: 'build mbedtls'
+ if: contains(matrix.build.install_steps, 'mbedtls') && steps.cache-mbedtls.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.mbedtls-version }} https://github.com/ARMmbed/mbedtls
+ cd mbedtls
+ make DESTDIR=$HOME/mbedtls install
+
+ - name: cache openssl3
+ if: contains(matrix.build.install_steps, 'openssl3')
+ uses: actions/cache@v4
+ id: cache-openssl3
+ env:
+ cache-name: cache-openssl3
+ with:
+ path: /home/runner/openssl3
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.openssl3-version }}
+
+ - name: 'install openssl3'
+ if: contains(matrix.build.install_steps, 'openssl3') && steps.cache-openssl3.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.openssl3-version }} https://github.com/openssl/openssl
+ cd openssl
+ ./config --prefix=$HOME/openssl3 --libdir=$HOME/openssl3/lib
+ make -j1 install_sw
+
+ - name: cache quictls
+ if: contains(matrix.build.install_steps, 'quictls')
+ uses: actions/cache@v4
+ id: cache-quictls
+ env:
+ cache-name: cache-quictls
+ with:
+ path: /home/runner/quictls
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-quictls-${{ env.quictls-version }}
+
+ - name: 'build quictls'
+ if: contains(matrix.build.install_steps, 'quictls') && steps.cache-quictls.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b openssl-${{ env.quictls-version }} https://github.com/quictls/openssl
+ cd openssl
+ ./config --prefix=$HOME/quictls --libdir=$HOME/quictls/lib
+ make -j1 install_sw
+
+ - name: cache msh3
+ if: contains(matrix.build.install_steps, 'msh3')
+ uses: actions/cache@v4
+ id: cache-msh3
+ env:
+ cache-name: cache-msh3
+ with:
+ path: /home/runner/msh3
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-msh3-${{ env.msh3-version }}
+
+ - name: 'build msh3'
+ if: contains(matrix.build.install_steps, 'msh3') && steps.cache-msh3.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet -b ${{ env.msh3-version }} --depth=1 --recursive https://github.com/nibanks/msh3
+ cd msh3 && mkdir build && cd build
+ cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=$HOME/msh3 ..
+ cmake --build .
+ cmake --install .
+
+ - if: contains(matrix.build.install_steps, 'rust')
+ run: |
+ cd $HOME
+ curl -sSf --compressed https://sh.rustup.rs/ | sh -s -- -y
+ source $HOME/.cargo/env
+ rustup toolchain install nightly
+ name: 'install rust'
+
+ - name: cache rustls
+ if: contains(matrix.build.install_steps, 'rustls')
+ uses: actions/cache@v4
+ id: cache-rustls
+ env:
+ cache-name: cache-rustls
+ with:
+ path: /home/runner/rustls
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-rustls-${{ env.rustls-version }}
+
+ - name: 'build rustls'
+ if: contains(matrix.build.install_steps, 'rustls') && steps.cache-rustls.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.rustls-version }} --recursive https://github.com/rustls/rustls-ffi.git
+ cd rustls-ffi
+ make DESTDIR=$HOME/rustls install
+
+ - if: contains(matrix.build.install_steps, 'hyper')
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 https://github.com/hyperium/hyper.git
+ cd $HOME/hyper
+ RUSTFLAGS="--cfg hyper_unstable_ffi" cargo +nightly rustc --features client,http1,http2,ffi -Z unstable-options --crate-type cdylib
+ echo "LD_LIBRARY_PATH=$HOME/hyper/target/debug:/usr/local/lib" >> $GITHUB_ENV
+ name: 'install hyper'
+
+ - if: contains(matrix.build.install_steps, 'intel')
+ run: |
+ cd /tmp
+ curl -sSf --compressed https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | sudo apt-key add -
+ sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main"
+ sudo apt install --no-install-recommends intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
+ source /opt/intel/oneapi/setvars.sh
+ printenv >> $GITHUB_ENV
+ name: 'install Intel compilers'
+
+ - if: contains(matrix.build.install_steps, 'pytest')
+ run: |
+ sudo apt-get install apache2 apache2-dev libnghttp2-dev
+ sudo python3 -m pip install -r tests/http/requirements.txt
+ name: 'install pytest and apach2-dev'
+
+ - name: cache mod_h2
+ if: contains(matrix.build.install_steps, 'pytest')
+ uses: actions/cache@v4
+ id: cache-mod_h2
+ env:
+ cache-name: cache-mod_h2
+ with:
+ path: /home/runner/mod_h2
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.mod_h2-version }}
+
+ - name: 'build mod_h2'
+ if: contains(matrix.build.install_steps, 'pytest') && steps.cache-mod_h2.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.mod_h2-version }} https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure
+ make
+
+ - name: 'install mod_h2'
+ if: contains(matrix.build.install_steps, 'pytest')
+ run: |
+ cd $HOME/mod_h2
+ sudo make install
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: |
+ git config --global --add safe.directory "*"
+ ./scripts/singleuse.pl ${{ matrix.build.singleuse }} lib/.libs/libcurl.a
+ name: single-use function check
+
+ - run: ./src/curl -V
+ name: 'check curl -V output'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+
+ - if: contains(matrix.build.install_steps, 'pytest')
+ # run for `tests` directory, so pytest does not pick up any other
+ # packages we might have built here
+ run:
+ pytest -v tests
+ name: 'run pytest'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+ CURL_CI: github
diff --git a/.github/workflows/linux32.yml b/.github/workflows/linux32.yml
index 7c2d4cbf6..e3fca3d1d 100644
--- a/.github/workflows/linux32.yml
+++ b/.github/workflows/linux32.yml
@@ -7,35 +7,35 @@ name: Linux 32-bit
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
@@ -55,39 +55,39 @@ jobs:
fail-fast: false
matrix:
build:
- - name: Linux i686
- install_packages: gcc-11-i686-linux-gnu libssl-dev:i386 zlib1g-dev:i386 libpsl-dev:i386 libbrotli-dev:i386 libzstd-dev:i386
- configure: --enable-debug --enable-websockets --with-openssl --host=i686-linux-gnu CC=i686-linux-gnu-gcc-11 PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CPPFLAGS=-I/usr/include/i386-linux-gnu LDFLAGS=-L/usr/lib/i386-linux-gnu
+ - name: Linux i686
+ install_packages: gcc-11-i686-linux-gnu libssl-dev:i386 zlib1g-dev:i386 libpsl-dev:i386 libbrotli-dev:i386 libzstd-dev:i386
+ configure: --enable-debug --enable-websockets --with-openssl --host=i686-linux-gnu CC=i686-linux-gnu-gcc-11 PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig CPPFLAGS=-I/usr/include/i386-linux-gnu LDFLAGS=-L/usr/lib/i386-linux-gnu
steps:
- - run: |
- sudo dpkg --add-architecture i386
- sudo apt-get update -y
- sudo apt-get install -y --no-install-suggests --no-install-recommends libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install_packages }}
- sudo python3 -m pip install impacket
- name: 'install prereqs'
+ - run: |
+ sudo dpkg --add-architecture i386
+ sudo apt-get update -y
+ sudo apt-get install -y --no-install-suggests --no-install-recommends libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install_packages }}
+ sudo python3 -m pip install impacket
+ name: 'install prereqs'
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - run: autoreconf -fi
- name: 'autoreconf'
+ - run: autoreconf -fi
+ name: 'autoreconf'
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ name: 'configure'
- - run: make V=1
- name: 'make'
+ - run: make V=1
+ name: 'make'
- - run: ./src/curl -V
- name: 'check curl -V output'
+ - run: ./src/curl -V
+ name: 'check curl -V output'
- - run: make V=1 examples
- name: 'make examples'
+ - run: make V=1 examples
+ name: 'make examples'
- - run: make V=1 -C tests
- name: 'make tests'
+ - run: make V=1 -C tests
+ name: 'make tests'
- - run: make V=1 test-ci
- name: 'run tests'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index e565f20e6..2f2d75397 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -7,31 +7,31 @@ name: macOS
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
@@ -52,141 +52,142 @@ jobs:
fail-fast: false
matrix:
build:
- - name: normal
- install: nghttp2
- configure: --without-ssl --enable-websockets
- macosx-version-min: 10.9
- - name: debug
- install: nghttp2
- configure: --enable-debug --without-ssl --enable-websockets
- macosx-version-min: 10.9
- - name: libssh2
- install: nghttp2 libssh2
- configure: --enable-debug --with-libssh2 --without-ssl --enable-websockets
- macosx-version-min: 10.9
- - name: libssh-c-ares
- install: openssl nghttp2 libssh
- configure: --enable-debug --with-libssh --with-openssl=/usr/local/opt/openssl --enable-ares --enable-websockets
- macosx-version-min: 10.9
- - name: libssh
- install: openssl nghttp2 libssh
- configure: --enable-debug --with-libssh --with-openssl=/usr/local/opt/openssl --enable-websockets
- macosx-version-min: 10.9
- - name: c-ares
- install: nghttp2
- configure: --enable-debug --enable-ares --without-ssl --enable-websockets
- macosx-version-min: 10.9
- - name: HTTP only
- install: nghttp2
- configure: |
- --enable-debug \
- --enable-maintainer-mode \
- --disable-alt-svc \
- --disable-dict \
- --disable-file \
- --disable-ftp \
- --disable-gopher \
- --disable-imap \
- --disable-ldap \
- --disable-pop3 \
- --disable-rtmp \
- --disable-rtsp \
- --disable-scp \
- --disable-sftp \
- --disable-shared \
- --disable-smb \
- --disable-smtp \
- --disable-telnet \
- --disable-tftp \
- --disable-unix-sockets \
- --without-brotli \
- --without-gssapi \
- --without-libidn2 \
- --without-libpsl \
- --without-librtmp \
- --without-libssh2 \
- --without-nghttp2 \
- --without-ntlm-auth \
- --without-ssl \
- --without-zlib \
- --without-zstd
- macosx-version-min: 10.15
- - name: SecureTransport http2
- install: nghttp2
- configure: --enable-debug --with-secure-transport --enable-websockets
- macosx-version-min: 10.8
- - name: gcc SecureTransport
- configure: CC=gcc-12 --enable-debug --with-secure-transport --enable-websockets
- macosx-version-min: 10.8
- - name: OpenSSL http2
- install: nghttp2 openssl
- configure: --enable-debug --with-openssl=/usr/local/opt/openssl --enable-websockets
- macosx-version-min: 10.9
- - name: LibreSSL http2
- install: nghttp2 libressl
- configure: --enable-debug --with-openssl=/usr/local/opt/libressl --enable-websockets
- macosx-version-min: 10.9
- - name: torture
- install: nghttp2 openssl
- configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=/usr/local/opt/openssl --enable-websockets
- tflags: -n -t --shallow=25 !FTP
- macosx-version-min: 10.9
- - name: torture-ftp
- install: nghttp2 openssl
- configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=/usr/local/opt/openssl --enable-websockets
- tflags: -n -t --shallow=20 FTP
- macosx-version-min: 10.9
- - name: macOS 10.15
- install: nghttp2 libssh2 openssl
- configure: --enable-debug --disable-ldap --with-openssl=/usr/local/opt/openssl --enable-websockets
- macosx-version-min: 10.15
+ - name: normal
+ install: nghttp2
+ configure: --without-ssl --enable-websockets
+ macosx-version-min: 10.9
+ - name: debug
+ install: nghttp2
+ configure: --enable-debug --without-ssl --enable-websockets
+ macosx-version-min: 10.9
+ - name: libssh2
+ install: nghttp2 libssh2
+ configure: --enable-debug --with-libssh2 --without-ssl --enable-websockets
+ macosx-version-min: 10.9
+ - name: libssh-c-ares
+ install: openssl nghttp2 libssh
+ configure: --enable-debug --with-libssh --with-openssl=/usr/local/opt/openssl --enable-ares --enable-websockets
+ macosx-version-min: 10.9
+ - name: libssh
+ install: openssl nghttp2 libssh
+ configure: --enable-debug --with-libssh --with-openssl=/usr/local/opt/openssl --enable-websockets
+ macosx-version-min: 10.9
+ - name: c-ares
+ install: nghttp2
+ configure: --enable-debug --enable-ares --without-ssl --enable-websockets
+ macosx-version-min: 10.9
+ - name: HTTP only
+ install: nghttp2
+ configure: |
+ --enable-debug \
+ --enable-maintainer-mode \
+ --disable-alt-svc \
+ --disable-dict \
+ --disable-file \
+ --disable-ftp \
+ --disable-gopher \
+ --disable-imap \
+ --disable-ldap \
+ --disable-pop3 \
+ --disable-rtmp \
+ --disable-rtsp \
+ --disable-scp \
+ --disable-sftp \
+ --disable-shared \
+ --disable-smb \
+ --disable-smtp \
+ --disable-telnet \
+ --disable-tftp \
+ --disable-unix-sockets \
+ --without-brotli \
+ --without-gssapi \
+ --without-libidn2 \
+ --without-libpsl \
+ --without-librtmp \
+ --without-libssh2 \
+ --without-nghttp2 \
+ --without-ntlm-auth \
+ --without-ssl \
+ --without-zlib \
+ --without-zstd
+
+ macosx-version-min: 10.15
+ - name: SecureTransport http2
+ install: nghttp2
+ configure: --enable-debug --with-secure-transport --enable-websockets
+ macosx-version-min: 10.8
+ - name: gcc SecureTransport
+ configure: CC=gcc-12 --enable-debug --with-secure-transport --enable-websockets --without-libpsl
+ macosx-version-min: 10.8
+ - name: OpenSSL http2
+ install: nghttp2 openssl
+ configure: --enable-debug --with-openssl=/usr/local/opt/openssl --enable-websockets
+ macosx-version-min: 10.9
+ - name: LibreSSL http2
+ install: nghttp2 libressl
+ configure: --enable-debug --with-openssl=/usr/local/opt/libressl --enable-websockets
+ macosx-version-min: 10.9
+ - name: torture
+ install: nghttp2 openssl
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=/usr/local/opt/openssl --enable-websockets
+ tflags: -n -t --shallow=25 !FTP
+ macosx-version-min: 10.9
+ - name: torture-ftp
+ install: nghttp2 openssl
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=/usr/local/opt/openssl --enable-websockets
+ tflags: -n -t --shallow=20 FTP
+ macosx-version-min: 10.9
+ - name: macOS 10.15
+ install: nghttp2 libssh2 openssl
+ configure: --enable-debug --disable-ldap --with-openssl=/usr/local/opt/openssl --enable-websockets
+ macosx-version-min: 10.15
steps:
- - run: echo libtool autoconf automake pkg-config ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
- name: 'brew bundle'
+ - run: echo libtool autoconf automake pkg-config libpsl ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
+ name: 'brew bundle'
- # Run this command with retries because of spurious failures seen
- # while running the tests, for example
- # https://github.com/curl/curl/runs/4095721123?check_suite_focus=true
- - run: "while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done"
- name: 'brew install'
+ # Run this command with retries because of spurious failures seen
+ # while running the tests, for example
+ # https://github.com/curl/curl/runs/4095721123?check_suite_focus=true
+ - run: "while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done"
+ name: 'brew install'
- - run: |
- case "${{ matrix.build.install }}" in
- *openssl*)
- ;;
- *)
- if test -d /usr/local/include/openssl; then
- brew unlink openssl
- fi;;
- esac
- name: 'brew unlink openssl'
+ - run: |
+ case "${{ matrix.build.install }}" in
+ *openssl*)
+ ;;
+ *)
+ if test -d /usr/local/include/openssl; then
+ brew unlink openssl
+ fi;;
+ esac
+ name: 'brew unlink openssl'
- - run: python3 -m pip install impacket
- name: 'pip3 install'
+ - run: python3 -m pip install impacket
+ name: 'pip3 install'
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - run: autoreconf -fi
- name: 'autoreconf'
+ - run: autoreconf -fi
+ name: 'autoreconf'
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
- env:
- CFLAGS: "-mmacosx-version-min=${{ matrix.build.macosx-version-min }}"
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ name: 'configure'
+ env:
+ CFLAGS: "-mmacosx-version-min=${{ matrix.build.macosx-version-min }}"
- - run: make V=1
- name: 'make'
+ - run: make V=1
+ name: 'make'
- - run: make V=1 examples
- name: 'make examples'
+ - run: make V=1 examples
+ name: 'make examples'
- - run: make V=1 -C tests
- name: 'make tests'
+ - run: make V=1 -C tests
+ name: 'make tests'
- - run: make V=1 test-ci
- name: 'run tests'
- env:
- TFLAGS: "${{ matrix.build.tflags }} ~1452"
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }} ~1452"
cmake:
name: cmake ${{ matrix.compiler.CC }} ${{ matrix.build.name }}
@@ -196,47 +197,47 @@ jobs:
fail-fast: false
matrix:
compiler:
- - CC: clang
- CXX: clang++
- CFLAGS: "-mmacosx-version-min=10.15 -Wno-deprecated-declarations"
- - CC: gcc-12
- CXX: g++-12
- CFLAGS: "-mmacosx-version-min=10.15 -Wno-error=undef -Wno-error=conversion"
+ - CC: clang
+ CXX: clang++
+ CFLAGS: "-mmacosx-version-min=10.15 -Wno-deprecated-declarations"
+ - CC: gcc-12
+ CXX: g++-12
+ CFLAGS: "-mmacosx-version-min=10.15 -Wno-error=undef -Wno-error=conversion"
build:
- - name: OpenSSL
- install: nghttp2 openssl
- generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9
- - name: LibreSSL
- install: nghttp2 libressl
- generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/libressl -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON -DCMAKE_UNITY_BUILD=ON
- - name: libssh2
- install: nghttp2 openssl libssh2
- generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCURL_USE_LIBSSH2=ON -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=ON
- - name: GnuTLS
- install: gnutls
- generate: -DCURL_USE_GNUTLS=ON -DCURL_USE_OPENSSL=OFF -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON -DCMAKE_SHARED_LINKER_FLAGS=-L/usr/local/lib -DCMAKE_EXE_LINKER_FLAGS=-L/usr/local/lib
+ - name: OpenSSL
+ install: nghttp2 openssl
+ generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9
+ - name: LibreSSL
+ install: nghttp2 libressl
+ generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/libressl -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON -DCMAKE_UNITY_BUILD=ON
+ - name: libssh2
+ install: nghttp2 openssl libssh2
+ generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCURL_USE_LIBSSH2=ON -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=ON
+ - name: GnuTLS
+ install: gnutls
+ generate: -DCURL_USE_GNUTLS=ON -DCURL_USE_OPENSSL=OFF -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON -DCMAKE_SHARED_LINKER_FLAGS=-L/usr/local/lib -DCMAKE_EXE_LINKER_FLAGS=-L/usr/local/lib
steps:
- - run: echo libtool autoconf automake pkg-config ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
- name: 'brew bundle'
-
- - run: "while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done"
- name: 'brew install'
-
- - run: |
- case "${{ matrix.build.install }}" in
- *openssl*)
- ;;
- *)
- if test -d /usr/local/include/openssl; then
- brew unlink openssl
- fi;;
- esac
- name: 'brew unlink openssl'
-
- - uses: actions/checkout@v4
-
- - run: cmake -S. -Bbuild -DCURL_WERROR=ON -DPICKY_COMPILER=ON ${{ matrix.build.generate }}
- name: 'cmake generate'
-
- - run: cmake --build build
- name: 'cmake build'
+ - run: echo libtool autoconf automake pkg-config ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
+ name: 'brew bundle'
+
+ - run: "while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done"
+ name: 'brew install'
+
+ - run: |
+ case "${{ matrix.build.install }}" in
+ *openssl*)
+ ;;
+ *)
+ if test -d /usr/local/include/openssl; then
+ brew unlink openssl
+ fi;;
+ esac
+ name: 'brew unlink openssl'
+
+ - uses: actions/checkout@v4
+
+ - run: cmake -S. -Bbuild -DCURL_WERROR=ON -DPICKY_COMPILER=ON ${{ matrix.build.generate }}
+ name: 'cmake generate'
+
+ - run: cmake --build build
+ name: 'cmake build'
diff --git a/.github/workflows/man-examples.yml b/.github/workflows/man-examples.yml
new file mode 100644
index 000000000..6f0d1e8ae
--- /dev/null
+++ b/.github/workflows/man-examples.yml
@@ -0,0 +1,35 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: manpage examples
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths:
+ - 'docs/libcurl/curl_*.3'
+ - 'docs/libcurl/opts/*.3'
+ - '.github/scripts/verify-examples.pl'
+ pull_request:
+ branches:
+ - master
+ paths:
+ - 'docs/libcurl/curl_*.3'
+ - 'docs/libcurl/opts/*.3'
+ - '.github/scripts/verify-examples.pl'
+
+jobs:
+ verify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: render nroff versions
+ run: autoreconf -fi && ./configure --without-ssl --without-libpsl && make -C docs
+
+ - name: verify examples
+ run: ./.github/scripts/verify-examples.pl docs/libcurl/curl*.3 docs/libcurl/opts/*.3
diff --git a/.github/workflows/ngtcp2-linux.yml b/.github/workflows/ngtcp2-linux.yml
index 0bc230aa4..19172b48f 100644
--- a/.github/workflows/ngtcp2-linux.yml
+++ b/.github/workflows/ngtcp2-linux.yml
@@ -7,35 +7,35 @@ name: ngtcp2-linux
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
# Hardcoded workflow filename as workflow name above is just Linux again
@@ -46,13 +46,13 @@ permissions: {}
env:
MAKEFLAGS: -j 3
- quictls-version: 3.0.10+quic
- gnutls-version: 3.8.0
+ quictls-version: 3.1.4+quic
+ gnutls-version: 3.8.3
wolfssl-version: master
- nghttp3-version: v0.15.0
- ngtcp2-version: v0.19.1
- nghttp2-version: v1.56.0
- mod_h2-version: v2.0.21
+ nghttp3-version: v1.1.0
+ ngtcp2-version: v1.2.0
+ nghttp2-version: v1.59.0
+ mod_h2-version: v2.0.26
jobs:
autotools:
@@ -63,208 +63,208 @@ jobs:
fail-fast: false
matrix:
build:
- - name: quictls
- configure: >-
- PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib"
- --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug
- --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
- --with-openssl=$HOME/nghttpx
- - name: gnutls
- configure: >-
- PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib"
- --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug
- --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
- --with-gnutls=$HOME/nghttpx
- - name: wolfssl
- configure: >-
- PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib"
- --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug
- --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
- --with-wolfssl=$HOME/nghttpx
+ - name: quictls
+ configure: >-
+ PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib"
+ --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug --disable-ntlm
+ --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
+ --with-openssl=$HOME/nghttpx
+ - name: gnutls
+ configure: >-
+ PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib"
+ --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug
+ --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
+ --with-gnutls=$HOME/nghttpx
+ - name: wolfssl
+ configure: >-
+ PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib"
+ --with-ngtcp2=$HOME/nghttpx --enable-warnings --enable-werror --enable-debug
+ --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
+ --with-wolfssl=$HOME/nghttpx
steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 \
- libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev \
- nettle-dev libp11-kit-dev libtspi-dev libunistring-dev guile-2.2-dev libtasn1-bin \
- libtasn1-6-dev libidn2-0-dev gawk gperf libtss2-dev dns-root-data bison gtk-doc-tools \
- texinfo texlive texlive-extra-utils autopoint libev-dev \
- apache2 apache2-dev libnghttp2-dev
- name: 'install prereqs and impacket, pytest, crypto, apache2'
-
- - name: cache quictls
- uses: actions/cache@v3
- id: cache-quictls
- env:
- cache-name: cache-quictls
- with:
- path: /home/runner/quictls
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.quictls-version }}
-
- - if: steps.cache-quictls.outputs.cache-hit != 'true'
- run: |
- cd $HOME
- git clone --quiet --depth=1 -b openssl-${{ env.quictls-version }} https://github.com/quictls/openssl quictls
- cd quictls
- ./config --prefix=$HOME/nghttpx --libdir=$HOME/nghttpx/lib
- make
- name: 'build quictls'
-
- - run: |
- cd $HOME/quictls
- make -j1 install_sw
- name: 'install quictls'
-
-
- - name: cache gnutls
- uses: actions/cache@v3
- id: cache-gnutls
- env:
- cache-name: cache-gnutls
- with:
- path: /home/runner/gnutls
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.gnutls-version }}
-
- - if: steps.cache-gnutls.outputs.cache-hit != 'true'
- run: |
- cd $HOME
- git clone --quiet --depth=1 -b ${{ env.gnutls-version }} https://github.com/gnutls/gnutls.git
- cd gnutls
- ./bootstrap
- ./configure --prefix=$HOME/nghttpx \
- PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib -L$HOME/nghttpx/lib" \
- --with-included-libtasn1 --with-included-unistring \
- --disable-guile --disable-doc --disable-tests --disable-tools
- make
- name: 'build gnutls'
-
- - run: |
- cd $HOME/gnutls
- make install
- name: 'install gnutls'
-
-
- - name: cache wolfssl
- uses: actions/cache@v3
- id: cache-wolfssl
- env:
- cache-name: cache-wolfssl
- with:
- path: /home/runner/wolfssl
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.wolfssl-version }}
-
- - if: steps.cache-wolfssl.outputs.cache-hit != 'true' || ${{ env.wolfssl-version }} == 'master'
- run: |
- cd $HOME
- rm -rf wolfssl
- git clone --quiet --depth=1 -b ${{ env.wolfssl-version }} https://github.com/wolfSSL/wolfssl.git
- cd wolfssl
- ./autogen.sh
- ./configure --enable-all --enable-quic --prefix=$HOME/nghttpx
- make
- name: 'build wolfssl'
-
- - run: |
- cd $HOME/wolfssl
- make install
- name: 'install wolfssl'
-
-
- - name: cache nghttp3
- uses: actions/cache@v3
- id: cache-nghttp3
- env:
- cache-name: cache-nghttp3
- with:
- path: /home/runner/nghttp3
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.nghttp3-version }}
-
- - if: steps.cache-nghttp3.outputs.cache-hit != 'true'
- run: |
- cd $HOME
- git clone --quiet --depth=1 -b ${{ env.nghttp3-version }} https://github.com/ngtcp2/nghttp3
- cd nghttp3
- autoreconf -fi
- ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only
- make
- name: 'build nghttp3'
-
- - run: |
- cd $HOME/nghttp3
- make install
- name: 'install nghttp3'
-
- # depends on all other cached libs built so far
- - run: |
- git clone --quiet --depth=1 -b ${{ env.ngtcp2-version }} https://github.com/ngtcp2/ngtcp2
- cd ngtcp2
- autoreconf -fi
- ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only --with-openssl --with-gnutls --with-wolfssl
- make install
- name: 'install ngtcp2'
-
- # depends on all other cached libs built so far
- - run: |
- git clone --quiet --depth=1 -b ${{ env.nghttp2-version }} https://github.com/nghttp2/nghttp2
- cd nghttp2
- autoreconf -fi
- ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-http3
- make install
- name: 'install nghttp2'
-
- - name: cache mod_h2
- uses: actions/cache@v3
- id: cache-mod_h2
- env:
- cache-name: cache-mod_h2
- with:
- path: /home/runner/mod_h2
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.mod_h2-version }}
-
- - if: steps.cache-mod_h2.outputs.cache-hit != 'true'
- run: |
- cd $HOME
- git clone --quiet --depth=1 -b ${{ env.mod_h2-version }} https://github.com/icing/mod_h2
- cd mod_h2
- autoreconf -fi
- ./configure
- make
- name: 'build mod_h2'
-
- - run: |
- cd $HOME/mod_h2
- sudo make install
- name: 'install mod_h2'
-
- - uses: actions/checkout@v4
-
- - run: |
- sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
- name: 'install python test prereqs'
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 -C tests
- name: 'make tests'
-
- - run: make V=1 test-ci
- name: 'run tests'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
-
- - run: pytest -v tests
- name: 'run pytest'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
- CURL_CI: github
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 \
+ libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev \
+ nettle-dev libp11-kit-dev libtspi-dev libunistring-dev guile-2.2-dev libtasn1-bin \
+ libtasn1-6-dev libidn2-0-dev gawk gperf libtss2-dev dns-root-data bison gtk-doc-tools \
+ texinfo texlive texlive-extra-utils autopoint libev-dev \
+ apache2 apache2-dev libnghttp2-dev
+ name: 'install prereqs and impacket, pytest, crypto, apache2'
+
+ - name: cache quictls
+ uses: actions/cache@v4
+ id: cache-quictls-no-deprecated
+ env:
+ cache-name: cache-quictls-no-deprecated
+ with:
+ path: /home/runner/quictls
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.quictls-version }}
+
+ - if: steps.cache-quictls-no-deprecated.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b openssl-${{ env.quictls-version }} https://github.com/quictls/openssl quictls
+ cd quictls
+ ./config no-deprecated --prefix=$HOME/nghttpx --libdir=$HOME/nghttpx/lib
+ make
+ name: 'build quictls'
+
+ - run: |
+ cd $HOME/quictls
+ make -j1 install_sw
+ name: 'install quictls'
+
+
+ - name: cache gnutls
+ uses: actions/cache@v4
+ id: cache-gnutls
+ env:
+ cache-name: cache-gnutls
+ with:
+ path: /home/runner/gnutls
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.gnutls-version }}
+
+ - if: steps.cache-gnutls.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.gnutls-version }} https://github.com/gnutls/gnutls.git
+ cd gnutls
+ ./bootstrap
+ ./configure --prefix=$HOME/nghttpx \
+ PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/nghttpx/lib -L$HOME/nghttpx/lib" \
+ --with-included-libtasn1 --with-included-unistring \
+ --disable-guile --disable-doc --disable-tests --disable-tools
+ make
+ name: 'build gnutls'
+
+ - run: |
+ cd $HOME/gnutls
+ make install
+ name: 'install gnutls'
+
+
+ - name: cache wolfssl
+ uses: actions/cache@v4
+ id: cache-wolfssl
+ env:
+ cache-name: cache-wolfssl
+ with:
+ path: /home/runner/wolfssl
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.wolfssl-version }}
+
+ - if: steps.cache-wolfssl.outputs.cache-hit != 'true' || ${{ env.wolfssl-version }} == 'master'
+ run: |
+ cd $HOME
+ rm -rf wolfssl
+ git clone --quiet --depth=1 -b ${{ env.wolfssl-version }} https://github.com/wolfSSL/wolfssl.git
+ cd wolfssl
+ ./autogen.sh
+ ./configure --enable-all --enable-quic --prefix=$HOME/nghttpx
+ make
+ name: 'build wolfssl'
+
+ - run: |
+ cd $HOME/wolfssl
+ make install
+ name: 'install wolfssl'
+
+
+ - name: cache nghttp3
+ uses: actions/cache@v4
+ id: cache-nghttp3
+ env:
+ cache-name: cache-nghttp3
+ with:
+ path: /home/runner/nghttp3
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.nghttp3-version }}
+
+ - if: steps.cache-nghttp3.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.nghttp3-version }} https://github.com/ngtcp2/nghttp3
+ cd nghttp3
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only
+ make
+ name: 'build nghttp3'
+
+ - run: |
+ cd $HOME/nghttp3
+ make install
+ name: 'install nghttp3'
+
+ # depends on all other cached libs built so far
+ - run: |
+ git clone --quiet --depth=1 -b ${{ env.ngtcp2-version }} https://github.com/ngtcp2/ngtcp2
+ cd ngtcp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only --with-openssl --with-gnutls --with-wolfssl
+ make install
+ name: 'install ngtcp2'
+
+ # depends on all other cached libs built so far
+ - run: |
+ git clone --quiet --depth=1 -b ${{ env.nghttp2-version }} https://github.com/nghttp2/nghttp2
+ cd nghttp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-http3
+ make install
+ name: 'install nghttp2'
+
+ - name: cache mod_h2
+ uses: actions/cache@v4
+ id: cache-mod_h2
+ env:
+ cache-name: cache-mod_h2
+ with:
+ path: /home/runner/mod_h2
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.mod_h2-version }}
+
+ - if: steps.cache-mod_h2.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.mod_h2-version }} https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure
+ make
+ name: 'build mod_h2'
+
+ - run: |
+ cd $HOME/mod_h2
+ sudo make install
+ name: 'install mod_h2'
+
+ - uses: actions/checkout@v4
+
+ - run: |
+ sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
+ name: 'install python test prereqs'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+
+ - run: pytest -v tests
+ name: 'run pytest'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+ CURL_CI: github
diff --git a/.github/workflows/osslq-linux.yml b/.github/workflows/osslq-linux.yml
new file mode 100644
index 000000000..997e35bab
--- /dev/null
+++ b/.github/workflows/osslq-linux.yml
@@ -0,0 +1,233 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: osslq-linux
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+ pull_request:
+ branches:
+ - master
+ paths-ignore:
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
+
+concurrency:
+ # Hardcoded workflow filename as workflow name above is just Linux again
+ group: osslq-${{ github.event.pull_request.number || github.sha }}
+ cancel-in-progress: true
+
+permissions: {}
+
+env:
+ MAKEFLAGS: -j 3
+ openssl3-version: openssl-3.2.0
+ quictls-version: 3.1.4+quic
+ nghttp3-version: v1.1.0
+ ngtcp2-version: v1.2.0
+ nghttp2-version: v1.59.0
+ mod_h2-version: v2.0.26
+
+jobs:
+ autotools:
+ name: ${{ matrix.build.name }}
+ runs-on: 'ubuntu-latest'
+ timeout-minutes: 60
+ strategy:
+ fail-fast: false
+ matrix:
+ build:
+ - name: openssl-quic
+ configure: >-
+ PKG_CONFIG_PATH="$HOME/openssl3/lib/pkgconfig" LDFLAGS="-Wl,-rpath,$HOME/openssl3/lib"
+ --enable-warnings --enable-werror --enable-debug --disable-ntlm
+ --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
+ --with-openssl=$HOME/openssl3 --with-openssl-quic
+ --with-nghttp3=$HOME/nghttpx
+
+ steps:
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 \
+ libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev \
+ nettle-dev libp11-kit-dev libtspi-dev libunistring-dev guile-2.2-dev libtasn1-bin \
+ libtasn1-6-dev libidn2-0-dev gawk gperf libtss2-dev dns-root-data bison gtk-doc-tools \
+ texinfo texlive texlive-extra-utils autopoint libev-dev \
+ apache2 apache2-dev libnghttp2-dev
+ name: 'install prereqs and impacket, pytest, crypto, apache2'
+
+ - name: cache openssl3
+ if: contains(matrix.build.install_steps, 'openssl3')
+ uses: actions/cache@v3
+ id: cache-openssl3
+ env:
+ cache-name: cache-openssl3
+ with:
+ path: /home/runner/openssl3
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.openssl3-version }}
+
+ - name: 'install openssl3'
+ if: steps.cache-openssl3.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.openssl3-version }} https://github.com/openssl/openssl
+ cd openssl
+ ./config --prefix=$HOME/openssl3 --libdir=$HOME/openssl3/lib
+ make -j1 install_sw
+
+ - name: cache quictls
+ if: contains(matrix.build.install_steps, 'quictls')
+ uses: actions/cache@v3
+ id: cache-quictls
+ env:
+ cache-name: cache-quictls
+ with:
+ path: /home/runner/quictls
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-quictls-${{ env.quictls-version }}
+
+ - name: cache quictls
+ uses: actions/cache@v3
+ id: cache-quictls-no-deprecated
+ env:
+ cache-name: cache-quictls-no-deprecated
+ with:
+ path: /home/runner/quictls
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.quictls-version }}
+
+ - if: steps.cache-quictls-no-deprecated.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b openssl-${{ env.quictls-version }} https://github.com/quictls/openssl quictls
+ cd quictls
+ ./config no-deprecated --prefix=$HOME/nghttpx --libdir=$HOME/nghttpx/lib
+ make
+ name: 'build quictls'
+
+ - run: |
+ cd $HOME/quictls
+ make -j1 install_sw
+ name: 'install quictls'
+
+
+ - name: cache nghttp3
+ uses: actions/cache@v3
+ id: cache-nghttp3
+ env:
+ cache-name: cache-nghttp3
+ with:
+ path: /home/runner/nghttp3
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.nghttp3-version }}
+
+ - if: steps.cache-nghttp3.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.nghttp3-version }} https://github.com/ngtcp2/nghttp3
+ cd nghttp3
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only
+ make
+ name: 'build nghttp3'
+
+ - run: |
+ cd $HOME/nghttp3
+ make install
+ name: 'install nghttp3'
+
+ # depends on all other cached libs built so far
+ - run: |
+ git clone --quiet --depth=1 -b ${{ env.ngtcp2-version }} https://github.com/ngtcp2/ngtcp2
+ cd ngtcp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only --with-openssl
+ make install
+ name: 'install ngtcp2'
+
+ # depends on all other cached libs built so far
+ - run: |
+ git clone --quiet --depth=1 -b ${{ env.nghttp2-version }} https://github.com/nghttp2/nghttp2
+ cd nghttp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-http3
+ make install
+ name: 'install nghttp2'
+
+ - name: cache mod_h2
+ uses: actions/cache@v3
+ id: cache-mod_h2
+ env:
+ cache-name: cache-mod_h2
+ with:
+ path: /home/runner/mod_h2
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.mod_h2-version }}
+
+ - if: steps.cache-mod_h2.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.mod_h2-version }} https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure
+ make
+ name: 'build mod_h2'
+
+ - run: |
+ cd $HOME/mod_h2
+ sudo make install
+ name: 'install mod_h2'
+
+ - uses: actions/checkout@v4
+
+ - run: |
+ sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
+ name: 'install python test prereqs'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ # 2500 and 25002 fail atm due to fin handling
+ TFLAGS: "!http/3"
+
+ - run: pytest -v tests
+ name: 'run pytest'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+ CURL_CI: github
diff --git a/.github/workflows/proselint.yml b/.github/workflows/proselint.yml
index b01133c3b..871266722 100644
--- a/.github/workflows/proselint.yml
+++ b/.github/workflows/proselint.yml
@@ -7,17 +7,17 @@ name: proselint
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths:
- - '.github/workflows/proselint.yml'
- - '**.md'
+ - '.github/workflows/proselint.yml'
+ - '**.md'
pull_request:
branches:
- - master
+ - master
paths:
- - '.github/workflows/proselint.yml'
- - '**.md'
+ - '.github/workflows/proselint.yml'
+ - '**.md'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
@@ -29,40 +29,41 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - name: install prereqs
- run: sudo apt-get install python3-proselint
+ - name: install prereqs
+ run: sudo apt-get install python3-proselint
- # config file help: https://github.com/amperser/proselint/
- - name: create proselint config
- run: |
- cat <<JSON > $HOME/.proselintrc
- {
- "checks": {
- "typography.diacritical_marks": false,
- "typography.symbols": false,
- "annotations.misc": false
+ # config file help: https://github.com/amperser/proselint/
+ - name: create proselint config
+ run: |
+ cat <<JSON > $HOME/.proselintrc
+ {
+ "checks": {
+ "typography.diacritical_marks": false,
+ "typography.symbols": false,
+ "annotations.misc": false,
+ "security.password": false
+ }
}
- }
- JSON
+ JSON
- - name: check prose
- run: a=`git ls-files '*.md' | grep -v docs/CHECKSRC.md` && proselint $a README
+ - name: check prose
+ run: a=`git ls-files '*.md' | grep -v docs/CHECKSRC.md` && proselint $a README
- # This is for CHECKSRC and files with aggressive exclamation mark needs
- - name: create second proselint config
- run: |
- cat <<JSON > $HOME/.proselintrc
- {
- "checks": {
- "typography.diacritical_marks": false,
- "typography.symbols": false,
- "typography.exclamation": false,
- "annotations.misc": false
+ # This is for CHECKSRC and files with aggressive exclamation mark needs
+ - name: create second proselint config
+ run: |
+ cat <<JSON > $HOME/.proselintrc
+ {
+ "checks": {
+ "typography.diacritical_marks": false,
+ "typography.symbols": false,
+ "typography.exclamation": false,
+ "annotations.misc": false
+ }
}
- }
- JSON
+ JSON
- - name: check special prose
- run: a=docs/CHECKSRC.md && proselint $a
+ - name: check special prose
+ run: a=docs/CHECKSRC.md && proselint $a
diff --git a/.github/workflows/quiche-linux.yml b/.github/workflows/quiche-linux.yml
index 90dec5e3a..40fc4d580 100644
--- a/.github/workflows/quiche-linux.yml
+++ b/.github/workflows/quiche-linux.yml
@@ -7,35 +7,35 @@ name: quiche
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
# Hardcoded workflow filename as workflow name above is just Linux again
@@ -46,12 +46,12 @@ permissions: {}
env:
MAKEFLAGS: -j 3
- openssl-version: 3.0.10+quic
- nghttp3-version: v0.15.0
- ngtcp2-version: v0.19.1
- nghttp2-version: v1.56.0
- quiche-version: 0.17.2
- mod_h2-version: v2.0.21
+ openssl-version: 3.1.4+quic
+ nghttp3-version: v1.1.0
+ ngtcp2-version: v1.2.0
+ nghttp2-version: v1.59.0
+ quiche-version: 0.20.0
+ mod_h2-version: v2.0.26
jobs:
autotools:
@@ -62,149 +62,149 @@ jobs:
fail-fast: false
matrix:
build:
- - name: quiche
- install: >-
- libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev
- install_steps: pytest
- configure: >-
- LDFLAGS="-Wl,-rpath,/home/runner/quiche/target/release"
- --with-openssl=/home/runner/quiche/quiche/deps/boringssl/src
- --enable-debug
- --with-quiche=/home/runner/quiche/target/release
- --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
- --with-ca-fallback
+ - name: quiche
+ install: >-
+ libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libev-dev libc-ares-dev
+ install_steps: pytest
+ configure: >-
+ LDFLAGS="-Wl,-rpath,/home/runner/quiche/target/release"
+ --with-openssl=/home/runner/quiche/quiche/deps/boringssl/src
+ --enable-debug
+ --with-quiche=/home/runner/quiche/target/release
+ --with-test-nghttpx="$HOME/nghttpx/bin/nghttpx"
+ --with-ca-fallback
steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo apt-get install apache2 apache2-dev libnghttp2-dev
- name: 'install prereqs and impacket, pytest, crypto'
-
- - name: cache nghttpx
- uses: actions/cache@v3
- id: cache-nghttpx
- env:
- cache-name: cache-nghttpx
- with:
- path: /home/runner/nghttpx
- key: ${{ runner.os }}-build-${{ env.cache-name }}-openssl-${{ env.openssl-version }}-nghttp3-${{ env.nghttp3-version }}-ngtcp2-${{ env.ngtcp2-version }}-nghttp2-${{ env.nghttp2-version }}
-
- - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b openssl-${{ env.openssl-version }} https://github.com/quictls/openssl
- cd openssl
- ./config --prefix=$HOME/nghttpx --libdir=$HOME/nghttpx/lib
- make -j1 install_sw
- name: 'install quictls'
-
- - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.nghttp3-version }} https://github.com/ngtcp2/nghttp3
- cd nghttp3
- autoreconf -fi
- ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only
- make install
- name: 'install nghttp3'
-
- - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.ngtcp2-version }} https://github.com/ngtcp2/ngtcp2
- cd ngtcp2
- autoreconf -fi
- ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only --with-openssl
- make install
- name: 'install ngtcp2'
-
- - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b ${{ env.nghttp2-version }} https://github.com/nghttp2/nghttp2
- cd nghttp2
- autoreconf -fi
- ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-http3
- make install
- name: 'install nghttp2'
-
- - name: cache quiche
- uses: actions/cache@v3
- id: cache-quiche
- env:
- cache-name: cache-quiche
- with:
- path: /home/runner/quiche
- key: ${{ runner.os }}-build-${{ env.cache-name }}-quiche-${{ env.quiche-version }}
-
- - if: steps.cache-quiche.outputs.cache-hit != 'true'
- run: |
- cd $HOME
- git clone --quiet --depth=1 -b ${{ env.quiche-version }} --recursive https://github.com/cloudflare/quiche.git
- cd quiche
- #### Work-around https://github.com/curl/curl/issues/7927 #######
- #### See https://github.com/alexcrichton/cmake-rs/issues/131 ####
- sed -i -e 's/cmake = "0.1"/cmake = "=0.1.45"/' quiche/Cargo.toml
-
- cargo build -v --package quiche --release --features ffi,pkg-config-meta,qlog --verbose
- mkdir -v quiche/deps/boringssl/src/lib
- ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) quiche/deps/boringssl/src/lib/
-
- # include dir
- # /home/runner/quiche/quiche/deps/boringssl/src/include
- # lib dir
- # /home/runner/quiche/quiche/deps/boringssl/src/lib
- name: 'build quiche and boringssl'
-
- - name: cache mod_h2
- uses: actions/cache@v3
- id: cache-mod_h2
- env:
- cache-name: cache-mod_h2
- with:
- path: /home/runner/mod_h2
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.mod_h2-version }}
-
- - if: steps.cache-mod_h2.outputs.cache-hit != 'true'
- run: |
- cd $HOME
- git clone --quiet --depth=1 -b ${{ env.mod_h2-version }} https://github.com/icing/mod_h2
- cd mod_h2
- autoreconf -fi
- ./configure
- make
- name: 'build mod_h2'
-
- - run: |
- cd $HOME/mod_h2
- sudo make install
- name: 'install mod_h2'
-
- - uses: actions/checkout@v4
-
- - run: |
- sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
- name: 'install python test prereqs'
-
- - run: autoreconf -fi
- name: 'autoreconf'
-
- - run: ./configure ${{ matrix.build.configure }}
- name: 'configure'
-
- - run: make V=1
- name: 'make'
-
- - run: make V=1 examples
- name: 'make examples'
-
- - run: make V=1 -C tests
- name: 'make tests'
-
- - run: make V=1 test-ci
- name: 'run tests'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
-
- - run: pytest -v tests
- name: 'run pytest'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
- CURL_CI: github
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
+ sudo apt-get install apache2 apache2-dev libnghttp2-dev
+ name: 'install prereqs and impacket, pytest, crypto'
+
+ - name: cache nghttpx
+ uses: actions/cache@v4
+ id: cache-nghttpx
+ env:
+ cache-name: cache-nghttpx
+ with:
+ path: /home/runner/nghttpx
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-openssl-${{ env.openssl-version }}-nghttp3-${{ env.nghttp3-version }}-ngtcp2-${{ env.ngtcp2-version }}-nghttp2-${{ env.nghttp2-version }}
+
+ - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b openssl-${{ env.openssl-version }} https://github.com/quictls/openssl
+ cd openssl
+ ./config --prefix=$HOME/nghttpx --libdir=$HOME/nghttpx/lib
+ make -j1 install_sw
+ name: 'install quictls'
+
+ - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.nghttp3-version }} https://github.com/ngtcp2/nghttp3
+ cd nghttp3
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only
+ make install
+ name: 'install nghttp3'
+
+ - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.ngtcp2-version }} https://github.com/ngtcp2/ngtcp2
+ cd ngtcp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-lib-only --with-openssl
+ make install
+ name: 'install ngtcp2'
+
+ - if: steps.cache-nghttpx.outputs.cache-hit != 'true'
+ run: |
+ git clone --quiet --depth=1 -b ${{ env.nghttp2-version }} https://github.com/nghttp2/nghttp2
+ cd nghttp2
+ autoreconf -fi
+ ./configure --prefix=$HOME/nghttpx PKG_CONFIG_PATH="$HOME/nghttpx/lib/pkgconfig" --enable-http3
+ make install
+ name: 'install nghttp2'
+
+ - name: cache quiche
+ uses: actions/cache@v4
+ id: cache-quiche
+ env:
+ cache-name: cache-quiche
+ with:
+ path: /home/runner/quiche
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-quiche-${{ env.quiche-version }}
+
+ - if: steps.cache-quiche.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.quiche-version }} --recursive https://github.com/cloudflare/quiche.git
+ cd quiche
+ #### Work-around https://github.com/curl/curl/issues/7927 #######
+ #### See https://github.com/alexcrichton/cmake-rs/issues/131 ####
+ sed -i -e 's/cmake = "0.1"/cmake = "=0.1.45"/' quiche/Cargo.toml
+
+ cargo build -v --package quiche --release --features ffi,pkg-config-meta,qlog --verbose
+ mkdir -v quiche/deps/boringssl/src/lib
+ ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) quiche/deps/boringssl/src/lib/
+
+ # include dir
+ # /home/runner/quiche/quiche/deps/boringssl/src/include
+ # lib dir
+ # /home/runner/quiche/quiche/deps/boringssl/src/lib
+ name: 'build quiche and boringssl'
+
+ - name: cache mod_h2
+ uses: actions/cache@v4
+ id: cache-mod_h2
+ env:
+ cache-name: cache-mod_h2
+ with:
+ path: /home/runner/mod_h2
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.mod_h2-version }}
+
+ - if: steps.cache-mod_h2.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b ${{ env.mod_h2-version }} https://github.com/icing/mod_h2
+ cd mod_h2
+ autoreconf -fi
+ ./configure
+ make
+ name: 'build mod_h2'
+
+ - run: |
+ cd $HOME/mod_h2
+ sudo make install
+ name: 'install mod_h2'
+
+ - uses: actions/checkout@v4
+
+ - run: |
+ sudo python3 -m pip install -r tests/requirements.txt -r tests/http/requirements.txt
+ name: 'install python test prereqs'
+
+ - run: autoreconf -fi
+ name: 'autoreconf'
+
+ - run: ./configure ${{ matrix.build.configure }}
+ name: 'configure'
+
+ - run: make V=1
+ name: 'make'
+
+ - run: make V=1 examples
+ name: 'make examples'
+
+ - run: make V=1 -C tests
+ name: 'make tests'
+
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+
+ - run: pytest -v tests
+ name: 'run pytest'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
+ CURL_CI: github
diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml
index 0cb5295c7..27b33e2c8 100644
--- a/.github/workflows/reuse.yml
+++ b/.github/workflows/reuse.yml
@@ -8,11 +8,11 @@ name: REUSE compliance
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
pull_request:
branches:
- - master
+ - master
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
@@ -24,6 +24,6 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - name: REUSE Compliance Check
- uses: fsfe/reuse-action@v2
+ - uses: actions/checkout@v4
+ - name: REUSE Compliance Check
+ uses: fsfe/reuse-action@v2
diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml
index 4793cf190..a619fcc04 100644
--- a/.github/workflows/spellcheck.yml
+++ b/.github/workflows/spellcheck.yml
@@ -6,24 +6,24 @@ name: spell
on:
push:
branches:
- - master
+ - master
paths:
- - '**.md'
- - '**.3'
- - '**.1'
- - '**/spellcheck.yml'
- - '**/spellcheck.yaml'
- - '**/wordlist.txt'
+ - '**.md'
+ - '**.3'
+ - '**.1'
+ - '**/spellcheck.yml'
+ - '**/spellcheck.yaml'
+ - '**/wordlist.txt'
pull_request:
branches:
- - master
+ - master
paths:
- - '**.md'
- - '**.3'
- - '**.1'
- - '**/spellcheck.yml'
- - '**/spellcheck.yaml'
- - '**/wordlist.txt'
+ - '**.md'
+ - '**.3'
+ - '**.1'
+ - '**/spellcheck.yml'
+ - '**/spellcheck.yaml'
+ - '**/wordlist.txt'
permissions: {}
@@ -31,36 +31,42 @@ jobs:
check:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - name: install pandoc
- run: sudo apt-get install pandoc
+ - name: install pandoc
+ run: sudo apt-get install pandoc
- - name: build curl.1
- run: |
- autoreconf -fi
- ./configure --without-ssl
- make -C docs
+ - name: build curl.1
+ run: |
+ autoreconf -fi
+ ./configure --without-ssl --without-libpsl
+ make -C docs
- - name: strip "uncheckable" sections from .3 pages
- run: find docs -name "*.3" -size +40c | sed 's/\.3//' | xargs -t -n1 -I OO ./.github/scripts/cleanspell.pl OO.3 OO.33
+ - name: strip "uncheckable" sections from .3 pages
+ run: find docs -name "*.3" -size +40c | sed 's/\.3//' | xargs -t -n1 -I OO ./.github/scripts/cleanspell.pl OO.3 OO.33
- - name: convert .3 man pages to markdown
- run: find docs -name "*.33" -size +40c | sed 's/\.33//' | xargs -t -n1 -I OO pandoc -f man -t markdown OO.33 -o OO.md
+ - name: convert .3 man pages to markdown
+ run: find docs -name "*.33" -size +40c | sed 's/\.33//' | xargs -t -n1 -I OO pandoc -f man -t markdown OO.33 -o OO.md
- - name: convert .1 man pages to markdown
- run: find docs -name "*.1" -size +40c | sed 's/\.1//' | xargs -t -n1 -I OO pandoc OO.1 -o OO.md
+ - name: convert .1 man pages to markdown
+ run: find docs -name "*.1" -size +40c | sed 's/\.1//' | xargs -t -n1 -I OO pandoc OO.1 -o OO.md
- - name: trim the curl.1 markdown file
- run: |
- perl -pi -e 's/^ .*//' docs/curl.md
- perl -pi -e 's/\-\-[\a-z0-9-]*//ig' docs/curl.md
- perl -pi -e 's!https://[a-z0-9%/.-]*!!ig' docs/curl.md
+ - name: trim the curl.1 markdown file
+ run: |
+ perl -pi -e 's/^ .*//' docs/curl.md
+ perl -pi -e 's/\-\-[\a-z0-9-]*//ig' docs/curl.md
+ perl -pi -e 's!https://[a-z0-9%/.-]*!!ig' docs/curl.md
- - name: setup the custom wordlist
- run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt
+ - name: trim the cmdline docs markdown files
+ run: find docs/cmdline-opts -name "*.md" ! -name "_*" ! -name MANPAGE.md | xargs -n1 ./.github/scripts/cleancmd.pl
- - name: Check Spelling
- uses: rojopolis/spellcheck-github-actions@v0
- with:
- config_path: .github/scripts/spellcheck.yaml
+ - name: trim the cmdline docs markdown _*.md files
+ run: find docs/cmdline-opts -name "_*.md" | xargs -n1 ./.github/scripts/cleancmd.pl --no-header
+
+ - name: setup the custom wordlist
+ run: grep -v '^#' .github/scripts/spellcheck.words > wordlist.txt
+
+ - name: Check Spelling
+ uses: rojopolis/spellcheck-github-actions@v0
+ with:
+ config_path: .github/scripts/spellcheck.yaml
diff --git a/.github/workflows/synopsis.yml b/.github/workflows/synopsis.yml
new file mode 100644
index 000000000..0938f4bfc
--- /dev/null
+++ b/.github/workflows/synopsis.yml
@@ -0,0 +1,28 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+name: SYNOPSIS
+
+on:
+ push:
+ branches:
+ - master
+ - '*/ci'
+ paths:
+ - 'docs/libcurl/curl_*.3'
+ pull_request:
+ branches:
+ - master
+ paths:
+ - 'docs/libcurl/curl_*.3'
+
+jobs:
+ verify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: verify-synopsis
+ run: ./.github/scripts/verify-synopsis.pl docs/libcurl/curl*.3
diff --git a/.github/workflows/torture.yml b/.github/workflows/torture.yml
index fa70eecd4..a50b37f14 100644
--- a/.github/workflows/torture.yml
+++ b/.github/workflows/torture.yml
@@ -7,35 +7,35 @@ name: Linux torture
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
# Hardcoded workflow filename as workflow name above is just Linux again
@@ -56,37 +56,37 @@ jobs:
fail-fast: false
matrix:
build:
- - name: torture
- install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libnghttp2-dev libssh2-1-dev libc-ares-dev
- configure: --with-openssl --enable-debug --enable-ares --enable-websockets
- tflags: -n -t --shallow=25 !FTP
- - name: torture-ftp
- install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libnghttp2-dev libssh2-1-dev libc-ares-dev
- configure: --with-openssl --enable-debug --enable-ares
- tflags: -n -t --shallow=20 FTP
+ - name: torture
+ install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libnghttp2-dev libssh2-1-dev libc-ares-dev
+ configure: --with-openssl --enable-debug --enable-ares --enable-websockets
+ tflags: -n -t --shallow=25 !FTP
+ - name: torture-ftp
+ install: libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libnghttp2-dev libssh2-1-dev libc-ares-dev
+ configure: --with-openssl --enable-debug --enable-ares
+ tflags: -n -t --shallow=20 FTP
steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - run: autoreconf -fi
- name: 'autoreconf'
+ - run: autoreconf -fi
+ name: 'autoreconf'
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ name: 'configure'
- - run: make V=1
- name: 'make'
+ - run: make V=1
+ name: 'make'
- - run: make V=1 -C tests
- name: 'make tests'
+ - run: make V=1 -C tests
+ name: 'make tests'
- - run: make V=1 test-torture
- name: 'run tests'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
+ - run: make V=1 test-torture
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.github/workflows/wolfssl.yml b/.github/workflows/wolfssl.yml
index 48c831dd7..5aaf3d1bd 100644
--- a/.github/workflows/wolfssl.yml
+++ b/.github/workflows/wolfssl.yml
@@ -7,35 +7,35 @@ name: Linux wolfSSL
on:
push:
branches:
- - master
- - '*/ci'
+ - master
+ - '*/ci'
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
pull_request:
branches:
- - master
+ - master
paths-ignore:
- - '**/*.md'
- - '**/CMakeLists.txt'
- - '.azure-pipelines.yml'
- - '.circleci/**'
- - '.cirrus.yml'
- - 'appveyor.yml'
- - 'CMake/**'
- - 'packages/**'
- - 'plan9/**'
- - 'projects/**'
- - 'winbuild/**'
+ - '**/*.md'
+ - '**/CMakeLists.txt'
+ - '.azure-pipelines.yml'
+ - '.circleci/**'
+ - '.cirrus.yml'
+ - 'appveyor.*'
+ - 'CMake/**'
+ - 'packages/**'
+ - 'plan9/**'
+ - 'projects/**'
+ - 'winbuild/**'
concurrency:
# Hardcoded workflow filename as workflow name above is just Linux again
@@ -56,50 +56,50 @@ jobs:
fail-fast: false
matrix:
build:
- - name: wolfssl (configured with --enable-all)
- install:
- configure: LDFLAGS="-Wl,-rpath,$HOME/wssl/lib" --with-wolfssl=$HOME/wssl --enable-debug
- wolfssl-configure: --enable-all
- - name: wolfssl (configured with --enable-opensslextra)
- install:
- configure: LDFLAGS="-Wl,-rpath,$HOME/wssl/lib" --with-wolfssl=$HOME/wssl --enable-debug
- wolfssl-configure: --enable-opensslextra
+ - name: wolfssl (configured with --enable-all)
+ install:
+ configure: LDFLAGS="-Wl,-rpath,$HOME/wssl/lib" --with-wolfssl=$HOME/wssl --enable-debug
+ wolfssl-configure: --enable-all
+ - name: wolfssl (configured with --enable-opensslextra)
+ install:
+ configure: LDFLAGS="-Wl,-rpath,$HOME/wssl/lib" --with-wolfssl=$HOME/wssl --enable-debug
+ wolfssl-configure: --enable-opensslextra
steps:
- - run: |
- sudo apt-get update
- sudo apt-get install libtool autoconf automake pkg-config stunnel4 ${{ matrix.build.install }}
- sudo python3 -m pip install impacket
- name: 'install prereqs and impacket'
+ - run: |
+ sudo apt-get update
+ sudo apt-get install libtool autoconf automake pkg-config stunnel4 libpsl-dev ${{ matrix.build.install }}
+ sudo python3 -m pip install impacket
+ name: 'install prereqs and impacket'
- - run: |
- WOLFSSL_VER=5.6.3
- curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://github.com/wolfSSL/wolfssl/archive/v$WOLFSSL_VER-stable.tar.gz
- tar -xzf v$WOLFSSL_VER-stable.tar.gz
- cd wolfssl-$WOLFSSL_VER-stable
- ./autogen.sh
- ./configure --enable-tls13 ${{ matrix.build.wolfssl-configure }} --enable-harden --prefix=$HOME/wssl
- make install
- name: 'install wolfssl'
+ - run: |
+ WOLFSSL_VER=5.6.3
+ curl -LOsSf --retry 6 --retry-connrefused --max-time 999 https://github.com/wolfSSL/wolfssl/archive/v$WOLFSSL_VER-stable.tar.gz
+ tar -xzf v$WOLFSSL_VER-stable.tar.gz
+ cd wolfssl-$WOLFSSL_VER-stable
+ ./autogen.sh
+ ./configure --enable-tls13 ${{ matrix.build.wolfssl-configure }} --enable-harden --prefix=$HOME/wssl
+ make install
+ name: 'install wolfssl'
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - run: autoreconf -fi
- name: 'autoreconf'
+ - run: autoreconf -fi
+ name: 'autoreconf'
- - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
- name: 'configure'
+ - run: ./configure --enable-warnings --enable-werror ${{ matrix.build.configure }}
+ name: 'configure'
- - run: make V=1
- name: 'make'
+ - run: make V=1
+ name: 'make'
- - run: make V=1 examples
- name: 'make examples'
+ - run: make V=1 examples
+ name: 'make examples'
- - run: make V=1 -C tests
- name: 'make tests'
+ - run: make V=1 -C tests
+ name: 'make tests'
- - run: make V=1 test-ci
- name: 'run tests'
- env:
- TFLAGS: "${{ matrix.build.tflags }}"
+ - run: make V=1 test-ci
+ name: 'run tests'
+ env:
+ TFLAGS: "${{ matrix.build.tflags }}"
diff --git a/.reuse/dep5 b/.reuse/dep5
index 3a7a672a2..60c9a012d 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -96,3 +96,7 @@ License: curl
Files: .mailmap
Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
License: curl
+
+Files: .github/dependabot.yml
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
+License: curl
diff --git a/CMake/CurlTests.c b/CMake/CurlTests.c
index ea80ec89a..83d743d34 100644
--- a/CMake/CurlTests.c
+++ b/CMake/CurlTests.c
@@ -23,7 +23,6 @@
***************************************************************************/
#ifdef HAVE_FCNTL_O_NONBLOCK
-
/* headers for FCNTL_O_NONBLOCK test */
#include <sys/types.h>
#include <unistd.h>
@@ -45,14 +44,13 @@
#error "O_NONBLOCK does not work on this platform"
#endif
-int
-main ()
+int main(void)
{
- /* O_NONBLOCK source test */
- int flags = 0;
- if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK))
- return 1;
- return 0;
+ /* O_NONBLOCK source test */
+ int flags = 0;
+ if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK))
+ return 1;
+ return 0;
}
#endif
@@ -108,36 +106,16 @@ int main(void)
}
#endif
-#ifdef HAVE_SOCKLEN_T
-#ifdef _WIN32
-#include <ws2tcpip.h>
-#else
-#include <sys/types.h>
-#include <sys/socket.h>
-#endif
-int
-main ()
-{
-if ((socklen_t *) 0)
- return 0;
-if (sizeof (socklen_t))
- return 0;
- ;
- return 0;
-}
-#endif
#ifdef HAVE_IN_ADDR_T
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
-
-int
-main ()
+int main(void)
{
-if ((in_addr_t *) 0)
- return 0;
-if (sizeof (in_addr_t))
- return 0;
+ if((in_addr_t *) 0)
+ return 0;
+ if(sizeof(in_addr_t))
+ return 0;
;
return 0;
}
@@ -150,11 +128,10 @@ if (sizeof (in_addr_t))
#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#endif
-int
-main ()
+int main(void)
{
-if (sizeof (bool *) )
- return 0;
+ if(sizeof(bool *))
+ return 0;
;
return 0;
}
@@ -165,8 +142,9 @@ if (sizeof (bool *) )
#include <stdarg.h>
#include <string.h>
#include <float.h>
-int main() { return 0; }
+int main(void) { return 0; }
#endif
+
#ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
@@ -181,104 +159,83 @@ int main() { return 0; }
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
-int main () { ; return 0; }
+int main(void) { ; return 0; }
#endif
+
#ifdef HAVE_IOCTLSOCKET
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
+# include <winsock2.h>
#endif
-
-int
-main ()
+int main(void)
{
-
-/* ioctlsocket source code */
- int socket;
- unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
-
+ /* ioctlsocket source code */
+ int socket;
+ unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
;
return 0;
}
#endif
+
#ifdef HAVE_IOCTLSOCKET_CAMEL
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
+# include <winsock2.h>
#endif
-
-int
-main ()
+int main(void)
{
-
-/* IoctlSocket source code */
- if(0 != IoctlSocket(0, 0, 0))
- return 1;
+ /* IoctlSocket source code */
+ if(0 != IoctlSocket(0, 0, 0))
+ return 1;
;
return 0;
}
#endif
+
#ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
+# include <winsock2.h>
#endif
-
-int
-main ()
+int main(void)
{
-
-/* IoctlSocket source code */
- long flags = 0;
- if(0 != IoctlSocket(0, FIONBIO, &flags))
- return 1;
+ /* IoctlSocket source code */
+ long flags = 0;
+ if(0 != IoctlSocket(0, FIONBIO, &flags))
+ return 1;
;
return 0;
}
#endif
+
#ifdef HAVE_IOCTLSOCKET_FIONBIO
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
+# include <winsock2.h>
#endif
-
-int
-main ()
+int main(void)
{
-
- int flags = 0;
- if(0 != ioctlsocket(0, FIONBIO, &flags))
- return 1;
-
+ int flags = 0;
+ if(0 != ioctlsocket(0, FIONBIO, &flags))
+ return 1;
;
return 0;
}
#endif
+
#ifdef HAVE_IOCTL_FIONBIO
/* headers for FIONBIO test */
/* includes start */
@@ -297,19 +254,16 @@ main ()
#ifdef HAVE_STROPTS_H
# include <stropts.h>
#endif
-
-int
-main ()
+int main(void)
{
-
- int flags = 0;
- if(0 != ioctl(0, FIONBIO, &flags))
- return 1;
-
+ int flags = 0;
+ if(0 != ioctl(0, FIONBIO, &flags))
+ return 1;
;
return 0;
}
#endif
+
#ifdef HAVE_IOCTL_SIOCGIFADDR
/* headers for FIONBIO test */
/* includes start */
@@ -329,28 +283,23 @@ main ()
# include <stropts.h>
#endif
#include <net/if.h>
-
-int
-main ()
+int main(void)
{
- struct ifreq ifr;
- if(0 != ioctl(0, SIOCGIFADDR, &ifr))
- return 1;
-
+ struct ifreq ifr;
+ if(0 != ioctl(0, SIOCGIFADDR, &ifr))
+ return 1;
;
return 0;
}
#endif
+
#ifdef HAVE_SETSOCKOPT_SO_NONBLOCK
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
+# include <winsock2.h>
#endif
/* includes start */
#ifdef HAVE_SYS_TYPES_H
@@ -360,30 +309,30 @@ main ()
# include <sys/socket.h>
#endif
/* includes end */
-
-int
-main ()
+int main(void)
{
- if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0))
- return 1;
+ if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0))
+ return 1;
;
return 0;
}
#endif
+
#ifdef HAVE_GLIBC_STRERROR_R
#include <string.h>
#include <errno.h>
void check(char c) {}
-int
-main () {
+int main(void)
+{
char buffer[1024];
/* This will not compile if strerror_r does not return a char* */
check(strerror_r(EACCES, buffer, sizeof(buffer))[0]);
return 0;
}
#endif
+
#ifdef HAVE_POSIX_STRERROR_R
#include <string.h>
#include <errno.h>
@@ -391,92 +340,51 @@ main () {
/* float, because a pointer can't be implicitly cast to float */
void check(float f) {}
-int
-main () {
+int main(void)
+{
char buffer[1024];
/* This will not compile if strerror_r does not return an int */
check(strerror_r(EACCES, buffer, sizeof(buffer)));
return 0;
}
#endif
+
#ifdef HAVE_FSETXATTR_6
#include <sys/xattr.h> /* header from libc, not from libattr */
-int
-main() {
+int main(void)
+{
fsetxattr(0, 0, 0, 0, 0, 0);
return 0;
}
#endif
+
#ifdef HAVE_FSETXATTR_5
#include <sys/xattr.h> /* header from libc, not from libattr */
-int
-main() {
+int main(void)
+{
fsetxattr(0, 0, 0, 0, 0);
return 0;
}
#endif
+
#ifdef HAVE_CLOCK_GETTIME_MONOTONIC
#include <time.h>
-int
-main() {
+int main(void)
+{
struct timespec ts = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &ts);
return 0;
}
#endif
+
#ifdef HAVE_BUILTIN_AVAILABLE
-int
-main() {
+int main(void)
+{
if(__builtin_available(macOS 10.12, *)) {}
return 0;
}
#endif
-#ifdef HAVE_VARIADIC_MACROS_C99
-#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__)
-#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__)
-
-int fun3(int arg1, int arg2, int arg3);
-int fun2(int arg1, int arg2);
-
-int fun3(int arg1, int arg2, int arg3) {
- return arg1 + arg2 + arg3;
-}
-int fun2(int arg1, int arg2) {
- return arg1 + arg2;
-}
-
-int
-main() {
- int res3 = c99_vmacro3(1, 2, 3);
- int res2 = c99_vmacro2(1, 2);
- (void)res3;
- (void)res2;
- return 0;
-}
-#endif
-#ifdef HAVE_VARIADIC_MACROS_GCC
-#define gcc_vmacro3(first, args...) fun3(first, args)
-#define gcc_vmacro2(first, args...) fun2(first, args)
-int fun3(int arg1, int arg2, int arg3);
-int fun2(int arg1, int arg2);
-
-int fun3(int arg1, int arg2, int arg3) {
- return arg1 + arg2 + arg3;
-}
-int fun2(int arg1, int arg2) {
- return arg1 + arg2;
-}
-
-int
-main() {
- int res3 = gcc_vmacro3(1, 2, 3);
- int res2 = gcc_vmacro2(1, 2);
- (void)res3;
- (void)res2;
- return 0;
-}
-#endif
#ifdef HAVE_ATOMIC
/* includes start */
#ifdef HAVE_SYS_TYPES_H
@@ -490,17 +398,24 @@ main() {
#endif
/* includes end */
-int
-main() {
+int main(void)
+{
_Atomic int i = 1;
i = 0; /* Force an atomic-write operation. */
return i;
}
#endif
+
#ifdef HAVE_WIN32_WINNT
/* includes start */
-#ifdef WIN32
-# include "../lib/setup-win32.h"
+#ifdef _WIN32
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+# ifndef NOGDI
+# define NOGDI
+# endif
+# include <windows.h>
#endif
/* includes end */
@@ -508,8 +423,8 @@ main() {
#define expand(x) enquote(x)
#pragma message("_WIN32_WINNT=" expand(_WIN32_WINNT))
-int
-main() {
+int main(void)
+{
return 0;
}
#endif
diff --git a/CMake/FindZstd.cmake b/CMake/FindZstd.cmake
index 973e6ad4a..0ea9e0c87 100644
--- a/CMake/FindZstd.cmake
+++ b/CMake/FindZstd.cmake
@@ -56,11 +56,18 @@ find_library(Zstd_LIBRARY NAMES zstd
${PC_Zstd_LIBRARY_DIRS}
)
+if(Zstd_INCLUDE_DIR)
+ file(READ "${Zstd_INCLUDE_DIR}/zstd.h" _zstd_header)
+ string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" _zstd_ver "${_zstd_header}")
+ set(Zstd_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
+endif()
+
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Zstd
REQUIRED_VARS
Zstd_LIBRARY
Zstd_INCLUDE_DIR
+ VERSION_VAR Zstd_VERSION
)
if(Zstd_FOUND)
diff --git a/CMake/Macros.cmake b/CMake/Macros.cmake
index e12bf303f..9ff62ea72 100644
--- a/CMake/Macros.cmake
+++ b/CMake/Macros.cmake
@@ -23,19 +23,6 @@
###########################################################################
#File defines convenience macros for available feature testing
-# This macro checks if the symbol exists in the library and if it
-# does, it prepends library to the list. It is intended to be called
-# multiple times with a sequence of possibly dependent libraries in
-# order of least-to-most-dependent. Some libraries depend on others
-# to link correctly.
-macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE)
- check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
- ${VARIABLE})
- if(${VARIABLE})
- set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
- endif()
-endmacro()
-
# Check if header file exists and add it to the list.
# This macro is intended to be called multiple times with a sequence of
# possibly dependent header files. Some headers depend on others to be
@@ -58,7 +45,7 @@ macro(curl_internal_test CURL_TEST)
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
endif()
- message(STATUS "Performing Curl Test ${CURL_TEST}")
+ message(STATUS "Performing Test ${CURL_TEST}")
try_compile(${CURL_TEST}
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
@@ -67,15 +54,15 @@ macro(curl_internal_test CURL_TEST)
OUTPUT_VARIABLE OUTPUT)
if(${CURL_TEST})
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
- message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
+ message(STATUS "Performing Test ${CURL_TEST} - Success")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Performing Curl Test ${CURL_TEST} passed with the following output:\n"
+ "Performing Test ${CURL_TEST} passed with the following output:\n"
"${OUTPUT}\n")
else()
- message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
+ message(STATUS "Performing Test ${CURL_TEST} - Failed")
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Performing Curl Test ${CURL_TEST} failed with the following output:\n"
+ "Performing Test ${CURL_TEST} failed with the following output:\n"
"${OUTPUT}\n")
endif()
endif()
diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake
index d67a9059b..7701c0ee9 100644
--- a/CMake/OtherTests.cmake
+++ b/CMake/OtherTests.cmake
@@ -23,115 +23,89 @@
###########################################################################
include(CheckCSourceCompiles)
include(CheckCSourceRuns)
-
-# The begin of the sources (macros and includes)
-set(_source_epilogue "#undef inline")
+include(CheckTypeSize)
macro(add_header_include check header)
if(${check})
- set(_source_epilogue "${_source_epilogue}\n#include <${header}>")
+ set(_source_epilogue "${_source_epilogue}
+ #include <${header}>")
endif()
endmacro()
-set(signature_call_conv)
-if(HAVE_WINDOWS_H)
- add_header_include(HAVE_WINSOCK2_H "winsock2.h")
- add_header_include(HAVE_WINDOWS_H "windows.h")
- set(_source_epilogue
- "${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif")
- set(signature_call_conv "PASCAL")
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
+if(NOT DEFINED HAVE_STRUCT_SOCKADDR_STORAGE)
+ set(CMAKE_EXTRA_INCLUDE_FILES)
if(WIN32)
- set(CMAKE_REQUIRED_LIBRARIES ws2_32)
+ set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
+ set(CMAKE_REQUIRED_DEFINITIONS "-DWIN32_LEAN_AND_MEAN")
+ set(CMAKE_REQUIRED_LIBRARIES "ws2_32")
+ elseif(HAVE_SYS_SOCKET_H)
+ set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
endif()
-else()
+ check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
+ set(HAVE_STRUCT_SOCKADDR_STORAGE ${HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE})
+endif()
+
+if(NOT WIN32)
+ set(_source_epilogue "#undef inline")
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
+ check_c_source_compiles("${_source_epilogue}
+ int main(void)
+ {
+ int flag = MSG_NOSIGNAL;
+ (void)flag;
+ return 0;
+ }" HAVE_MSG_NOSIGNAL)
endif()
-set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
-
+set(_source_epilogue "#undef inline")
+add_header_include(HAVE_SYS_TIME_H "sys/time.h")
check_c_source_compiles("${_source_epilogue}
- int main(void) {
- int flag = MSG_NOSIGNAL;
- (void)flag;
+ #include <time.h>
+ int main(void)
+ {
+ struct timeval ts;
+ ts.tv_sec = 0;
+ ts.tv_usec = 0;
+ (void)ts;
return 0;
- }" HAVE_MSG_NOSIGNAL)
-
-if(NOT HAVE_WINDOWS_H)
- add_header_include(HAVE_SYS_TIME_H "sys/time.h")
-endif()
-check_c_source_compiles("${_source_epilogue}
-#include <time.h>
-int main(void) {
- struct timeval ts;
- ts.tv_sec = 0;
- ts.tv_usec = 0;
- (void)ts;
- return 0;
-}" HAVE_STRUCT_TIMEVAL)
-
-if(HAVE_WINDOWS_H)
- set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
-else()
- set(CMAKE_EXTRA_INCLUDE_FILES)
- if(HAVE_SYS_SOCKET_H)
- set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
- endif()
-endif()
-
-check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
-if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
- set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
-endif()
+ }" HAVE_STRUCT_TIMEVAL)
unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
-if(NOT CMAKE_CROSSCOMPILING)
- if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "iOS")
- # only try this on non-apple platforms
-
- # if not cross-compilation...
- set(CMAKE_REQUIRED_FLAGS "")
- if(HAVE_SYS_POLL_H)
- set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
- elseif(HAVE_POLL_H)
- set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
- endif()
- check_c_source_runs("
- #include <stdlib.h>
- #include <sys/time.h>
-
- #ifdef HAVE_SYS_POLL_H
- # include <sys/poll.h>
- #elif HAVE_POLL_H
- # include <poll.h>
- #endif
-
- int main(void)
- {
- if(0 != poll(0, 0, 10)) {
- return 1; /* fail */
- }
- else {
- /* detect the 10.12 poll() breakage */
- struct timeval before, after;
- int rc;
- size_t us;
-
- gettimeofday(&before, NULL);
- rc = poll(NULL, 0, 500);
- gettimeofday(&after, NULL);
-
- us = (after.tv_sec - before.tv_sec) * 1000000 +
- (after.tv_usec - before.tv_usec);
-
- if(us < 400000) {
- return 1;
- }
- }
- return 0;
+if(NOT CMAKE_CROSSCOMPILING AND NOT APPLE)
+ set(_source_epilogue "#undef inline")
+ add_header_include(HAVE_SYS_POLL_H "sys/poll.h")
+ add_header_include(HAVE_POLL_H "poll.h")
+ check_c_source_runs("${_source_epilogue}
+ #include <stdlib.h>
+ #include <sys/time.h>
+ int main(void)
+ {
+ if(0 != poll(0, 0, 10)) {
+ return 1; /* fail */
+ }
+ else {
+ /* detect the 10.12 poll() breakage */
+ struct timeval before, after;
+ int rc;
+ size_t us;
+
+ gettimeofday(&before, NULL);
+ rc = poll(NULL, 0, 500);
+ gettimeofday(&after, NULL);
+
+ us = (after.tv_sec - before.tv_sec) * 1000000 +
+ (after.tv_usec - before.tv_usec);
+
+ if(us < 400000) {
+ return 1;
+ }
+ }
+ return 0;
}" HAVE_POLL_FINE)
- endif()
endif()
# Detect HAVE_GETADDRINFO_THREADSAFE
@@ -140,8 +114,8 @@ if(WIN32)
set(HAVE_GETADDRINFO_THREADSAFE ${HAVE_GETADDRINFO})
elseif(NOT HAVE_GETADDRINFO)
set(HAVE_GETADDRINFO_THREADSAFE FALSE)
-elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
- CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
+elseif(APPLE OR
+ CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
CMAKE_SYSTEM_NAME STREQUAL "HP-UX" OR
CMAKE_SYSTEM_NAME STREQUAL "MidnightBSD" OR
@@ -153,14 +127,10 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "BSD")
endif()
if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE)
-
- set(_save_epilogue "${_source_epilogue}")
set(_source_epilogue "#undef inline")
-
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
add_header_include(HAVE_NETDB_H "netdb.h")
-
check_c_source_compiles("${_source_epilogue}
int main(void)
{
@@ -172,7 +142,7 @@ if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE)
}" HAVE_H_ERRNO)
if(NOT HAVE_H_ERRNO)
- check_c_source_runs("${_source_epilogue}
+ check_c_source_compiles("${_source_epilogue}
int main(void)
{
h_errno = 2;
@@ -197,17 +167,12 @@ if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE)
if(HAVE_H_ERRNO OR HAVE_H_ERRNO_ASSIGNABLE OR HAVE_H_ERRNO_SBS_ISSUE_7)
set(HAVE_GETADDRINFO_THREADSAFE TRUE)
endif()
-
- set(_source_epilogue "${_save_epilogue}")
endif()
-if(NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
- set(_save_epilogue "${_source_epilogue}")
+if(NOT WIN32 AND NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
set(_source_epilogue "#undef inline")
-
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
-
check_c_source_compiles("${_source_epilogue}
#include <time.h>
int main(void)
@@ -216,6 +181,4 @@ if(NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
(void)clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
return 0;
}" HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
-
- set(_source_epilogue "${_save_epilogue}")
endif()
diff --git a/CMake/PickyWarnings.cmake b/CMake/PickyWarnings.cmake
index 1310cb4fb..d82bbb1d6 100644
--- a/CMake/PickyWarnings.cmake
+++ b/CMake/PickyWarnings.cmake
@@ -23,6 +23,12 @@
###########################################################################
include(CheckCCompilerFlag)
+unset(WPICKY)
+
+if(CURL_WERROR AND CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
+ set(WPICKY "${WPICKY} -pedantic-errors")
+endif()
+
if(PICKY_COMPILER)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
@@ -52,8 +58,8 @@ if(PICKY_COMPILER)
# Assume these options always exist with both clang and gcc.
# Require clang 3.0 / gcc 2.95 or later.
list(APPEND WPICKY_ENABLE
- -Wbad-function-cast # clang 3.0 gcc 2.95
- -Wconversion # clang 3.0 gcc 2.95
+ -Wbad-function-cast # clang 2.7 gcc 2.95
+ -Wconversion # clang 2.7 gcc 2.95
-Winline # clang 1.0 gcc 1.0
-Wmissing-declarations # clang 1.0 gcc 2.7
-Wmissing-prototypes # clang 1.0 gcc 1.0
@@ -70,23 +76,38 @@ if(PICKY_COMPILER)
# Always enable with clang, version dependent with gcc
set(WPICKY_COMMON_OLD
+ -Waddress # clang 2.7 gcc 4.3
+ -Wattributes # clang 2.7 gcc 4.1
-Wcast-align # clang 1.0 gcc 4.2
-Wdeclaration-after-statement # clang 1.0 gcc 3.4
- -Wempty-body # clang 3.0 gcc 4.3
+ -Wdiv-by-zero # clang 2.7 gcc 4.1
+ -Wempty-body # clang 2.7 gcc 4.3
-Wendif-labels # clang 1.0 gcc 3.3
-Wfloat-equal # clang 1.0 gcc 2.96 (3.0)
- -Wignored-qualifiers # clang 3.0 gcc 4.3
+ -Wformat-security # clang 2.7 gcc 4.1
+ -Wignored-qualifiers # clang 2.8 gcc 4.3
+ -Wmissing-field-initializers # clang 2.7 gcc 4.1
+ -Wmissing-noreturn # clang 2.7 gcc 4.1
-Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0)
- -Wno-sign-conversion # clang 3.0 gcc 4.3
-Wno-system-headers # clang 1.0 gcc 3.0
+ # -Wpadded # clang 2.9 gcc 4.1 # Not used because we cannot change public structs
+ -Wold-style-definition # clang 2.7 gcc 3.4
+ -Wredundant-decls # clang 2.7 gcc 4.1
+ -Wsign-conversion # clang 2.9 gcc 4.3
+ -Wno-error=sign-conversion # FIXME
-Wstrict-prototypes # clang 1.0 gcc 3.3
- -Wtype-limits # clang 3.0 gcc 4.3
+ # -Wswitch-enum # clang 2.7 gcc 4.1 # Not used because this basically disallows default case
+ -Wtype-limits # clang 2.7 gcc 4.3
+ -Wunreachable-code # clang 2.7 gcc 4.1
+ # -Wunused-macros # clang 2.7 gcc 4.1 # Not practical
+ -Wunused-parameter # clang 2.7 gcc 4.1
-Wvla # clang 2.8 gcc 4.3
)
set(WPICKY_COMMON
-Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3
-Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0
+ -Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
-Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1
)
@@ -95,12 +116,17 @@ if(PICKY_COMPILER)
${WPICKY_COMMON_OLD}
-Wshift-sign-overflow # clang 2.9
-Wshorten-64-to-32 # clang 1.0
+ -Wlanguage-extension-token # clang 3.0
+ -Wformat=2 # clang 3.0 gcc 4.8
)
# Enable based on compiler version
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
list(APPEND WPICKY_ENABLE
${WPICKY_COMMON}
+ -Wunreachable-code-break # clang 3.5 appleclang 6.0
+ -Wheader-guard # clang 3.4 appleclang 5.1
+ -Wsometimes-uninitialized # clang 3.2 appleclang 4.6
)
endif()
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR
@@ -117,6 +143,12 @@ if(PICKY_COMPILER)
-Wextra-semi-stmt # clang 7.0 appleclang 10.3
)
endif()
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.4))
+ list(APPEND WPICKY_ENABLE
+ -Wimplicit-fallthrough # clang 4.0 gcc 7.0 appleclang 12.4 # we have silencing markup for clang 10.0 and above only
+ )
+ endif()
else() # gcc
list(APPEND WPICKY_DETECT
${WPICKY_COMMON}
@@ -125,9 +157,11 @@ if(PICKY_COMPILER)
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3)
list(APPEND WPICKY_ENABLE
${WPICKY_COMMON_OLD}
+ -Wclobbered # gcc 4.3
-Wmissing-parameter-type # gcc 4.3
-Wold-style-declaration # gcc 4.3
-Wstrict-aliasing=3 # gcc 4.0
+ -Wtrampolines # gcc 4.3
)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5 AND MINGW)
@@ -137,7 +171,7 @@ if(PICKY_COMPILER)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8)
list(APPEND WPICKY_ENABLE
- -Wformat=2 # clang 3.0 gcc 4.8 (clang part-default, enabling it fully causes -Wformat-nonliteral warnings)
+ -Wformat=2 # clang 3.0 gcc 4.8
)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
@@ -159,7 +193,8 @@ if(PICKY_COMPILER)
-Walloc-zero # gcc 7.0
-Wduplicated-branches # gcc 7.0
-Wformat-overflow=2 # gcc 7.0
- -Wformat-truncation=1 # gcc 7.0
+ -Wformat-truncation=2 # gcc 7.0
+ -Wimplicit-fallthrough # clang 4.0 gcc 7.0
-Wrestrict # gcc 7.0
)
endif()
@@ -172,13 +207,11 @@ if(PICKY_COMPILER)
#
- unset(WPICKY)
-
- foreach(_CCOPT ${WPICKY_ENABLE})
+ foreach(_CCOPT IN LISTS WPICKY_ENABLE)
set(WPICKY "${WPICKY} ${_CCOPT}")
endforeach()
- foreach(_CCOPT ${WPICKY_DETECT})
+ foreach(_CCOPT IN LISTS WPICKY_DETECT)
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
# test result in.
string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
@@ -190,8 +223,10 @@ if(PICKY_COMPILER)
set(WPICKY "${WPICKY} ${_CCOPT}")
endif()
endforeach()
-
- message(STATUS "Picky compiler options:${WPICKY}")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WPICKY}")
endif()
endif()
+
+if(WPICKY)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WPICKY}")
+ message(STATUS "Picky compiler options:${WPICKY}")
+endif()
diff --git a/CMake/Platforms/WindowsCache.cmake b/CMake/Platforms/WindowsCache.cmake
index 5daec0e1e..d3391d92f 100644
--- a/CMake/Platforms/WindowsCache.cmake
+++ b/CMake/Platforms/WindowsCache.cmake
@@ -21,113 +21,168 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-if(NOT UNIX)
- if(WIN32)
+if(NOT WIN32)
+ message(FATAL_ERROR "This file should be included on Windows platform only")
+endif()
- set(HAVE_WINDOWS_H 1)
- set(HAVE_WS2TCPIP_H 1)
- set(HAVE_WINSOCK2_H 1)
+set(HAVE_LOCALE_H 1)
- if(MINGW)
- set(HAVE_SNPRINTF 1)
- set(HAVE_UNISTD_H 1)
- set(HAVE_INTTYPES_H 1)
+if(MINGW)
+ set(HAVE_SNPRINTF 1)
+ set(HAVE_UNISTD_H 1)
+ set(HAVE_LIBGEN_H 1)
+ set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
+ set(HAVE_STDBOOL_H 1)
+ set(HAVE_BOOL_T "${HAVE_STDBOOL_H}")
+ set(HAVE_STRTOLL 1)
+ set(HAVE_BASENAME 1)
+ set(HAVE_STRCASECMP 1)
+ set(HAVE_FTRUNCATE 1)
+ set(HAVE_SYS_PARAM_H 1)
+ set(HAVE_SYS_TIME_H 1)
+ set(HAVE_GETTIMEOFDAY 1)
+else()
+ set(HAVE_LIBGEN_H 0)
+ set(HAVE_STRCASECMP 0)
+ set(HAVE_FTRUNCATE 0)
+ set(HAVE_SYS_PARAM_H 0)
+ set(HAVE_SYS_TIME_H 0)
+ set(HAVE_GETTIMEOFDAY 0)
+ if(MSVC)
+ set(HAVE_UNISTD_H 0)
+ set(HAVE_LOCALE_H 1)
+ set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
+ set(HAVE_STDATOMIC_H 0)
+ if(NOT MSVC_VERSION LESS 1800)
+ set(HAVE_STDBOOL_H 1)
set(HAVE_STRTOLL 1)
- set(HAVE_BASENAME 1)
- elseif(MSVC)
- if(NOT MSVC_VERSION LESS 1800)
- set(HAVE_INTTYPES_H 1)
- set(HAVE_STRTOLL 1)
- else()
- set(HAVE_INTTYPES_H 0)
- set(HAVE_STRTOLL 0)
- endif()
- if(NOT MSVC_VERSION LESS 1900)
- set(HAVE_SNPRINTF 1)
- else()
- set(HAVE_SNPRINTF 0)
- endif()
- set(HAVE_BASENAME 0)
+ else()
+ set(HAVE_STDBOOL_H 0)
+ set(HAVE_STRTOLL 0)
endif()
+ set(HAVE_BOOL_T "${HAVE_STDBOOL_H}")
+ if(NOT MSVC_VERSION LESS 1900)
+ set(HAVE_SNPRINTF 1)
+ else()
+ set(HAVE_SNPRINTF 0)
+ endif()
+ set(HAVE_BASENAME 0)
+ set(HAVE_STRTOK_R 0)
+ set(HAVE_FILE_OFFSET_BITS 0)
+ set(HAVE_ATOMIC 0)
+ endif()
+endif()
- set(HAVE_LIBSOCKET 0)
- set(HAVE_GETHOSTNAME 1)
- set(HAVE_LIBZ 0)
+# Available in Windows XP and newer
+set(HAVE_GETADDRINFO 1)
+set(HAVE_FREEADDRINFO 1)
- set(HAVE_ARC4RANDOM 0)
- set(HAVE_FNMATCH 0)
- set(HAVE_SCHED_YIELD 0)
- set(HAVE_ARPA_INET_H 0)
- set(HAVE_FCNTL_H 1)
- set(HAVE_IFADDRS_H 0)
- set(HAVE_IO_H 1)
- set(HAVE_NETDB_H 0)
- set(HAVE_NETINET_IN_H 0)
- set(HAVE_NETINET_TCP_H 0)
- set(HAVE_NETINET_UDP_H 0)
- set(HAVE_NET_IF_H 0)
- set(HAVE_IOCTL_SIOCGIFADDR 0)
- set(HAVE_POLL_H 0)
- set(HAVE_POLL_FINE 0)
- set(HAVE_PWD_H 0)
- set(HAVE_STRINGS_H 0)
- set(HAVE_SYS_FILIO_H 0)
- set(HAVE_SYS_WAIT_H 0)
- set(HAVE_SYS_IOCTL_H 0)
- set(HAVE_SYS_PARAM_H 0)
- set(HAVE_SYS_POLL_H 0)
- set(HAVE_SYS_RESOURCE_H 0)
- set(HAVE_SYS_SELECT_H 0)
- set(HAVE_SYS_SOCKET_H 0)
- set(HAVE_SYS_SOCKIO_H 0)
- set(HAVE_SYS_STAT_H 1)
- set(HAVE_SYS_TIME_H 0)
- set(HAVE_SYS_TYPES_H 1)
- set(HAVE_SYS_UN_H 0)
- set(HAVE_SYS_UTIME_H 1)
- set(HAVE_TERMIOS_H 0)
- set(HAVE_TERMIO_H 0)
- set(HAVE_UTIME_H 0)
+set(HAVE_FCHMOD 0)
+set(HAVE_SOCKETPAIR 0)
+set(HAVE_SENDMSG 0)
+set(HAVE_ALARM 0)
+set(HAVE_FCNTL 0)
+set(HAVE_GETPPID 0)
+set(HAVE_UTIMES 0)
+set(HAVE_GETPWUID_R 0)
+set(HAVE_STRERROR_R 0)
+set(HAVE_SIGINTERRUPT 0)
+set(HAVE_PIPE 0)
+set(HAVE_IF_NAMETOINDEX 0)
+set(HAVE_GETRLIMIT 0)
+set(HAVE_SETRLIMIT 0)
+set(HAVE_FSETXATTR 0)
+set(HAVE_LIBSOCKET 0)
+set(HAVE_SETLOCALE 1)
+set(HAVE_SETMODE 1)
+set(HAVE_GETPEERNAME 1)
+set(HAVE_GETSOCKNAME 1)
+set(HAVE_GETHOSTNAME 1)
+set(HAVE_LIBZ 0)
- set(HAVE_FSEEKO 0)
- set(HAVE__FSEEKI64 1)
- set(HAVE_SOCKET 1)
- set(HAVE_SELECT 1)
- set(HAVE_STRDUP 1)
- set(HAVE_STRICMP 1)
- set(HAVE_STRCMPI 1)
- set(HAVE_MEMRCHR 0)
- set(HAVE_GETTIMEOFDAY 0)
- set(HAVE_CLOSESOCKET 1)
- set(HAVE_SIGSETJMP 0)
- set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
- set(HAVE_GETPASS_R 0)
- set(HAVE_GETPWUID 0)
- set(HAVE_GETEUID 0)
- set(HAVE_UTIME 1)
- set(HAVE_GMTIME_R 0)
- set(HAVE_CLOCK_GETTIME_MONOTONIC_RAW 0)
- set(HAVE_GETHOSTBYNAME_R 0)
- set(HAVE_SIGNAL 1)
- set(HAVE_LINUX_TCP_H 0)
- set(HAVE_GLIBC_STRERROR_R 0)
- set(HAVE_MACH_ABSOLUTE_TIME 0)
- set(HAVE_GETIFADDRS 0)
+set(HAVE_RECV 1)
+set(HAVE_SEND 1)
+set(HAVE_STROPTS_H 0)
+set(HAVE_SYS_XATTR_H 0)
+set(HAVE_ARC4RANDOM 0)
+set(HAVE_FNMATCH 0)
+set(HAVE_SCHED_YIELD 0)
+set(HAVE_ARPA_INET_H 0)
+set(HAVE_FCNTL_H 1)
+set(HAVE_IFADDRS_H 0)
+set(HAVE_IO_H 1)
+set(HAVE_NETDB_H 0)
+set(HAVE_NETINET_IN_H 0)
+set(HAVE_NETINET_TCP_H 0)
+set(HAVE_NETINET_UDP_H 0)
+set(HAVE_NET_IF_H 0)
+set(HAVE_IOCTL_SIOCGIFADDR 0)
+set(HAVE_POLL_H 0)
+set(HAVE_POLL_FINE 0)
+set(HAVE_PWD_H 0)
+set(HAVE_STRINGS_H 0) # mingw-w64 has it (wrapper to string.h)
+set(HAVE_SYS_FILIO_H 0)
+set(HAVE_SYS_WAIT_H 0)
+set(HAVE_SYS_IOCTL_H 0)
+set(HAVE_SYS_POLL_H 0)
+set(HAVE_SYS_RESOURCE_H 0)
+set(HAVE_SYS_SELECT_H 0)
+set(HAVE_SYS_SOCKET_H 0)
+set(HAVE_SYS_SOCKIO_H 0)
+set(HAVE_SYS_STAT_H 1)
+set(HAVE_SYS_TYPES_H 1)
+set(HAVE_SYS_UN_H 0)
+set(HAVE_SYS_UTIME_H 1)
+set(HAVE_TERMIOS_H 0)
+set(HAVE_TERMIO_H 0)
+set(HAVE_UTIME_H 0) # mingw-w64 has it (wrapper to sys/utime.h)
- set(HAVE_GETHOSTBYNAME_R_3 0)
- set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
- set(HAVE_GETHOSTBYNAME_R_5 0)
- set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0)
- set(HAVE_GETHOSTBYNAME_R_6 0)
- set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
+set(HAVE_FSEEKO 0)
+set(HAVE__FSEEKI64 1)
+set(HAVE_SOCKET 1)
+set(HAVE_SELECT 1)
+set(HAVE_STRDUP 1)
+set(HAVE_STRICMP 1)
+set(HAVE_STRCMPI 1)
+set(HAVE_MEMRCHR 0)
+set(HAVE_CLOSESOCKET 1)
+set(HAVE_SIGSETJMP 0)
+set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
+set(HAVE_GETPASS_R 0)
+set(HAVE_GETPWUID 0)
+set(HAVE_GETEUID 0)
+set(HAVE_UTIME 1)
+set(HAVE_GMTIME_R 0)
+set(HAVE_GETHOSTBYNAME_R 0)
+set(HAVE_SIGNAL 1)
+set(HAVE_SIGACTION 0)
+set(HAVE_LINUX_TCP_H 0)
+set(HAVE_GLIBC_STRERROR_R 0)
+set(HAVE_MACH_ABSOLUTE_TIME 0)
+set(HAVE_GETIFADDRS 0)
+set(HAVE_FCNTL_O_NONBLOCK 0)
+set(HAVE_IOCTLSOCKET 1)
+set(HAVE_IOCTLSOCKET_CAMEL 0)
+set(HAVE_IOCTLSOCKET_CAMEL_FIONBIO 0)
+set(HAVE_IOCTLSOCKET_FIONBIO 1)
+set(HAVE_IOCTL_FIONBIO 0)
+set(HAVE_SETSOCKOPT_SO_NONBLOCK 0)
+set(HAVE_POSIX_STRERROR_R 0)
+set(HAVE_BUILTIN_AVAILABLE 0)
+set(HAVE_MSG_NOSIGNAL 0)
+set(HAVE_STRUCT_TIMEVAL 1)
+set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
- set(HAVE_O_NONBLOCK 0)
- set(HAVE_IN_ADDR_T 0)
- set(STDC_HEADERS 1)
+set(HAVE_GETHOSTBYNAME_R_3 0)
+set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
+set(HAVE_GETHOSTBYNAME_R_5 0)
+set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0)
+set(HAVE_GETHOSTBYNAME_R_6 0)
+set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
- set(HAVE_SIGACTION 0)
- set(HAVE_MACRO_SIGSETJMP 0)
- else()
- message("This file should be included on Windows platform only")
- endif()
-endif()
+set(HAVE_O_NONBLOCK 0)
+set(HAVE_IN_ADDR_T 0)
+set(STDC_HEADERS 1)
+
+set(HAVE_SIZEOF_SUSECONDS_T 0)
+set(HAVE_SIZEOF_SA_FAMILY_T 0)
diff --git a/CMake/curl-config.cmake.in b/CMake/curl-config.cmake.in
index 056907c4f..9adb96e0a 100644
--- a/CMake/curl-config.cmake.in
+++ b/CMake/curl-config.cmake.in
@@ -35,4 +35,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")
# Alias for either shared or static library
-add_library(@PROJECT_NAME@::libcurl ALIAS @PROJECT_NAME@::@LIB_SELECTED@)
+if(NOT TARGET @PROJECT_NAME@::libcurl)
+ add_library(@PROJECT_NAME@::libcurl ALIAS @PROJECT_NAME@::@LIB_SELECTED@)
+endif()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1b19c681d..1b5ea67c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,25 +21,8 @@
# SPDX-License-Identifier: curl
#
###########################################################################
-# curl/libcurl CMake script
# by Tetetest and Sukender (Benoit Neil)
-# TODO:
-# 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).
-# 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:
-# - lists of headers that 'configure' checks for;
-# - curl-specific tests (the ones that are in m4/curl-*.m4 files);
-# - (most obvious thing:) curl version numbers.
-# Add documentation subproject
-#
-# 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.
-
# Note: By default this CMake build script detects the version of some
# dependencies using `check_symbol_exists`. Those checks do not work
# in the case that both CURL and its dependency are included as
@@ -54,13 +37,13 @@
# HAVE_GNUTLS_SRP: `gnutls_srp_verifier` present in GnuTLS
# HAVE_SSL_CTX_SET_QUIC_METHOD: `SSL_CTX_set_quic_method` present in OpenSSL/wolfSSL
# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in QUICHE
-# HAVE_ZSTD_CREATEDSTREAM: `ZSTD_createDStream` present in Zstd
#
# For each of the above variables, if the variable is DEFINED (either
# to ON or OFF), the symbol detection will be skipped. If the
# variable is NOT DEFINED, the symbol detection will be performed.
cmake_minimum_required(VERSION 3.7...3.16 FATAL_ERROR)
+message(STATUS "Using CMake version ${CMAKE_VERSION}")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
@@ -105,6 +88,8 @@ option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(BUILD_STATIC_LIBS "Build static libraries" OFF)
option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
+option(CURL_DISABLE_INSTALL "Set to ON to disable installation targets" OFF)
+
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF)
@@ -220,6 +205,8 @@ option(CURL_DISABLE_GETOPTIONS "disables curl_easy_options API for existing opti
mark_as_advanced(CURL_DISABLE_GETOPTIONS)
option(CURL_DISABLE_GOPHER "disables Gopher" OFF)
mark_as_advanced(CURL_DISABLE_GOPHER)
+option(CURL_DISABLE_HEADERS_API "disables headers-api support" OFF)
+mark_as_advanced(CURL_DISABLE_HEADERS_API)
option(CURL_DISABLE_HSTS "disables HSTS support" OFF)
mark_as_advanced(CURL_DISABLE_HSTS)
option(CURL_DISABLE_HTTP "disables HTTP" OFF)
@@ -237,6 +224,8 @@ mark_as_advanced(CURL_DISABLE_LIBCURL_OPTION)
option(CURL_DISABLE_MIME "disables MIME support" OFF)
mark_as_advanced(CURL_DISABLE_MIME)
option(CURL_DISABLE_MQTT "disables MQTT" OFF)
+mark_as_advanced(CURL_DISABLE_BINDLOCAL)
+option(CURL_DISABLE_BINDLOCAL "disables local binding support" OFF)
mark_as_advanced(CURL_DISABLE_MQTT)
option(CURL_DISABLE_NETRC "disables netrc parser" OFF)
mark_as_advanced(CURL_DISABLE_NETRC)
@@ -315,18 +304,22 @@ if(ENABLE_IPV6 AND NOT WIN32)
endif()
endif()
-if(USE_MANUAL)
- #nroff is currently only used when USE_MANUAL is set, so we can prevent the warning of no *NROFF if USE_MANUAL is OFF (or not defined), by not even looking for NROFF..
- curl_nroff_check()
-endif()
find_package(Perl)
-cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual"
- ON "NROFF_USEFUL;PERL_FOUND"
- OFF)
+option(BUILD_LIBCURL_DOCS "to build libcurl man pages" ON)
+# curl source release tarballs come with the curl man page pre-built.
+option(ENABLE_CURL_MANUAL "to build the man page for curl and enable its -M/--manual option" OFF)
-if(ENABLE_MANUAL)
- set(USE_MANUAL ON)
+if(ENABLE_CURL_MANUAL OR BUILD_LIBCURL_DOCS)
+ if(PERL_FOUND)
+ curl_nroff_check()
+ if(NROFF_USEFUL)
+ set(HAVE_MANUAL_TOOLS ON)
+ endif()
+ endif()
+ if(NOT HAVE_MANUAL_TOOLS)
+ message(WARNING "Perl not found, or nroff not useful. Will not build manuals.")
+ endif()
endif()
if(CURL_STATIC_CRT)
@@ -362,28 +355,30 @@ include(CheckCSourceCompiles)
# On windows preload settings
if(WIN32)
- list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_WINSOCKAPI_=)
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
endif()
if(ENABLE_THREADED_RESOLVER)
- find_package(Threads REQUIRED)
if(WIN32)
set(USE_THREADS_WIN32 ON)
else()
+ find_package(Threads REQUIRED)
set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT})
set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT})
+ set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
- set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
endif()
# Check for all needed libraries
-check_library_exists_concat("socket" connect HAVE_LIBSOCKET)
+check_library_exists("socket" "connect" "" HAVE_LIBSOCKET)
+if(HAVE_LIBSOCKET)
+ set(CURL_LIBS "socket;${CURL_LIBS}")
+endif()
check_function_exists(gethostname HAVE_GETHOSTNAME)
if(WIN32)
- list(APPEND CURL_LIBS "ws2_32")
+ list(APPEND CURL_LIBS "ws2_32" "bcrypt")
if(USE_LIBRTMP)
list(APPEND CURL_LIBS "winmm")
endif()
@@ -413,7 +408,7 @@ set(openssl_default ON)
if(WIN32 OR CURL_USE_SECTRANSP OR CURL_USE_SCHANNEL OR CURL_USE_MBEDTLS OR CURL_USE_WOLFSSL)
set(openssl_default OFF)
endif()
-cmake_dependent_option(CURL_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default} CURL_ENABLE_SSL OFF)
+cmake_dependent_option(CURL_USE_OPENSSL "Enable OpenSSL for SSL/TLS" ${openssl_default} CURL_ENABLE_SSL OFF)
option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF)
count_true(enabled_ssl_options_count
@@ -487,11 +482,6 @@ if(CURL_USE_OPENSSL)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
- if(WIN32)
- list(APPEND CURL_LIBS "ws2_32")
- list(APPEND CURL_LIBS "bcrypt") # for OpenSSL/LibreSSL
- endif()
-
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl")
set(valid_default_ssl_backend TRUE)
endif()
@@ -604,17 +594,12 @@ option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
set(HAVE_ZSTD OFF)
if(CURL_ZSTD)
find_package(Zstd REQUIRED)
- if(NOT DEFINED HAVE_ZSTD_CREATEDSTREAM)
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
- set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
- check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM)
- cmake_pop_check_state()
- endif()
- if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM)
+ if(Zstd_FOUND AND NOT Zstd_VERSION VERSION_LESS "1.0.0")
set(HAVE_ZSTD ON)
list(APPEND CURL_LIBS ${Zstd_LIBRARIES})
include_directories(${Zstd_INCLUDE_DIRS})
+ else()
+ message(WARNING "zstd v1.0.0 or newer is required, disabling zstd support.")
endif()
endif()
@@ -647,6 +632,20 @@ macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE)
cmake_pop_check_state()
endmacro()
+# Ensure that the OpenSSL fork actually supports QUIC.
+macro(openssl_check_quic)
+ if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
+ if(USE_OPENSSL)
+ openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+ elseif(USE_WOLFSSL)
+ openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+ endif()
+ endif()
+ if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
+ message(FATAL_ERROR "QUIC support is missing in OpenSSL fork. Try setting -DOPENSSL_ROOT_DIR")
+ endif()
+endmacro()
+
if(USE_OPENSSL OR USE_WOLFSSL)
if(NOT DEFINED HAVE_SSL_SET0_WBIO)
openssl_check_symbol_exists(SSL_set0_wbio "openssl/ssl.h" HAVE_SSL_SET0_WBIO)
@@ -673,18 +672,7 @@ if(USE_NGTCP2)
else()
find_package(NGTCP2 REQUIRED quictls)
endif()
-
- # Be sure that the OpenSSL/wolfSSL library actually supports QUIC.
- if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
- if(USE_OPENSSL)
- openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
- elseif(USE_WOLFSSL)
- openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
- endif()
- endif()
- if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
- message(FATAL_ERROR "QUIC support is missing in OpenSSL/LibreSSL/BoringSSL/wolfSSL. Try setting -DOPENSSL_ROOT_DIR")
- endif()
+ openssl_check_quic()
elseif(USE_GNUTLS)
find_package(NGTCP2 REQUIRED GnuTLS)
else()
@@ -706,7 +694,10 @@ if(USE_QUICHE)
message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
endif()
find_package(QUICHE REQUIRED)
- CheckQuicSupportInOpenSSL()
+ if(NOT HAVE_BORINGSSL)
+ message(FATAL_ERROR "quiche requires BoringSSL")
+ endif()
+ openssl_check_quic()
set(USE_QUICHE ON)
include_directories(${QUICHE_INCLUDE_DIRS})
list(APPEND CURL_LIBS ${QUICHE_LIBRARIES})
@@ -729,6 +720,10 @@ if(USE_MSH3)
list(APPEND CURL_LIBS ${MSH3_LIBRARIES})
endif()
+if(CURL_WITH_MULTI_SSL AND (USE_NGTCP2 OR USE_QUICHE OR USE_MSH3))
+ message(FATAL_ERROR "MultiSSL cannot be enabled with HTTP/3 and vice versa.")
+endif()
+
if(NOT CURL_DISABLE_SRP AND (HAVE_GNUTLS_SRP OR HAVE_OPENSSL_SRP))
set(USE_TLS_SRP 1)
endif()
@@ -751,8 +746,12 @@ if(NOT CURL_DISABLE_LDAP)
if(NOT USE_WIN32_LDAP)
# Check for LDAP
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
- check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP)
- check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER)
+ check_library_exists("${CMAKE_LDAP_LIB}" "ldap_init" "" HAVE_LIBLDAP)
+ if(HAVE_LIBLDAP)
+ check_library_exists("${CMAKE_LDAP_LIB};${CMAKE_LBER_LIB}" "ber_init" "" HAVE_LIBLBER)
+ else()
+ check_library_exists("${CMAKE_LBER_LIB}" "ber_init" "" HAVE_LIBLBER)
+ endif()
set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES})
set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory")
@@ -776,7 +775,7 @@ if(NOT CURL_DISABLE_LDAP)
endif()
set(NEED_LBER_H ON)
set(_HEADER_LIST)
- if(HAVE_WINDOWS_H)
+ if(WIN32)
list(APPEND _HEADER_LIST "windows.h")
endif()
if(HAVE_SYS_TYPES_H)
@@ -791,8 +790,10 @@ if(NOT CURL_DISABLE_LDAP)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DLDAP_DEPRECATED=1)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
+ set(CURL_LIBS "${CMAKE_LDAP_LIB};${CURL_LIBS}")
if(HAVE_LIBLBER)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
+ set(CURL_LIBS "${CMAKE_LBER_LIB};${CURL_LIBS}")
endif()
check_c_source_compiles("
@@ -839,7 +840,11 @@ endif()
# Check for idn2
option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
if(USE_LIBIDN2)
- check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
+ check_library_exists("idn2" "idn2_lookup_ul" "" HAVE_LIBIDN2)
+ if(HAVE_LIBIDN2)
+ set(CURL_LIBS "idn2;${CURL_LIBS}")
+ check_include_file_concat("idn2.h" HAVE_IDN2_H)
+ endif()
else()
set(HAVE_LIBIDN2 OFF)
endif()
@@ -910,10 +915,8 @@ if(CURL_USE_GSSAPI)
check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
- if(GSS_FLAVOUR STREQUAL "Heimdal")
- set(HAVE_GSSHEIMDAL ON)
- else() # MIT
- set(HAVE_GSSMIT ON)
+ if(NOT GSS_FLAVOUR STREQUAL "Heimdal")
+ # MIT
set(_INCLUDE_LIST "")
if(HAVE_GSSAPI_GSSAPI_H)
list(APPEND _INCLUDE_LIST "gssapi/gssapi.h")
@@ -1052,13 +1055,46 @@ if(CURL_CA_PATH_SET AND
endif()
# Check for header files
-if(NOT UNIX)
- check_include_file_concat("windows.h" HAVE_WINDOWS_H)
- check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
- check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H)
+if(WIN32)
+ set(CURL_INCLUDES ${CURL_INCLUDES} "winsock2.h")
+ set(CURL_INCLUDES ${CURL_INCLUDES} "ws2tcpip.h")
+ set(CURL_INCLUDES ${CURL_INCLUDES} "windows.h")
+endif()
+
+if(WIN32)
+ # detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
+ curl_internal_test(HAVE_WIN32_WINNT)
+ if(HAVE_WIN32_WINNT)
+ string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}")
+ string(REGEX REPLACE ".*_WIN32_WINNT=" "" OUTPUT "${OUTPUT}")
+ string(REGEX REPLACE "0x([0-9a-f][0-9a-f][0-9a-f])$" "0x0\\1" OUTPUT "${OUTPUT}") # pad to 4 digits
+ string(TOLOWER "${OUTPUT}" HAVE_WIN32_WINNT)
+ message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
+ endif()
+ # avoid storing HAVE_WIN32_WINNT in CMake cache
+ unset(HAVE_WIN32_WINNT CACHE)
+
+ if(HAVE_WIN32_WINNT)
+ if(HAVE_WIN32_WINNT STRLESS "0x0501")
+ # Windows XP is required for freeaddrinfo, getaddrinfo
+ message(FATAL_ERROR "Building for Windows XP or newer is required.")
+ endif()
+
+ # pre-fill detection results based on target OS version
+ if(MINGW OR MSVC)
+ if(HAVE_WIN32_WINNT STRLESS "0x0600")
+ set(HAVE_INET_NTOP 0)
+ set(HAVE_INET_PTON 0)
+ else() # Windows Vista or newer
+ set(HAVE_INET_NTOP 1)
+ set(HAVE_INET_PTON 1)
+ endif()
+ unset(HAVE_INET_NTOP CACHE)
+ unset(HAVE_INET_PTON CACHE)
+ endif()
+ endif()
endif()
-check_include_file_concat("inttypes.h" HAVE_INTTYPES_H)
check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H)
check_include_file_concat("sys/wait.h" HAVE_SYS_WAIT_H)
check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H)
@@ -1076,7 +1112,6 @@ check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H)
check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H)
check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
-check_include_file_concat("idn2.h" HAVE_IDN2_H)
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
check_include_file_concat("io.h" HAVE_IO_H)
check_include_file_concat("libgen.h" HAVE_LIBGEN_H)
@@ -1092,7 +1127,6 @@ check_include_file_concat("poll.h" HAVE_POLL_H)
check_include_file_concat("pwd.h" HAVE_PWD_H)
check_include_file_concat("stdatomic.h" HAVE_STDATOMIC_H)
check_include_file_concat("stdbool.h" HAVE_STDBOOL_H)
-check_include_file_concat("stdint.h" HAVE_STDINT_H)
check_include_file_concat("strings.h" HAVE_STRINGS_H)
check_include_file_concat("stropts.h" HAVE_STROPTS_H)
check_include_file_concat("termio.h" HAVE_TERMIO_H)
@@ -1137,7 +1171,6 @@ elseif(HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES socket)
endif()
-check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD)
check_symbol_exists(fnmatch "${CURL_INCLUDES};fnmatch.h" HAVE_FNMATCH)
check_symbol_exists(basename "${CURL_INCLUDES};string.h" HAVE_BASENAME)
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
@@ -1174,6 +1207,7 @@ check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
check_symbol_exists(signal "${CURL_INCLUDES};signal.h" HAVE_SIGNAL)
check_symbol_exists(strtoll "${CURL_INCLUDES};stdlib.h" HAVE_STRTOLL)
check_symbol_exists(strerror_r "${CURL_INCLUDES};stdlib.h;string.h" HAVE_STRERROR_R)
+check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
check_symbol_exists(siginterrupt "${CURL_INCLUDES};signal.h" HAVE_SIGINTERRUPT)
check_symbol_exists(getaddrinfo "${CURL_INCLUDES};stdlib.h;string.h" HAVE_GETADDRINFO)
check_symbol_exists(getifaddrs "${CURL_INCLUDES};stdlib.h" HAVE_GETIFADDRS)
@@ -1190,6 +1224,10 @@ check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE)
check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
+if(HAVE_FSEEKO)
+ set(HAVE_DECL_FSEEKO 1)
+endif()
+
if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900))
# earlier MSVC compilers had faulty snprintf implementations
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
@@ -1213,20 +1251,11 @@ check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T)
set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T})
set(CMAKE_EXTRA_INCLUDE_FILES "")
-set(CMAKE_EXTRA_INCLUDE_FILES "ws2def.h")
-check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
-set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
-set(CMAKE_EXTRA_INCLUDE_FILES "")
-
-# sigaction and sigsetjmp are special. Use special mechanism for
-# detecting those, but only if previous attempt failed.
-check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
-
-if(NOT HAVE_SIGSETJMP)
- check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
- if(HAVE_MACRO_SIGSETJMP)
- set(HAVE_SIGSETJMP 1)
- endif()
+if(WIN32)
+ set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
+ check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
+ set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
+ set(CMAKE_EXTRA_INCLUDE_FILES "")
endif()
# Do curl specific tests
@@ -1250,8 +1279,6 @@ foreach(CURL_TEST
HAVE_BOOL_T
STDC_HEADERS
HAVE_FILE_OFFSET_BITS
- HAVE_VARIADIC_MACROS_C99
- HAVE_VARIADIC_MACROS_GCC
HAVE_ATOMIC
)
curl_internal_test(${CURL_TEST})
@@ -1271,18 +1298,6 @@ set(CMAKE_EXTRA_INCLUDE_FILES "curl/curl.h")
check_type_size("curl_socket_t" SIZEOF_CURL_SOCKET_T)
set(CMAKE_EXTRA_INCLUDE_FILES "")
-if(WIN32)
- # detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
- curl_internal_test(HAVE_WIN32_WINNT)
- if(HAVE_WIN32_WINNT)
- string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}")
- string(REGEX REPLACE ".*_WIN32_WINNT=" "" HAVE_WIN32_WINNT "${OUTPUT}")
- message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
- endif()
- # avoid storing HAVE_WIN32_WINNT in CMake cache
- unset(HAVE_WIN32_WINNT CACHE)
-endif()
-
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
# on not-Windows and not-crosscompiling, check for writable argv[]
include(CheckCSourceRuns)
@@ -1338,8 +1353,10 @@ if(NEED_REENTRANT)
endforeach()
endif()
-# Check clock_gettime(CLOCK_MONOTONIC, x) support
-curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
+if(NOT WIN32)
+ # Check clock_gettime(CLOCK_MONOTONIC, x) support
+ curl_internal_test(HAVE_CLOCK_GETTIME_MONOTONIC)
+endif()
# Check compiler support of __builtin_available()
curl_internal_test(HAVE_BUILTIN_AVAILABLE)
@@ -1375,15 +1392,6 @@ if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
endif()
endif()
-# TODO test which of these headers are required
-if(WIN32)
- set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H})
-else()
- set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H})
- set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H})
- set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H})
-endif()
-
include(CMake/OtherTests.cmake)
add_definitions(-DHAVE_CONFIG_H)
@@ -1404,8 +1412,6 @@ if(WIN32)
if(USE_WIN32_CRYPTO OR USE_SCHANNEL)
list(APPEND CURL_LIBS "advapi32" "crypt32")
endif()
-
- list(APPEND CURL_LIBS "bcrypt")
endif()
if(MSVC)
@@ -1475,7 +1481,7 @@ set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
-if(USE_MANUAL)
+if(HAVE_MANUAL_TOOLS)
add_subdirectory(docs)
endif()
@@ -1492,258 +1498,257 @@ if(BUILD_TESTING)
add_subdirectory(tests)
endif()
-# Helper to populate a list (_items) with a label when conditions (the remaining
-# args) are satisfied
-macro(_add_if label)
- # needs to be a macro to allow this indirection
- if(${ARGN})
- set(_items ${_items} "${label}")
+if(NOT CURL_DISABLE_INSTALL)
+
+ # Helper to populate a list (_items) with a label when conditions (the remaining
+ # args) are satisfied
+ macro(_add_if label)
+ # needs to be a macro to allow this indirection
+ if(${ARGN})
+ set(_items ${_items} "${label}")
+ endif()
+ endmacro()
+
+ # NTLM support requires crypto function adaptions from various SSL libs
+ if(NOT (CURL_DISABLE_NTLM) AND
+ (USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO OR USE_GNUTLS))
+ set(use_curl_ntlm_core ON)
endif()
-endmacro()
-# NTLM support requires crypto function adaptions from various SSL libs
-# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
-if(NOT (CURL_DISABLE_NTLM) AND
- (USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO OR USE_GNUTLS))
- set(use_curl_ntlm_core ON)
-endif()
-
-# Clear list and try to detect available features
-set(_items)
-_add_if("SSL" SSL_ENABLED)
-_add_if("IPv6" ENABLE_IPV6)
-_add_if("unixsockets" USE_UNIX_SOCKETS)
-_add_if("libz" HAVE_LIBZ)
-_add_if("brotli" HAVE_BROTLI)
-_add_if("zstd" HAVE_ZSTD)
-_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
-_add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN)
-_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
- ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
-# TODO SSP1 (Schannel) check is missing
-_add_if("SSPI" USE_WINDOWS_SSPI)
-_add_if("GSS-API" HAVE_GSSAPI)
-_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
-_add_if("HSTS" NOT CURL_DISABLE_HSTS)
-# TODO SSP1 missing for SPNEGO
-_add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
- (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
-_add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND
- (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
-# NTLM support requires crypto function adaptions from various SSL libs
-# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
-_add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND
- (use_curl_ntlm_core OR USE_WINDOWS_SSPI))
-# TODO missing option (autoconf: --enable-ntlm-wb)
-_add_if("NTLM_WB" NOT (CURL_DISABLE_NTLM) AND
- (use_curl_ntlm_core OR USE_WINDOWS_SSPI) 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)
-# TODO wolfSSL only support this from v5.0.0 onwards
-_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS
- OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
- USE_MBEDTLS OR USE_SECTRANSP))
-_add_if("unicode" ENABLE_UNICODE)
-_add_if("threadsafe" HAVE_ATOMIC OR (WIN32 AND
- HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
-_add_if("PSL" USE_LIBPSL)
-string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
-message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
-
-# Clear list and try to detect available protocols
-set(_items)
-_add_if("HTTP" NOT CURL_DISABLE_HTTP)
-_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED)
-_add_if("FTP" NOT CURL_DISABLE_FTP)
-_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED)
-_add_if("FILE" NOT CURL_DISABLE_FILE)
-_add_if("TELNET" NOT CURL_DISABLE_TELNET)
-_add_if("LDAP" NOT CURL_DISABLE_LDAP)
-# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
-_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
- ((USE_OPENLDAP AND SSL_ENABLED) OR
- (NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
-_add_if("DICT" NOT CURL_DISABLE_DICT)
-_add_if("TFTP" NOT CURL_DISABLE_TFTP)
-_add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
-_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
-_add_if("POP3" NOT CURL_DISABLE_POP3)
-_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
-_add_if("IMAP" NOT CURL_DISABLE_IMAP)
-_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
-_add_if("SMB" NOT CURL_DISABLE_SMB AND
- use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
-_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND
- use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
-_add_if("SMTP" NOT CURL_DISABLE_SMTP)
-_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
-_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" NOT CURL_DISABLE_MQTT)
-_add_if("WS" USE_WEBSOCKETS)
-_add_if("WSS" USE_WEBSOCKETS)
-if(_items)
- list(SORT _items)
-endif()
-string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
-message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
-
-# Clear list and collect SSL backends
-set(_items)
-_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL)
-_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
-_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
-_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
-_add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL)
-_add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL)
-_add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS)
-
-if(_items)
- list(SORT _items)
-endif()
-string(REPLACE ";" " " SSL_BACKENDS "${_items}")
-message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
-if(CURL_DEFAULT_SSL_BACKEND)
- message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}")
-endif()
-
-# curl-config needs the following options to be set.
-set(CC "${CMAKE_C_COMPILER}")
-# TODO probably put a -D... options here?
-set(CONFIGURE_OPTIONS "")
-set(CURLVERSION "${CURL_VERSION}")
-set(exec_prefix "\${prefix}")
-set(includedir "\${prefix}/include")
-set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
-set(LIBCURL_LIBS "")
-set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
-foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
- if(TARGET "${_lib}")
- set(_libname "${_lib}")
- get_target_property(_imported "${_libname}" IMPORTED)
- if(NOT _imported)
- # Reading the LOCATION property on non-imported target will error out.
- # Assume the user won't need this information in the .pc file.
- continue()
+ # Clear list and try to detect available features
+ set(_items)
+ _add_if("SSL" SSL_ENABLED)
+ _add_if("IPv6" ENABLE_IPV6)
+ _add_if("UnixSockets" USE_UNIX_SOCKETS)
+ _add_if("libz" HAVE_LIBZ)
+ _add_if("brotli" HAVE_BROTLI)
+ _add_if("zstd" HAVE_ZSTD)
+ _add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
+ _add_if("IDN" HAVE_LIBIDN2 OR USE_WIN32_IDN)
+ _add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
+ ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
+ _add_if("SSPI" USE_WINDOWS_SSPI)
+ _add_if("GSS-API" HAVE_GSSAPI)
+ _add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
+ _add_if("HSTS" NOT CURL_DISABLE_HSTS)
+ _add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
+ (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
+ _add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND
+ (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
+ _add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND
+ (use_curl_ntlm_core OR USE_WINDOWS_SSPI))
+ _add_if("NTLM_WB" NOT (CURL_DISABLE_NTLM) AND
+ (use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND
+ NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
+ _add_if("TLS-SRP" USE_TLS_SRP)
+ _add_if("HTTP2" USE_NGHTTP2)
+ _add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
+ _add_if("MultiSSL" CURL_WITH_MULTI_SSL)
+ # TODO wolfSSL only support this from v5.0.0 onwards
+ _add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS
+ OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
+ USE_MBEDTLS OR USE_SECTRANSP))
+ _add_if("unicode" ENABLE_UNICODE)
+ _add_if("threadsafe" HAVE_ATOMIC OR
+ (USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR
+ (WIN32 AND HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
+ _add_if("PSL" USE_LIBPSL)
+ string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
+ message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
+
+ # Clear list and try to detect available protocols
+ set(_items)
+ _add_if("HTTP" NOT CURL_DISABLE_HTTP)
+ _add_if("IPFS" NOT CURL_DISABLE_HTTP)
+ _add_if("IPNS" NOT CURL_DISABLE_HTTP)
+ _add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED)
+ _add_if("FTP" NOT CURL_DISABLE_FTP)
+ _add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED)
+ _add_if("FILE" NOT CURL_DISABLE_FILE)
+ _add_if("TELNET" NOT CURL_DISABLE_TELNET)
+ _add_if("LDAP" NOT CURL_DISABLE_LDAP)
+ # CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
+ _add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
+ ((USE_OPENLDAP AND SSL_ENABLED) OR
+ (NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
+ _add_if("DICT" NOT CURL_DISABLE_DICT)
+ _add_if("TFTP" NOT CURL_DISABLE_TFTP)
+ _add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
+ _add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
+ _add_if("POP3" NOT CURL_DISABLE_POP3)
+ _add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
+ _add_if("IMAP" NOT CURL_DISABLE_IMAP)
+ _add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
+ _add_if("SMB" NOT CURL_DISABLE_SMB AND
+ use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
+ _add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND
+ use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
+ _add_if("SMTP" NOT CURL_DISABLE_SMTP)
+ _add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
+ _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" NOT CURL_DISABLE_MQTT)
+ _add_if("WS" USE_WEBSOCKETS)
+ _add_if("WSS" USE_WEBSOCKETS)
+ if(_items)
+ list(SORT _items)
+ endif()
+ string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
+ message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
+
+ # Clear list and collect SSL backends
+ set(_items)
+ _add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL)
+ _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
+ _add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
+ _add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
+ _add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL)
+ _add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL)
+ _add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS)
+
+ if(_items)
+ list(SORT _items)
+ endif()
+ string(REPLACE ";" " " SSL_BACKENDS "${_items}")
+ message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
+ if(CURL_DEFAULT_SSL_BACKEND)
+ message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}")
+ endif()
+
+ # curl-config needs the following options to be set.
+ set(CC "${CMAKE_C_COMPILER}")
+ # TODO probably put a -D... options here?
+ set(CONFIGURE_OPTIONS "")
+ set(CURLVERSION "${CURL_VERSION}")
+ set(exec_prefix "\${prefix}")
+ set(includedir "\${prefix}/include")
+ set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+ set(LIBCURL_LIBS "")
+ set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
+ foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
+ if(TARGET "${_lib}")
+ set(_libname "${_lib}")
+ get_target_property(_imported "${_libname}" IMPORTED)
+ if(NOT _imported)
+ # Reading the LOCATION property on non-imported target 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()
- get_target_property(_lib "${_libname}" LOCATION)
- if(NOT _lib)
- message(WARNING "Bad lib in library list: ${_libname}")
- continue()
+ if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
+ set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
+ else()
+ set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
endif()
+ endforeach()
+ if(BUILD_SHARED_LIBS)
+ set(ENABLE_SHARED "yes")
+ set(LIBCURL_NO_SHARED "")
+ set(CPPFLAG_CURL_STATICLIB "")
+ else()
+ set(ENABLE_SHARED "no")
+ set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
+ set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB")
endif()
- if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
- set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
+ if(BUILD_STATIC_LIBS)
+ set(ENABLE_STATIC "yes")
else()
- set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
+ set(ENABLE_STATIC "no")
endif()
-endforeach()
-if(BUILD_SHARED_LIBS)
- set(ENABLE_SHARED "yes")
- set(LIBCURL_NO_SHARED "")
- set(CPPFLAG_CURL_STATICLIB "")
-else()
- set(ENABLE_SHARED "no")
- set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
- set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB")
-endif()
-if(BUILD_STATIC_LIBS)
- set(ENABLE_STATIC "yes")
-else()
- set(ENABLE_STATIC "no")
-endif()
-# "a" (Linux) or "lib" (Windows)
-string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
-set(prefix "${CMAKE_INSTALL_PREFIX}")
-# Set this to "yes" to append all libraries on which -lcurl is dependent
-set(REQUIRE_LIB_DEPS "no")
-# SUPPORT_FEATURES
-# SUPPORT_PROTOCOLS
-set(VERSIONNUM "${CURL_VERSION_NUM}")
-
-# Finally generate a "curl-config" matching this config
-# Use:
-# * ENABLE_SHARED
-# * ENABLE_STATIC
-configure_file("${CURL_SOURCE_DIR}/curl-config.in"
- "${CURL_BINARY_DIR}/curl-config" @ONLY)
-install(FILES "${CURL_BINARY_DIR}/curl-config"
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- PERMISSIONS
- OWNER_READ OWNER_WRITE OWNER_EXECUTE
- GROUP_READ GROUP_EXECUTE
- WORLD_READ WORLD_EXECUTE)
-
-# Finally generate a pkg-config file matching this config
-configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
- "${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
-install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
- DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
-
-# install headers
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
- FILES_MATCHING PATTERN "*.h")
-
-include(CMakePackageConfigHelpers)
-write_basic_package_version_file(
- "${version_config}"
- VERSION ${CURL_VERSION}
- COMPATIBILITY SameMajorVersion
-)
-file(READ "${version_config}" generated_version_config)
-file(WRITE "${version_config}"
-"if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\")
- # Version 8 satisfies version 7... requirements
- set(PACKAGE_FIND_VERSION_MAJOR 8)
- set(PACKAGE_FIND_VERSION_COUNT 1)
-endif()
-${generated_version_config}"
-)
+ # "a" (Linux) or "lib" (Windows)
+ string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
+ set(prefix "${CMAKE_INSTALL_PREFIX}")
+ # Set this to "yes" to append all libraries on which -lcurl is dependent
+ set(REQUIRE_LIB_DEPS "no")
+ # SUPPORT_FEATURES
+ # SUPPORT_PROTOCOLS
+ set(VERSIONNUM "${CURL_VERSION_NUM}")
+
+ # Finally generate a "curl-config" matching this config
+ # Use:
+ # * ENABLE_SHARED
+ # * ENABLE_STATIC
+ configure_file("${CURL_SOURCE_DIR}/curl-config.in"
+ "${CURL_BINARY_DIR}/curl-config" @ONLY)
+ install(FILES "${CURL_BINARY_DIR}/curl-config"
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
+ PERMISSIONS
+ OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+
+ # Finally generate a pkg-config file matching this config
+ configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
+ "${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
+ install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+
+ # install headers
+ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ FILES_MATCHING PATTERN "*.h")
+
+ include(CMakePackageConfigHelpers)
+ write_basic_package_version_file(
+ "${version_config}"
+ VERSION ${CURL_VERSION}
+ COMPATIBILITY SameMajorVersion
+ )
+ file(READ "${version_config}" generated_version_config)
+ file(WRITE "${version_config}"
+ "if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\")
+ # Version 8 satisfies version 7... requirements
+ set(PACKAGE_FIND_VERSION_MAJOR 8)
+ set(PACKAGE_FIND_VERSION_COUNT 1)
+ endif()
+ ${generated_version_config}"
+ )
-# Use:
-# * TARGETS_EXPORT_NAME
-# * PROJECT_NAME
-configure_package_config_file(CMake/curl-config.cmake.in
- "${project_config}"
- INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
-)
+ # Use:
+ # * TARGETS_EXPORT_NAME
+ # * PROJECT_NAME
+ configure_package_config_file(CMake/curl-config.cmake.in
+ "${project_config}"
+ INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
+ )
+
+ if(CURL_ENABLE_EXPORT_TARGET)
+ install(
+ EXPORT "${TARGETS_EXPORT_NAME}"
+ NAMESPACE "${PROJECT_NAME}::"
+ DESTINATION ${CURL_INSTALL_CMAKE_DIR}
+ )
+ endif()
-if(CURL_ENABLE_EXPORT_TARGET)
install(
- EXPORT "${TARGETS_EXPORT_NAME}"
- NAMESPACE "${PROJECT_NAME}::"
+ FILES ${version_config} ${project_config}
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
)
-endif()
-
-install(
- FILES ${version_config} ${project_config}
- DESTINATION ${CURL_INSTALL_CMAKE_DIR}
-)
-# Workaround for MSVS10 to avoid the Dialog Hell
-# FIXME: This could be removed with future version of CMake.
-if(MSVC_VERSION EQUAL 1600)
- set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
- if(EXISTS "${CURL_SLN_FILENAME}")
- file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n")
+ # Workaround for MSVS10 to avoid the Dialog Hell
+ # FIXME: This could be removed with future version of CMake.
+ if(MSVC_VERSION EQUAL 1600)
+ set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
+ if(EXISTS "${CURL_SLN_FILENAME}")
+ file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n")
+ endif()
endif()
-endif()
-if(NOT TARGET curl_uninstall)
- configure_file(
- ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
- ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
- IMMEDIATE @ONLY)
+ if(NOT TARGET curl_uninstall)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
+ IMMEDIATE @ONLY)
- add_custom_target(curl_uninstall
- COMMAND ${CMAKE_COMMAND} -P
- ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
+ add_custom_target(curl_uninstall
+ COMMAND ${CMAKE_COMMAND} -P
+ ${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
+ endif()
endif()
diff --git a/COPYING b/COPYING
index d1eab3eb9..d9e7e0bef 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE
-Copyright (c) 1996 - 2023, Daniel Stenberg, <daniel@haxx.se>, and many
+Copyright (c) 1996 - 2024, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.
diff --git a/METADATA b/METADATA
index 1402d4921..2a72692f3 100644
--- a/METADATA
+++ b/METADATA
@@ -1,26 +1,23 @@
# This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update curl
+# Usage: tools/external_updater/updater.sh update external/curl
# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
name: "curl"
description: "A command line tool and library for transferring data with URLs."
third_party {
- url {
- type: HOMEPAGE
- value: "https://curl.haxx.se/"
- }
- url {
- type: GIT
- value: "https://github.com/curl/curl/"
- }
- version: "curl-8_4_0"
license_type: NOTICE
security {
tag: "NVD-CPE2.3:cpe:/a:haxx:curl:7.87.0"
}
last_upgrade_date {
- year: 2023
- month: 10
- day: 11
+ year: 2024
+ month: 2
+ day: 20
+ }
+ homepage: "https://curl.haxx.se/"
+ identifier {
+ type: "Git"
+ value: "https://github.com/curl/curl/"
+ version: "curl-8_6_0"
}
}
diff --git a/Makefile.am b/Makefile.am
index 6c780a849..b56ca1a1e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,27 +53,6 @@ CMAKE_DIST = \
CMake/Utilities.cmake \
CMakeLists.txt
-VC10_LIBTMPL = projects/Windows/VC10/lib/libcurl.tmpl
-VC10_LIBVCXPROJ = projects/Windows/VC10/lib/libcurl.vcxproj.dist
-VC10_LIBVCXPROJ_DEPS = $(VC10_LIBTMPL) Makefile.am lib/Makefile.inc
-VC10_SRCTMPL = projects/Windows/VC10/src/curl.tmpl
-VC10_SRCVCXPROJ = projects/Windows/VC10/src/curl.vcxproj.dist
-VC10_SRCVCXPROJ_DEPS = $(VC10_SRCTMPL) Makefile.am src/Makefile.inc
-
-VC11_LIBTMPL = projects/Windows/VC11/lib/libcurl.tmpl
-VC11_LIBVCXPROJ = projects/Windows/VC11/lib/libcurl.vcxproj.dist
-VC11_LIBVCXPROJ_DEPS = $(VC11_LIBTMPL) Makefile.am lib/Makefile.inc
-VC11_SRCTMPL = projects/Windows/VC11/src/curl.tmpl
-VC11_SRCVCXPROJ = projects/Windows/VC11/src/curl.vcxproj.dist
-VC11_SRCVCXPROJ_DEPS = $(VC11_SRCTMPL) Makefile.am src/Makefile.inc
-
-VC12_LIBTMPL = projects/Windows/VC12/lib/libcurl.tmpl
-VC12_LIBVCXPROJ = projects/Windows/VC12/lib/libcurl.vcxproj.dist
-VC12_LIBVCXPROJ_DEPS = $(VC12_LIBTMPL) Makefile.am lib/Makefile.inc
-VC12_SRCTMPL = projects/Windows/VC12/src/curl.tmpl
-VC12_SRCVCXPROJ = projects/Windows/VC12/src/curl.vcxproj.dist
-VC12_SRCVCXPROJ_DEPS = $(VC12_SRCTMPL) Makefile.am src/Makefile.inc
-
VC14_LIBTMPL = projects/Windows/VC14/lib/libcurl.tmpl
VC14_LIBVCXPROJ = projects/Windows/VC14/lib/libcurl.vcxproj.dist
VC14_LIBVCXPROJ_DEPS = $(VC14_LIBTMPL) Makefile.am lib/Makefile.inc
@@ -88,6 +67,13 @@ VC14_10_SRCTMPL = projects/Windows/VC14.10/src/curl.tmpl
VC14_10_SRCVCXPROJ = projects/Windows/VC14.10/src/curl.vcxproj.dist
VC14_10_SRCVCXPROJ_DEPS = $(VC14_10_SRCTMPL) Makefile.am src/Makefile.inc
+VC14_20_LIBTMPL = projects/Windows/VC14.20/lib/libcurl.tmpl
+VC14_20_LIBVCXPROJ = projects/Windows/VC14.20/lib/libcurl.vcxproj.dist
+VC14_20_LIBVCXPROJ_DEPS = $(VC14_20_LIBTMPL) Makefile.am lib/Makefile.inc
+VC14_20_SRCTMPL = projects/Windows/VC14.20/src/curl.tmpl
+VC14_20_SRCVCXPROJ = projects/Windows/VC14.20/src/curl.vcxproj.dist
+VC14_20_SRCVCXPROJ_DEPS = $(VC14_20_SRCTMPL) Makefile.am src/Makefile.inc
+
VC14_30_LIBTMPL = projects/Windows/VC14.30/lib/libcurl.tmpl
VC14_30_LIBVCXPROJ = projects/Windows/VC14.30/lib/libcurl.vcxproj.dist
VC14_30_LIBVCXPROJ_DEPS = $(VC14_30_LIBTMPL) Makefile.am lib/Makefile.inc
@@ -99,21 +85,6 @@ VC_DIST = projects/README.md \
projects/build-openssl.bat \
projects/build-wolfssl.bat \
projects/checksrc.bat \
- projects/Windows/VC10/curl-all.sln \
- projects/Windows/VC10/lib/libcurl.sln \
- projects/Windows/VC10/lib/libcurl.vcxproj.filters \
- projects/Windows/VC10/src/curl.sln \
- projects/Windows/VC10/src/curl.vcxproj.filters \
- projects/Windows/VC11/curl-all.sln \
- projects/Windows/VC11/lib/libcurl.sln \
- projects/Windows/VC11/lib/libcurl.vcxproj.filters \
- projects/Windows/VC11/src/curl.sln \
- projects/Windows/VC11/src/curl.vcxproj.filters \
- projects/Windows/VC12/curl-all.sln \
- projects/Windows/VC12/lib/libcurl.sln \
- projects/Windows/VC12/lib/libcurl.vcxproj.filters \
- projects/Windows/VC12/src/curl.sln \
- projects/Windows/VC12/src/curl.vcxproj.filters \
projects/Windows/VC14/curl-all.sln \
projects/Windows/VC14/lib/libcurl.sln \
projects/Windows/VC14/lib/libcurl.vcxproj.filters \
@@ -124,6 +95,11 @@ VC_DIST = projects/README.md \
projects/Windows/VC14.10/lib/libcurl.vcxproj.filters \
projects/Windows/VC14.10/src/curl.sln \
projects/Windows/VC14.10/src/curl.vcxproj.filters \
+ projects/Windows/VC14.20/curl-all.sln \
+ projects/Windows/VC14.20/lib/libcurl.sln \
+ projects/Windows/VC14.20/lib/libcurl.vcxproj.filters \
+ projects/Windows/VC14.20/src/curl.sln \
+ projects/Windows/VC14.20/src/curl.vcxproj.filters \
projects/Windows/VC14.30/curl-all.sln \
projects/Windows/VC14.30/lib/libcurl.sln \
projects/Windows/VC14.30/lib/libcurl.vcxproj.filters \
@@ -151,9 +127,9 @@ EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \
$(VC_DIST) $(WINBUILD_DIST) $(PLAN9_DIST) lib/libcurl.vers.in buildconf.bat \
libcurl.def
-CLEANFILES = $(VC10_LIBVCXPROJ) $(VC10_SRCVCXPROJ) $(VC11_LIBVCXPROJ) \
- $(VC11_SRCVCXPROJ) $(VC12_LIBVCXPROJ) $(VC12_SRCVCXPROJ) $(VC14_LIBVCXPROJ) \
- $(VC14_SRCVCXPROJ) $(VC14_10_LIBVCXPROJ) $(VC14_10_SRCVCXPROJ) \
+CLEANFILES = $(VC14_LIBVCXPROJ) $(VC14_SRCVCXPROJ) \
+ $(VC14_10_LIBVCXPROJ) $(VC14_10_SRCVCXPROJ) \
+ $(VC14_20_LIBVCXPROJ) $(VC14_20_SRCVCXPROJ) \
$(VC14_30_LIBVCXPROJ) $(VC14_30_SRCVCXPROJ)
bin_SCRIPTS = curl-config
@@ -177,12 +153,6 @@ dist-hook:
cp -p $$file $(distdir)$$strip; \
done)
-html:
- cd docs && $(MAKE) html
-
-pdf:
- cd docs && $(MAKE) pdf
-
check: test examples check-docs
if CROSSCOMPILING
@@ -300,10 +270,9 @@ checksrc:
.PHONY: vc-ide
-vc-ide: $(VC10_LIBVCXPROJ_DEPS) $(VC10_SRCVCXPROJ_DEPS) \
- $(VC11_LIBVCXPROJ_DEPS) $(VC11_SRCVCXPROJ_DEPS) $(VC12_LIBVCXPROJ_DEPS) \
- $(VC12_SRCVCXPROJ_DEPS) $(VC14_LIBVCXPROJ_DEPS) $(VC14_SRCVCXPROJ_DEPS) \
- $(VC14_10_LIBVCXPROJ_DEPS) $(VC14_10_SRCVCXPROJ_DEPS) \
+vc-ide: $(VC14_LIBVCXPROJ_DEPS) $(VC14_SRCVCXPROJ_DEPS) \
+ $(VC14_10_LIBVCXPROJ_DEPS) $(VC14_10_SRCVCXPROJ_DEPS) \
+ $(VC14_20_LIBVCXPROJ_DEPS) $(VC14_20_SRCVCXPROJ_DEPS) \
$(VC14_30_LIBVCXPROJ_DEPS) $(VC14_30_SRCVCXPROJ_DEPS)
@(win32_lib_srcs='$(LIB_CFILES)'; \
win32_lib_hdrs='$(LIB_HFILES) config-win32.h'; \
@@ -465,55 +434,7 @@ function gen_element(type, dir, file)\
printf("%s\r\n", $$0);\
}';\
\
- echo "generating '$(VC10_LIBVCXPROJ)'"; \
- awk -v proj_type=vcxproj \
- -v lib_srcs="$$sorted_lib_srcs" \
- -v lib_hdrs="$$sorted_lib_hdrs" \
- -v lib_rc="$$win32_lib_rc" \
- -v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
- -v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
- -v lib_vquic_srcs="$$sorted_lib_vquic_srcs" \
- -v lib_vquic_hdrs="$$sorted_lib_vquic_hdrs" \
- -v lib_vssh_srcs="$$sorted_lib_vssh_srcs" \
- -v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \
- -v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
- -v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
- "$$awk_code" $(srcdir)/$(VC10_LIBTMPL) > $(VC10_LIBVCXPROJ) || { exit 1; }; \
- \
- echo "generating '$(VC10_SRCVCXPROJ)'"; \
- awk -v proj_type=vcxproj \
- -v src_srcs="$$sorted_src_srcs" \
- -v src_hdrs="$$sorted_src_hdrs" \
- -v src_rc="$$win32_src_rc" \
- -v src_x_srcs="$$sorted_src_x_srcs" \
- -v src_x_hdrs="$$sorted_src_x_hdrs" \
- "$$awk_code" $(srcdir)/$(VC10_SRCTMPL) > $(VC10_SRCVCXPROJ) || { exit 1; }; \
- \
- echo "generating '$(VC11_LIBVCXPROJ)'"; \
- awk -v proj_type=vcxproj \
- -v lib_srcs="$$sorted_lib_srcs" \
- -v lib_hdrs="$$sorted_lib_hdrs" \
- -v lib_rc="$$win32_lib_rc" \
- -v lib_vauth_srcs="$$sorted_lib_vauth_srcs" \
- -v lib_vauth_hdrs="$$sorted_lib_vauth_hdrs" \
- -v lib_vquic_srcs="$$sorted_lib_vquic_srcs" \
- -v lib_vquic_hdrs="$$sorted_lib_vquic_hdrs" \
- -v lib_vssh_srcs="$$sorted_lib_vssh_srcs" \
- -v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \
- -v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
- -v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
- "$$awk_code" $(srcdir)/$(VC11_LIBTMPL) > $(VC11_LIBVCXPROJ) || { exit 1; }; \
- \
- echo "generating '$(VC11_SRCVCXPROJ)'"; \
- awk -v proj_type=vcxproj \
- -v src_srcs="$$sorted_src_srcs" \
- -v src_hdrs="$$sorted_src_hdrs" \
- -v src_rc="$$win32_src_rc" \
- -v src_x_srcs="$$sorted_src_x_srcs" \
- -v src_x_hdrs="$$sorted_src_x_hdrs" \
- "$$awk_code" $(srcdir)/$(VC11_SRCTMPL) > $(VC11_SRCVCXPROJ) || { exit 1; }; \
- \
- echo "generating '$(VC12_LIBVCXPROJ)'"; \
+ echo "generating '$(VC14_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
@@ -526,18 +447,18 @@ function gen_element(type, dir, file)\
-v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
- "$$awk_code" $(srcdir)/$(VC12_LIBTMPL) > $(VC12_LIBVCXPROJ) || { exit 1; }; \
+ "$$awk_code" $(srcdir)/$(VC14_LIBTMPL) > $(VC14_LIBVCXPROJ) || { exit 1; }; \
\
- echo "generating '$(VC12_SRCVCXPROJ)'"; \
+ echo "generating '$(VC14_SRCVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
- "$$awk_code" $(srcdir)/$(VC12_SRCTMPL) > $(VC12_SRCVCXPROJ) || { exit 1; }; \
+ "$$awk_code" $(srcdir)/$(VC14_SRCTMPL) > $(VC14_SRCVCXPROJ) || { exit 1; }; \
\
- echo "generating '$(VC14_LIBVCXPROJ)'"; \
+ echo "generating '$(VC14_10_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
@@ -550,18 +471,18 @@ function gen_element(type, dir, file)\
-v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
- "$$awk_code" $(srcdir)/$(VC14_LIBTMPL) > $(VC14_LIBVCXPROJ) || { exit 1; }; \
+ "$$awk_code" $(srcdir)/$(VC14_10_LIBTMPL) > $(VC14_10_LIBVCXPROJ) || { exit 1; }; \
\
- echo "generating '$(VC14_SRCVCXPROJ)'"; \
+ echo "generating '$(VC14_10_SRCVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
- "$$awk_code" $(srcdir)/$(VC14_SRCTMPL) > $(VC14_SRCVCXPROJ) || { exit 1; }; \
+ "$$awk_code" $(srcdir)/$(VC14_10_SRCTMPL) > $(VC14_10_SRCVCXPROJ) || { exit 1; }; \
\
- echo "generating '$(VC14_10_LIBVCXPROJ)'"; \
+ echo "generating '$(VC14_20_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v lib_srcs="$$sorted_lib_srcs" \
-v lib_hdrs="$$sorted_lib_hdrs" \
@@ -574,16 +495,16 @@ function gen_element(type, dir, file)\
-v lib_vssh_hdrs="$$sorted_lib_vssh_hdrs" \
-v lib_vtls_srcs="$$sorted_lib_vtls_srcs" \
-v lib_vtls_hdrs="$$sorted_lib_vtls_hdrs" \
- "$$awk_code" $(srcdir)/$(VC14_10_LIBTMPL) > $(VC14_10_LIBVCXPROJ) || { exit 1; }; \
+ "$$awk_code" $(srcdir)/$(VC14_20_LIBTMPL) > $(VC14_20_LIBVCXPROJ) || { exit 1; }; \
\
- echo "generating '$(VC14_10_SRCVCXPROJ)'"; \
+ echo "generating '$(VC14_20_SRCVCXPROJ)'"; \
awk -v proj_type=vcxproj \
-v src_srcs="$$sorted_src_srcs" \
-v src_hdrs="$$sorted_src_hdrs" \
-v src_rc="$$win32_src_rc" \
-v src_x_srcs="$$sorted_src_x_srcs" \
-v src_x_hdrs="$$sorted_src_x_hdrs" \
- "$$awk_code" $(srcdir)/$(VC14_10_SRCTMPL) > $(VC14_10_SRCVCXPROJ) || { exit 1; }; \
+ "$$awk_code" $(srcdir)/$(VC14_20_SRCTMPL) > $(VC14_20_SRCVCXPROJ) || { exit 1; }; \
\
echo "generating '$(VC14_30_LIBVCXPROJ)'"; \
awk -v proj_type=vcxproj \
diff --git a/Makefile.dist b/Makefile.dist
index a5818e1da..3db331a48 100644
--- a/Makefile.dist
+++ b/Makefile.dist
@@ -30,27 +30,6 @@ ssl:
./configure --with-openssl
make
-mingw32:
- $(MAKE) -C lib -f Makefile.mk
- $(MAKE) -C src -f Makefile.mk
-
-mingw32-clean:
- $(MAKE) -C lib -f Makefile.mk clean
- $(MAKE) -C src -f Makefile.mk clean
- $(MAKE) -C docs/examples -f Makefile.mk clean
-
-mingw32-vclean mingw32-distclean:
- $(MAKE) -C lib -f Makefile.mk vclean
- $(MAKE) -C src -f Makefile.mk vclean
- $(MAKE) -C docs/examples -f Makefile.mk vclean
-
-mingw32-examples%:
- $(MAKE) -C docs/examples -f Makefile.mk CFG=$@
-
-mingw32%:
- $(MAKE) -C lib -f Makefile.mk CFG=$@
- $(MAKE) -C src -f Makefile.mk CFG=$@
-
vc:
cd winbuild
nmake /f Makefile.vc MACHINE=x86
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 0b331a484..0bb5a8d43 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,155 +1,178 @@
-curl and libcurl 8.4.0
+curl and libcurl 8.6.0
- Public curl releases: 252
+ Public curl releases: 254
Command line options: 258
- curl_easy_setopt() options: 303
+ curl_easy_setopt() options: 304
Public functions in libcurl: 93
- Contributors: 2995
+ Contributors: 3078
This release includes the following changes:
- o curl: add support for the IPFS protocols via HTTP gateway [46]
- o curl_multi_get_handles: get easy handles from a multi handle [20]
- o mingw: delete support for legacy mingw.org toolchain [45]
+ o add CURLE_TOO_LARGE [48]
+ o add CURLINFO_QUEUE_TIME_T [76]
+ o add CURLOPT_SERVER_RESPONSE_TIMEOUT_MS: add [39]
+ o asyn-thread: use GetAddrInfoExW on >= Windows 8 [55]
+ o configure: make libpsl detection failure cause error [109]
+ o docs/cmdline: change to .md for cmdline docs [77]
+ o docs: introduce "curldown" for libcurl man page format [102]
+ o runtests: support -gl. Like -g but for lldb. [47]
This release includes the following bugfixes:
- o acinclude.m4: Document proper system truststore on FreeBSD [83]
- o appveyor: fix yamlint issues, indent [67]
- o appveyor: rewrite batch in PowerShell + CI improvements [109]
- o autotools: adjust `CURL_CA_PATH` value to CMake [53]
- o autotools: restore `HAVE_IOCTL_*` detections [111]
- o base64: also build for curl [78]
- o bufq: remove Curl_bufq_skip_and_shift (unused) [47]
- o build: delete checks for C89 standard headers [65]
- o build: do not publish `HAVE_BORINGSSL`, `HAVE_AWSLC` macros [114]
- o cf-socket: simulate slow/blocked receives in debug [120]
- o cmake, configure: also link with CoreServices [32]
- o cmake: add check for suseconds_t [91]
- o cmake: add feature checks for `memrchr` and `getifaddrs` [57]
- o cmake: add missing checks [86]
- o cmake: delete old `HAVE_LDAP_URL_PARSE` logic [105]
- o cmake: detect `HAVE_CLOCK_GETTIME_MONOTONIC_RAW` [75]
- o cmake: detect `HAVE_GETADDRINFO_THREADSAFE` [76]
- o cmake: detect `sys/wait.h` and `netinet/udp.h` [61]
- o cmake: detect TLS-SRP in OpenSSL/wolfSSL/GnuTLS [93]
- o cmake: disable unity mode with Windows Unicode + TrackMemory [108]
- o cmake: fix `HAVE_LDAP_SSL`, `HAVE_LDAP_URL_PARSE` on non-Windows [110]
- o cmake: fix `HAVE_WRITABLE_ARGV` detection [77]
- o cmake: fix duplicate symbols when linking tests [73]
- o cmake: fix missing `zlib.h` when compiling `libcurltool` [72]
- o cmake: fix stderr initialization in unity builds [71]
- o cmake: fix the help text to the static build option in CMakeLists.txt [10]
- o cmake: fix unity builds for more build combinations [96]
- o cmake: fix unity symbol collisions in h2 builds [48]
- o cmake: fix unity with Windows Unicode + TrackMemory [107]
- o cmake: improve OpenLDAP builds [92]
- o cmake: lib `CURL_STATICLIB` fixes (Windows) [74]
- o cmake: move global headers to specific checks [58]
- o cmake: pre-cache `HAVE_BASENAME` for mingw-w64 and MSVC [85]
- o cmake: pre-cache `HAVE_POLL_FINE` on Windows [36]
- o cmake: tidy-up `NOT_NEED_LBER_H` detection
- o cmake: validate `CURL_DEFAULT_SSL_BACKEND` config value [50]
- o configure: check for the capath by default [63]
- o configure: remove unused checks [87]
- o configure: replace adhoc domain with `localhost` in tests [79]
- o configure: sort AC_CHECK_FUNCS
- o connect: expire the timeout when trying next [54]
- o connect: only start the happy eyeballs timer when needed [95]
- o cookie: do not store the expire or max-age strings [16]
- o cookie: remove unnecessary struct fields [17]
- o cookie: set ->running in cookie_init even if data is NULL [5]
- o create-dirs.d: clarify it also uses --output-dirs [66]
- o curl.h: mark CURLSSLBACKEND_NSS as deprecated since 8.3.0 [18]
- o curl_easy_pause.3: mention h2/h3 buffering [113]
- o curl_easy_pause.3: mention it works within callbacks [112]
- o curl_easy_pause: set "in callback" true on exit if true [100]
- o CURLOPT_DEBUGFUNCTION.3: warn about internal handles [122]
- o docs/libcurl/opts/Makefile.inc: add missing manpage files
- o docs: adapt SEE ALSO sections to new requirements [52]
- o docs: explain how PINNEDPUBLICKEY is independent of VERIFYPEER [68]
- o docs: replace made up domains with example.com [82]
- o docs: update curl man page references [89]
- o docs: use CURLSSLBACKEND_NONE [19]
- o doh: inherit DEBUGFUNCTION/DATA [12]
- o escape: replace Curl_isunreserved with ISUNRESERVED [2]
- o FAQ: How do I upgrade curl.exe in Windows? [84]
- o GHA/linux: run singleuse to detect single-use global functions [35]
- o GHA: add workflow to compare configure vs cmake outputs [102]
- o h2-proxy: remove left-over mistake in drain_tunnel() [7]
- o h2: testcase and fix for pausing h2 streams [49]
- o h3: add support for ngtcp2 with AWS-LC builds [103]
- o http2: refused stream handling for retry [121]
- o http: fix CURL_DISABLE_BEARER_AUTH breakage [28]
- o http: h1/h2 proxy unification [21]
- o http: remove wrong comment for http_should_fail [55]
- o http: use per-request counter to check too large headers [6]
- o http_aws_sigv4: fix sorting with empty parts [13]
- o idn: fix WinIDN null ptr deref on bad host [90]
- o idn: if idn2_check_version returns NULL, return error [27]
- o inet_ntop: add typecast to silence Coverity [51]
- o lib: disambiguate Curl_client_write flag semantics [24]
- o lib: enable hmac for digest as well [26]
- o lib: failf/infof compiler warnings [8]
- o lib: let the max filesize option stop too big transfers too [44]
- o lib: move handling of `data->req.writer_stack` into Curl_client_write() [97]
- o lib: provide and use Curl_hexencode [62]
- o lib: remove TIME_WITH_SYS_TIME [88]
- o lib: use wrapper for curl_mime_data fseek callback [30]
- o libssh2: fix error message on failed pubkey-from-file [22]
- o libssh: cap SFTP packet size sent [14]
- o Makefile.mk: always set `CURL_STATICLIB` for lib (Windows) [42]
- o MANUAL.md: change domain to example.com [11]
- o misc: better random strings [15]
- o MQTT: improve receive of ACKs [125]
- o multi: do CURLM_CALL_MULTI_PERFORM at two more places [99]
- o multi: fix small timeouts [70]
- o multi: remove Curl_multi_dump [37]
- o multi: round the timeout up to prevent early wakeups [98]
- o multi: set CURLM_CALL_MULTI_PERFORM after switch to DOING_MORE [115]
- o openssl: improve ssl shutdown handling [69]
- o openssl: use X509_ALGOR_get0 instead of reaching into X509_ALGOR [104]
- o pytest: exclude test_03_goaway in CI runs due to timing dependency [23]
- o quic: set ciphers/curves the same way regular TLS does [43]
- o quiche: fix build error with --with-ca-fallback [1]
- o RELEASE-PROCEDURE.md: updated coming release dates
- o runtests: display the test status if tests appear hung [81]
- o runtests: eliminate a warning on old perl versions
- o socks: return error if hostname too long for remote resolve [118]
- o src/mkhelp: make generated code pass `checksrc` [59]
- o test1056: disable on Windows
- o test1474: disable test on NetBSD, OpenBSD and Solaris 10 [31]
- o test1592: greatly increase the maximum test timeout
- o test1903: actually verify the cookies after the test [116]
- o test1906: set a lower timeout since it's hit on Windows [117]
- o test2600: remove special case handling for USE_ALARM_TIMEOUT [3]
- o test650: fix an end tag typo
- o test661: return from test early in case of curl error
- o test: add missing <feature>s
- o tests: close the shell used to start sshd [41]
- o tests: fix a race condition in ftp server disconnect [101]
- o tests: fix compiler warnings [38]
- o tests: Fix zombie processes left behind by FTP tests. [80]
- o tests: improve SLOWDOWN test reliability by reducing sent data
- o tests: increase lib571 timeout from 3s to 30s [106]
- o tests: log the test result code after each libtest
- o tests: propagate errors in libtests
- o tests: set --expect100-timeout to improve test reliability
- o tests: show which curl tool `runtests.pl` is using [60]
- o tests: stop overriding the lock timeout
- o tftpd: always use curl's own tftp.h [25]
- o tool: use our own stderr variable [94]
- o tool_cb_wrt: fix debug assertion [4]
- o tool_getparam: accept variable expansion on file names too [123]
- o tool_setopt: remove unused function tool_setopt_flags [56]
- o upload-file.d: describe the file name slash/backslash handling [9]
- o url: fall back to http/https proxy env-variable if ws/wss not set [119]
- o url: fix netrc info message [39]
- o warnless: remove unused functions [33]
- o wolfssh: do cleanup in Curl_ssh_cleanup [40]
- o wolfssl: allow capath with CURLOPT_CAINFO_BLOB [29]
- o wolfssl: if CURLOPT_CAINFO_BLOB is set, ignore the CA files [34]
- o wolfssl: ignore errors in CA path [64]
+ o altsvc: free 'as' when returning error [23]
+ o appveyor: replace PowerShell with bash + parallel autotools [54]
+ o appveyor: switch to out-of-tree builds [29]
+ o asyn-ares: with modern c-ares, use its default timeout [127]
+ o build: delete unused `HAVE_{GSSHEIMDAL,GSSMIT,HEIMDAL}` [4]
+ o build: delete/replace clang warning pragmas [111]
+ o build: enable missing OpenSSF-recommended warnings, with fixes [11]
+ o build: fix `-Wconversion`/`-Wsign-conversion` warnings [26]
+ o build: fix Windows ADDRESS_FAMILY detection [35]
+ o build: more `-Wformat` fixes [40]
+ o build: remove redundant `CURL_PULL_*` settings [8]
+ o cf-h1-proxy: no CURLOPT_USERAGENT in CONNECT with hyper [133]
+ o cf-socket: show errno in tcpkeepalive error messages [120]
+ o CI/distcheck: run full tests [31]
+ o cmake: add option to disable building docs
+ o cmake: fix generation for system name iOS [53]
+ o cmake: fix typo [5]
+ o cmake: freshen up docs/INSTALL.cmake [101]
+ o cmake: prefill/cache `HAVE_STRUCT_SOCKADDR_STORAGE` [45]
+ o cmake: rework options to enable curl and libcurl docs [161]
+ o cmake: when USE_MANUAL=YES, build the curl.1 man page [113]
+ o cmdline-opts/write-out.d: remove spurious double quotes
+ o cmdline-opts: update availability for the *-ca-native options [66]
+ o cmdline/gen: fix the sorting of the man page options [33]
+ o configure: add libngtcp2_crypto_boringssl detection [155]
+ o configure: fix no default int compile error in ipv6 detection [69]
+ o configure: when enabling QUIC, check that TLS supports QUIC [87]
+ o connect: remove margin from eyeballer alloc [79]
+ o content_encoding: change return code to typedef'ed enum [94]
+ o cookie.d: document use of empty string to enable cookie engine [106]
+ o cookie: avoid fopen with empty file name [24]
+ o curl.h: CURLOPT_DNS_SERVERS is only available with c-ares [131]
+ o curl: show ipfs and ipns as supported "protocols" [15]
+ o curl_easy_getinfo.3: remove the wrong time value count [116]
+ o curl_multi_fdset.3: remove mention of null pointer support [134]
+ o CURLINFO_REFERER.3: clarify that it is the *request* header [70]
+ o CURLOPT_AUTOREFERER.3: mention CURLINFO_REFERER
+ o CURLOPT_POSTFIELDS.3: fix incorrect C string escape in example [27]
+ o CURLOPT_SSH_*_KEYFILE: clarify [57]
+ o dist: add tests/errorcodes.pl to the tarball [6]
+ o docs: clean up Protocols: for cmdline options [32]
+ o docs: describe and highlight super cookies [80]
+ o docs: do not start lines/sentences with So, But nor And [140]
+ o docs: install curl.1 with cmake [166]
+ o docs: mention env vars not used by schannel [124]
+ o doh: remove unused local variable [34]
+ o examples: add four new examples [99]
+ o file+ftp: use stack buffers instead of data->state.buffer [138]
+ o ftp: handle the PORT parsing without allocation [44]
+ o ftp: use dynbuf to store entrypath [83]
+ o ftp: use memdup0 to store the OS from a SYST 215 response [82]
+ o ftpserver.pl: send 213 SIZE response without spurious newline
+ o gen.pl: support ## for doing .IP in table-like lists [105]
+ o gen: do italics/bold for a range of letters, not just single word [78]
+ o GHA: add a job scanning for "bad words" in markdown [164]
+ o GHA: bump ngtcp2, gnutls, mod_h2, quiche [158]
+ o gnutls: fix build with --disable-verbose [3]
+ o haproxy-clientip.d: document the arg [68]
+ o headers: make sure the trailing newline is not stored [97]
+ o headers: remove assert from Curl_headers_push [115]
+ o hostip: return error immediately when Curl_ip2addr() fails [19]
+ o hsts: remove assert for zero length domain [96]
+ o http2: improved on_stream_close/data_done handling [49]
+ o http3/quiche: fix result code on a stream reset [91]
+ o http3: initial support for OpenSSL 3.2 QUIC stack [110]
+ o http: adjust_pollset fix [85]
+ o http: check for "Host:" case insensitively [154]
+ o http: fix off-by-one error in request method length check [14]
+ o http: only act on 101 responses when they are HTTP/1.1 [98]
+ o http: remove comment reference to a removed solution [156]
+ o http: use stack scratch buffer [150]
+ o http_proxy: a blank CURLOPT_USERAGENT should not be used in CONNECT [90]
+ o krb5: add prototype to silence clang warnings on mvsnprintf() [119]
+ o lib: add debug log outputs for CURLE_BAD_FUNCTION_ARGUMENT [62]
+ o lib: error out on multissl + http3 [13]
+ o lib: fix variable undeclared error caused by `infof` changes [2]
+ o lib: reduce use of strncpy [30]
+ o lib: rename Curl_strndup to Curl_memdup0 to avoid misunderstanding [36]
+ o lib: replace readwrite with write_resp [137]
+ o lib: strndup/memdup instead of malloc, memcpy and null-terminate [42]
+ o libssh2: use `libssh2_session_callback_set2()` with v1.11.1 [103]
+ o libssh: improve the deprecation warning dismissal [20]
+ o libssh: supress warnings without version check [18]
+ o Makefile.am: fix the MSVC project generation [22]
+ o Makefile.mk: drop Windows support [12]
+ o mbedtls: fix `-Wnull-dereference` and `-Wredundant-decls` [117]
+ o mbedtls: free the entropy when threaded [46]
+ o mime: use memdup0 instead of malloc + memcpy [63]
+ o mksymbolsmanpage.pl: provide references to where the symbol is used
+ o mprintf: overhaul and bugfixes [52]
+ o mqtt: use stack scratch buffer for recv+publish [148]
+ o multi: remove total timer reset in file_do() while fetching file:// [89]
+ o ngtcp2: put h3 at the front of alpn [58]
+ o ntlm_wb: do not use data->state.buffer any longer [151]
+ o openldap: fix an LDAP crash [75]
+ o openldap: fix STARTTLS [67]
+ o openssl: re-match LibreSSL deinit with init [17]
+ o openssl: when verifystatus fails, remove session id from cache [100]
+ o OS400: sync ILE/RPG binding [114]
+ o pingpong: stop using the download buffer [159]
+ o pop3: replace calloc + memcpy with memdup0 [60]
+ o pytest: scorecard tracking CPU and RSS [157]
+ o quiche: return CURLE_HTTP3 on send to invalid stream [65]
+ o readwrite_data: loop less [21]
+ o Revert "urldata: move async resolver state from easy handle to connectdata" [16]
+ o rtsp: deal with borked server responses [129]
+ o runtests: for mode="text" on <stdout>, fix newlines on both parts [64]
+ o sasl: make login option string override http auth [142]
+ o schannel: fix `-Warith-conversion` gcc 13 warning [28]
+ o sectransp: do verify_cert without memdup for blobs [93]
+ o sectransp_ make TLSCipherNameForNumber() available in non-verbose config [1]
+ o sendf: fix compiler warning with CURL_DISABLE_HEADERS_API [38]
+ o setopt: clear mimepost when formp is freed [92]
+ o setopt: use memdup0 when cloning COPYPOSTFIELDS [107]
+ o socks: fix generic output string to say SOCKS instead of SOCKS4 [144]
+ o socks: use own buffer instead of data->state.buffer [143]
+ o ssh: fix namespace of two local macros [51]
+ o ssh: use stack scratch buffer for seeks [146]
+ o strerror: repair get_winsock_error() [56]
+ o system.h: sync mingw `CURL_TYPEOF_CURL_SOCKLEN_T` with other compilers [9]
+ o system_win32: fix a function pointer assignment warning [71]
+ o telnet: use dynbuf instad of malloc for escape buffer [108]
+ o telnet: use stack scratch buffer for do [149]
+ o tests/server: delete workaround for old-mingw [25]
+ o tests: avoid int/size_t conversion size/sign warnings [163]
+ o tests: respect $TMPDIR when creating unix domain sockets [50]
+ o tool: make parser reject blank arguments if not supported [86]
+ o tool: prepend output_dir in header callback [95]
+ o tool_getparam: bsearch cmdline options [74]
+ o tool_getparam: do not try to expand without an argument [59]
+ o tool_getparam: stop supporting `@filename` style for --cookie [121]
+ o tool_listhelp: regenerate after recent .d updates [61]
+ o tool_operate: make --remove-on-error only remove "real" files [125]
+ o tool_operate: stop setting the file comment on Amiga [128]
+ o transfer: adjust_pollset improvements [81]
+ o transfer: fix upload rate limiting, add test cases [37]
+ o transfer: make the select_bits_paused condition check both directions [104]
+ o transfer: remove warning: Value stored to 'blen' is never read [136]
+ o url: don't set default CA paths for Secure Transport backend [126]
+ o url: for disabled protocols, mention if found in redirect [7]
+ o urlapi: remove assert [162]
+ o verify-examples.pl: fail verification on unescaped backslash [72]
+ o version: show only the libpsl version, not its dependencies [130]
+ o vquic: extract TLS setup into own source [88]
+ o vtls: fix missing multissl version info [73]
+ o vtls: receive max buffer [139]
+ o vtls: remove the Curl_cft_ssl_proxy object if CURL_DISABLE_PROXY [41]
+ o websockets: check for negative payload lengths [123]
+ o websockets: refactor decode chain [122]
+ o windows: delete redundant headers [43]
+ o windows: simplify detecting and using system headers [10]
+ o wolfssl: load certificate *chain* for PEM client certs [84]
+ o x509asn1: remove code for WANT_VERIFYHOST [132]
+ o x509asn1: switch from malloc to dynbuf [112]
This release includes the following known bugs:
@@ -164,143 +187,179 @@ Planned upcoming removals include:
This release would not have looked like this without help, code, reports and
advice from friends like these:
- Aleksander Mazur, black-desk on github, calvin2021y on github,
- Christian Schmitz, Christian Weisgerber, claudiusaiz on github,
- consulion on github, Craig Andrews, Dan Fandrich, Daniel Stenberg,
- David Benjamin, Douglas R. Reno, Eduard Strehlau, Elliot Killick,
- Gisle Vanem, Hakan Sunay Halil, Harry Sintonen, Jakub Jelen, John Haugabook,
- Joshix-1 on github, Juliusz Sosinowicz, Junho Choi,
- Karthikdasari0423 on github, Lars Francke, Loïc Yhuel, Marc Hörsken,
- Mark Gaiser, Mathias Fuchs, Maxim Dzhura, Michael Osipov, Natanael Copa,
- Patrick Monnerat, PBudmark on github, Peter Wang, Philip Heiduck, Ray Satiro,
- Robert Simpson, Ryan Schmidt, s0urc3_ on hackerone, Samuel Henrique,
- Stefan Eissing, Ted Lyngmo, Viktor Szakats, vvb2060, w0x42 on hackerone,
- 南宫雪珊
- (46 contributors)
+ Andy Alt, annalee, Baruch Siach, Ben, Boris Verkhovskiy, Brad Harder,
+ bubbleguuum on github, Cajus Pollmeier, calvin2021y on github, Chara White,
+ Chris Sauer, Dan Fandrich, Daniel Gustafsson, Daniel Stenberg,
+ dependabot[bot], Dmitry Karpov, Gabe, Geeknik Labs, Gisle Vanem,
+ Graham Campbell, Hans-Christian Egtvedt, Harry Sintonen, Haydar Alaidrus,
+ hgdagon on github, Hiroki Kurosawa, iAroc on github, ivanfywang,
+ janko-js on github, Jay Wu, Jess Lowe, Karthikdasari0423 on github,
+ Lealem Amedie, Lin Sun, Marcel Raad, Mark Huang, Mark Sinkovics,
+ Mauricio Scheffer, Michał Antoniak, Mike Hommey, Mohammadreza Hendiani,
+ Ozan Cansel, Patrick Monnerat, Pavel Pavlov, promptfuzz_ on hackerone,
+ Ray Satiro, RevaliQaQ on github, Richard Levitte, Scarlett McAllister,
+ Sergey Bronnikov, Sergey Markelov, sfan5 on github, Stefan Eissing,
+ Tatsuhiko Miyagawa, Tatsuhiro Tsujikawa, Theo, Thomas Ferguson,
+ Viktor Szakats, Xi Ruoyao, Yadhu Krishna M, Yedaya Katsman, Yifei Kong,
+ YX Hao, zengwei, zengwei2000, ウさん
+ (65 contributors)
References to bug reports and discussions on issues:
- [1] = https://curl.se/bug/?i=11850
- [2] = https://curl.se/bug/?i=11846
- [3] = https://curl.se/bug/?i=11767
- [4] = https://github.com/curl/curl/commit/af3f4e41#r127212213
- [5] = https://curl.se/bug/?i=11875
- [6] = https://curl.se/bug/?i=11871
- [7] = https://curl.se/bug/?i=11877
- [8] = https://curl.se/bug/?i=11874
- [9] = https://curl.se/bug/?i=11911
- [10] = https://curl.se/bug/?i=11843
- [11] = https://curl.se/bug/?i=11866
- [12] = https://curl.se/bug/?i=11864
- [13] = https://curl.se/bug/?i=11855
- [14] = https://curl.se/bug/?i=11804
- [15] = https://curl.se/bug/?i=11838
- [16] = https://curl.se/bug/?i=11862
- [17] = https://curl.se/bug/?i=11862
- [18] = https://curl.se/bug/?i=11905
- [19] = https://curl.se/bug/?i=11909
- [20] = https://curl.se/bug/?i=11750
- [21] = https://curl.se/bug/?i=11808
- [22] = https://curl.se/bug/?i=11837
- [23] = https://curl.se/bug/?i=11860
- [24] = https://curl.se/bug/?i=11885
- [25] = https://curl.se/bug/?i=11897
- [26] = https://curl.se/bug/?i=11890
- [27] = https://curl.se/bug/?i=11898
- [28] = https://curl.se/bug/?i=11892
- [29] = https://curl.se/bug/?i=11886
- [30] = https://curl.se/bug/?i=11882
- [31] = https://curl.se/bug/?i=11888
- [32] = https://curl.se/bug/?i=11893
- [33] = https://curl.se/bug/?i=11932
- [34] = https://curl.se/bug/?i=11884
- [35] = https://curl.se/bug/?i=11932
- [36] = https://curl.se/bug/?i=12003
- [37] = https://curl.se/bug/?i=11931
- [38] = https://curl.se/bug/?i=11925
- [39] = https://curl.se/bug/?i=11904
- [40] = https://curl.se/bug/?i=11921
- [41] = https://curl.se/bug/?i=12032
- [42] = https://curl.se/bug/?i=11924
- [43] = https://curl.se/bug/?i=11796
- [44] = https://curl.se/bug/?i=11810
- [45] = https://curl.se/bug/?i=11625
- [46] = https://curl.se/bug/?i=8805
- [47] = https://curl.se/bug/?i=11915
- [48] = https://curl.se/bug/?i=11912
- [49] = https://curl.se/bug/?i=11982
- [50] = https://curl.se/bug/?i=11998
- [51] = https://curl.se/bug/?i=11960
- [52] = https://curl.se/bug/?i=11957
- [53] = https://curl.se/bug/?i=11997
- [54] = https://curl.se/bug/?i=11920
- [55] = https://curl.se/bug/?i=11941
- [56] = https://curl.se/bug/?i=11943
- [57] = https://curl.se/bug/?i=11954
- [58] = https://curl.se/bug/?i=11951
- [59] = https://curl.se/bug/?i=11955
- [60] = https://curl.se/bug/?i=11953
- [61] = https://curl.se/bug/?i=11996
- [62] = https://curl.se/bug/?i=11990
- [63] = https://curl.se/bug/?i=11987
- [64] = https://curl.se/bug/?i=11987
- [65] = https://curl.se/bug/?i=11940
- [66] = https://curl.se/bug/?i=11991
- [67] = https://curl.se/bug/?i=11994
- [68] = https://curl.se/bug/?i=2935
- [69] = https://curl.se/bug/?i=11858
- [70] = https://curl.se/bug/?i=11937
- [71] = https://curl.se/bug/?i=11929
- [72] = https://curl.se/bug/?i=11927
- [73] = https://curl.se/bug/?i=11926
- [74] = https://curl.se/bug/?i=11914
- [75] = https://curl.se/bug/?i=11981
- [76] = https://curl.se/bug/?i=11979
- [77] = https://curl.se/bug/?i=11978
- [78] = https://curl.se/bug/?i=12010
- [79] = https://curl.se/bug/?i=11988
- [80] = https://curl.se/bug/?i=12018
- [81] = https://curl.se/bug/?i=11980
- [82] = https://curl.se/bug/?i=11986
- [83] = https://curl.se/bug/?i=11985
- [84] = https://curl.se/bug/?i=11984
- [85] = https://curl.se/bug/?i=11974
- [86] = https://curl.se/bug/?i=11973
- [87] = https://curl.se/bug/?i=11973
- [88] = https://curl.se/bug/?i=11975
- [89] = https://curl.se/bug/?i=11963
- [90] = https://curl.se/bug/?i=11983
- [91] = https://curl.se/bug/?i=11977
- [92] = https://curl.se/bug/?i=12024
- [93] = https://curl.se/bug/?i=11967
- [94] = https://curl.se/bug/?i=11958
- [95] = https://curl.se/bug/?i=11939
- [96] = https://curl.se/bug/?i=12027
- [97] = https://curl.se/bug/?i=11908
- [98] = https://curl.se/bug/?i=11938
- [99] = https://curl.se/bug/?i=12033
- [100] = https://curl.se/bug/?i=12059
- [101] = https://curl.se/bug/?i=12002
- [102] = https://curl.se/bug/?i=11964
- [103] = https://curl.se/bug/?i=12066
- [104] = https://curl.se/bug/?i=12038
- [105] = https://curl.se/bug/?i=12015
- [106] = https://curl.se/bug/?i=12013
- [107] = https://curl.se/bug/?i=11928
- [108] = https://curl.se/bug/?i=12005
- [109] = https://curl.se/bug/?i=11999
- [110] = https://curl.se/bug/?i=12006
- [111] = https://curl.se/bug/?i=12008
- [112] = https://curl.se/mail/lib-2023-10/0010.html
- [113] = https://curl.se/bug/?i=12045
- [114] = https://curl.se/bug/?i=12065
- [115] = https://curl.se/bug/?i=12042
- [116] = https://curl.se/bug/?i=12041
- [117] = https://curl.se/bug/?i=12036
- [118] = https://curl.se/docs/CVE-2023-38545.html
- [119] = https://curl.se/bug/?i=12031
- [120] = https://curl.se/bug/?i=12035
- [121] = https://curl.se/bug/?i=12054
- [122] = https://curl.se/bug/?i=12034
- [123] = https://curl.se/bug/?i=12048
- [125] = https://curl.se/bug/?i=12071
+ [1] = https://curl.se/bug/?i=12474
+ [2] = https://curl.se/bug/?i=12470
+ [3] = https://curl.se/bug/?i=12505
+ [4] = https://curl.se/bug/?i=12506
+ [5] = https://curl.se/bug/?i=12464
+ [6] = https://curl.se/bug/?i=12462
+ [7] = https://curl.se/bug/?i=12466
+ [8] = https://curl.se/bug/?i=12502
+ [9] = https://curl.se/bug/?i=12501
+ [10] = https://curl.se/bug/?i=12495
+ [11] = https://curl.se/bug/?i=12489
+ [12] = https://curl.se/bug/?i=12224
+ [13] = https://curl.se/bug/?i=12807
+ [14] = https://curl.se/bug/?i=12534
+ [15] = https://curl.se/mail/archive-2023-12/0026.html
+ [16] = https://curl.se/bug/?i=12524
+ [17] = https://curl.se/bug/?i=12525
+ [18] = https://curl.se/bug/?i=12523
+ [19] = https://curl.se/bug/?i=12522
+ [20] = https://curl.se/bug/?i=12519
+ [21] = https://curl.se/bug/?i=12504
+ [22] = https://curl.se/bug/?i=12564
+ [23] = https://curl.se/bug/?i=12570
+ [24] = https://curl.se/bug/?i=12514
+ [25] = https://curl.se/bug/?i=12510
+ [26] = https://curl.se/bug/?i=12557
+ [27] = https://curl.se/bug/?i=12588
+ [28] = https://curl.se/bug/?i=12616
+ [29] = https://curl.se/bug/?i=12550
+ [30] = https://curl.se/bug/?i=12499
+ [31] = https://curl.se/bug/?i=12503
+ [32] = https://curl.se/bug/?i=12496
+ [33] = https://curl.se/mail/archive-2023-12/0014.html
+ [34] = https://curl.se/bug/?i=12491
+ [35] = https://curl.se/bug/?i=12441
+ [36] = https://curl.se/bug/?i=12490
+ [37] = https://curl.se/bug/?i=12559
+ [38] = https://curl.se/bug/?i=12485
+ [39] = https://curl.se/bug/?i=12369
+ [40] = https://curl.se/bug/?i=12540
+ [41] = https://curl.se/bug/?i=12459
+ [42] = https://curl.se/bug/?i=12453
+ [43] = https://curl.se/bug/?i=12539
+ [44] = https://curl.se/bug/?i=12456
+ [45] = https://curl.se/bug/?i=12537
+ [46] = https://curl.se/bug/?i=12584
+ [47] = https://curl.se/bug/?i=12547
+ [48] = https://curl.se/bug/?i=12269
+ [49] = https://curl.se/bug/?i=10936
+ [50] = https://curl.se/bug/?i=12545
+ [51] = https://curl.se/bug/?i=12544
+ [52] = https://curl.se/bug/?i=12561
+ [53] = https://curl.se/bug/?i=12515
+ [54] = https://curl.se/bug/?i=12560
+ [55] = https://curl.se/bug/?i=12481
+ [56] = https://curl.se/bug/?i=12578
+ [57] = https://curl.se/bug/?i=12554
+ [58] = https://curl.se/bug/?i=12576
+ [59] = https://curl.se/bug/?i=12565
+ [60] = https://curl.se/bug/?i=12650
+ [61] = https://curl.se/bug/?i=12612
+ [62] = https://curl.se/bug/?i=12658
+ [63] = https://curl.se/bug/?i=12649
+ [64] = https://curl.se/bug/?i=12612
+ [65] = https://curl.se/bug/?i=12590
+ [66] = https://curl.se/bug/?i=12613
+ [67] = https://curl.se/bug/?i=12610
+ [68] = https://curl.se/bug/?i=12611
+ [69] = https://curl.se/bug/?i=12607
+ [70] = https://curl.se/bug/?i=12605
+ [71] = https://curl.se/bug/?i=12581
+ [72] = https://curl.se/bug/?i=12589
+ [73] = https://curl.se/bug/?i=12599
+ [74] = https://curl.se/bug/?i=12631
+ [75] = https://curl.se/bug/?i=12593
+ [76] = https://curl.se/bug/?i=12368
+ [77] = https://curl.se/bug/?i=12751
+ [78] = https://curl.se/bug/?i=12689
+ [79] = https://curl.se/bug/?i=12647
+ [80] = https://curl.se/bug/?i=12687
+ [81] = https://curl.se/bug/?i=12640
+ [82] = https://curl.se/bug/?i=12639
+ [83] = https://curl.se/bug/?i=12638
+ [84] = https://curl.se/bug/?i=12634
+ [85] = https://curl.se/bug/?i=12632
+ [86] = https://curl.se/bug/?i=12620
+ [87] = https://curl.se/bug/?i=12683
+ [88] = https://curl.se/bug/?i=12678
+ [89] = https://curl.se/bug/?i=12682
+ [90] = https://curl.se/bug/?i=12680
+ [91] = https://curl.se/bug/?i=12629
+ [92] = https://curl.se/bug/?i=12608
+ [93] = https://curl.se/bug/?i=12679
+ [94] = https://curl.se/bug/?i=12618
+ [95] = https://curl.se/bug/?i=12614
+ [96] = https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65661
+ [97] = https://curl.se/mail/lib-2024-01/0019.html
+ [98] = https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=66184
+ [99] = https://curl.se/bug/?i=12671
+ [100] = https://curl.se/bug/?i=12760
+ [101] = https://curl.se/bug/?i=12772
+ [102] = https://curl.se/bug/?i=12730
+ [103] = https://curl.se/bug/?i=12754
+ [104] = https://curl.se/mail/lib-2024-01/0049.html
+ [105] = https://curl.se/bug/?i=12667
+ [106] = https://curl.se/bug/?i=12643
+ [107] = https://curl.se/bug/?i=12651
+ [108] = https://curl.se/bug/?i=12652
+ [109] = https://curl.se/bug/?i=12661
+ [110] = https://curl.se/bug/?i=12734
+ [111] = https://curl.se/bug/?i=12812
+ [112] = https://curl.se/bug/?i=12808
+ [113] = https://curl.se/bug/?i=12742
+ [114] = https://curl.se/bug/?i=12815
+ [115] = https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65839
+ [116] = https://curl.se/bug/?i=12727
+ [117] = https://curl.se/bug/?i=12720
+ [119] = https://curl.se/bug/?i=12803
+ [120] = https://curl.se/bug/?i=12726
+ [121] = https://curl.se/bug/?i=12645
+ [122] = https://curl.se/bug/?i=12713
+ [123] = https://curl.se/bug/?i=12707
+ [124] = https://curl.se/bug/?i=12711
+ [125] = https://curl.se/bug/?i=12710
+ [126] = https://curl.se/bug/?i=12704
+ [127] = https://curl.se/bug/?i=12703
+ [128] = https://curl.se/bug/?i=12709
+ [129] = https://curl.se/bug/?i=12701
+ [130] = https://curl.se/bug/?i=12700
+ [131] = https://curl.se/bug/?i=12695
+ [132] = https://curl.se/bug/?i=12804
+ [133] = https://curl.se/bug/?i=12697
+ [134] = https://curl.se/bug/?i=12691
+ [136] = https://curl.se/bug/?i=12693
+ [137] = https://curl.se/bug/?i=12480
+ [138] = https://curl.se/bug/?i=12789
+ [139] = https://curl.se/bug/?i=12801
+ [140] = https://curl.se/bug/?i=12802
+ [142] = https://curl.se/bug/?i=10259
+ [143] = https://curl.se/bug/?i=12788
+ [144] = https://curl.se/bug/?i=12797
+ [146] = https://curl.se/bug/?i=12794
+ [148] = https://curl.se/bug/?i=12792
+ [149] = https://curl.se/bug/?i=12793
+ [150] = https://curl.se/bug/?i=12791
+ [151] = https://curl.se/bug/?i=12787
+ [154] = https://curl.se/bug/?i=12784
+ [155] = https://curl.se/bug/?i=12724
+ [156] = https://curl.se/bug/?i=12785
+ [157] = https://curl.se/bug/?i=12765
+ [158] = https://curl.se/bug/?i=12778
+ [159] = https://curl.se/bug/?i=12757
+ [161] = https://curl.se/bug/?i=12773
+ [162] = https://curl.se/bug/?i=12775
+ [163] = https://curl.se/bug/?i=12768
+ [164] = https://curl.se/bug/?i=12764
+ [166] = https://curl.se/bug/?i=12759
diff --git a/acinclude.m4 b/acinclude.m4
index 5fdd51e52..a44ae350e 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -156,7 +156,6 @@ AC_DEFUN([CURL_CHECK_AIX_ALL_SOURCE], [
#endif])
AC_BEFORE([$0], [AC_SYS_LARGEFILE])dnl
AC_BEFORE([$0], [CURL_CONFIGURE_REENTRANT])dnl
- AC_BEFORE([$0], [CURL_CONFIGURE_PULL_SYS_POLL])dnl
AC_MSG_CHECKING([if OS is AIX (to define _ALL_SOURCE)])
AC_EGREP_CPP([yes_this_is_aix],[
#ifdef _AIX
@@ -171,144 +170,28 @@ AC_DEFUN([CURL_CHECK_AIX_ALL_SOURCE], [
])
-dnl CURL_CHECK_HEADER_WINDOWS
-dnl -------------------------------------------------
-dnl Check for compilable and valid windows.h header
-
-AC_DEFUN([CURL_CHECK_HEADER_WINDOWS], [
- AC_CACHE_CHECK([for windows.h], [curl_cv_header_windows_h], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
- ]],[[
-#if defined(__CYGWIN__) || defined(__CEGCC__)
- HAVE_WINDOWS_H shall not be defined.
-#else
- int dummy=2*WINVER;
-#endif
- ]])
- ],[
- curl_cv_header_windows_h="yes"
- ],[
- curl_cv_header_windows_h="no"
- ])
- ])
- case "$curl_cv_header_windows_h" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_WINDOWS_H, 1,
- [Define to 1 if you have the windows.h header file.])
- ;;
- esac
-])
-
-
dnl CURL_CHECK_NATIVE_WINDOWS
dnl -------------------------------------------------
dnl Check if building a native Windows target
AC_DEFUN([CURL_CHECK_NATIVE_WINDOWS], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINDOWS])dnl
AC_CACHE_CHECK([whether build target is a native Windows one], [curl_cv_native_windows], [
- if test "$curl_cv_header_windows_h" = "no"; then
- curl_cv_native_windows="no"
- else
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- ]],[[
-#if defined(__MINGW32__) || defined(__MINGW32CE__) || \
- (defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64)))
- int dummy=1;
-#else
- Not a native Windows build target.
-#endif
- ]])
- ],[
- curl_cv_native_windows="yes"
- ],[
- curl_cv_native_windows="no"
- ])
- fi
- ])
- AM_CONDITIONAL(DOING_NATIVE_WINDOWS, test "x$curl_cv_native_windows" = xyes)
-])
-
-
-dnl CURL_CHECK_HEADER_WINSOCK2
-dnl -------------------------------------------------
-dnl Check for compilable and valid winsock2.h header
-
-AC_DEFUN([CURL_CHECK_HEADER_WINSOCK2], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINDOWS])dnl
- AC_CACHE_CHECK([for winsock2.h], [curl_cv_header_winsock2_h], [
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <winsock2.h>
- ]],[[
-#if defined(__CYGWIN__) || defined(__CEGCC__) || defined(__MINGW32CE__)
- HAVE_WINSOCK2_H shall not be defined.
-#else
- int dummy=2*IPPROTO_ESP;
-#endif
- ]])
- ],[
- curl_cv_header_winsock2_h="yes"
- ],[
- curl_cv_header_winsock2_h="no"
- ])
- ])
- case "$curl_cv_header_winsock2_h" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_WINSOCK2_H, 1,
- [Define to 1 if you have the winsock2.h header file.])
- ;;
- esac
-])
-
-
-dnl CURL_CHECK_HEADER_WS2TCPIP
-dnl -------------------------------------------------
-dnl Check for compilable and valid ws2tcpip.h header
-
-AC_DEFUN([CURL_CHECK_HEADER_WS2TCPIP], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINSOCK2])dnl
- AC_CACHE_CHECK([for ws2tcpip.h], [curl_cv_header_ws2tcpip_h], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
]],[[
-#if defined(__CYGWIN__) || defined(__CEGCC__) || defined(__MINGW32CE__)
- HAVE_WS2TCPIP_H shall not be defined.
+#ifdef _WIN32
+ int dummy=1;
#else
- int dummy=2*IP_PKTINFO;
+ Not a native Windows build target.
#endif
]])
],[
- curl_cv_header_ws2tcpip_h="yes"
+ curl_cv_native_windows="yes"
],[
- curl_cv_header_ws2tcpip_h="no"
+ curl_cv_native_windows="no"
])
])
- case "$curl_cv_header_ws2tcpip_h" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_WS2TCPIP_H, 1,
- [Define to 1 if you have the ws2tcpip.h header file.])
- ;;
- esac
+ AM_CONDITIONAL(DOING_NATIVE_WINDOWS, test "x$curl_cv_native_windows" = xyes)
])
@@ -318,12 +201,12 @@ dnl Check for compilable and valid lber.h header,
dnl and check if it is needed even with ldap.h
AC_DEFUN([CURL_CHECK_HEADER_LBER], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINDOWS])dnl
+ AC_REQUIRE([CURL_CHECK_NATIVE_WINDOWS])dnl
AC_CACHE_CHECK([for lber.h], [curl_cv_header_lber_h], [
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -355,7 +238,7 @@ AC_DEFUN([CURL_CHECK_HEADER_LBER], [
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -403,7 +286,7 @@ AC_DEFUN([CURL_CHECK_HEADER_LDAP], [
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -449,7 +332,7 @@ AC_DEFUN([CURL_CHECK_HEADER_LDAP_SSL], [
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -534,7 +417,7 @@ AC_DEFUN([CURL_CHECK_LIBS_WINLDAP], [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -632,7 +515,7 @@ AC_DEFUN([CURL_CHECK_LIBS_LDAP], [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -701,14 +584,11 @@ AC_DEFUN([TYPE_SOCKADDR_STORAGE],
[if struct sockaddr_storage is defined]), ,
[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -731,7 +611,7 @@ dnl -------------------------------------------------
dnl Test if the socket recv() function is available,
AC_DEFUN([CURL_CHECK_FUNC_RECV], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINSOCK2])dnl
+ AC_REQUIRE([CURL_CHECK_NATIVE_WINDOWS])dnl
AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
AC_CHECK_HEADERS(sys/types.h sys/socket.h)
#
@@ -739,14 +619,11 @@ AC_DEFUN([CURL_CHECK_FUNC_RECV], [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
$curl_includes_bsdsocket
#ifdef HAVE_SYS_TYPES_H
@@ -782,7 +659,7 @@ dnl -------------------------------------------------
dnl Test if the socket send() function is available,
AC_DEFUN([CURL_CHECK_FUNC_SEND], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINSOCK2])dnl
+ AC_REQUIRE([CURL_CHECK_NATIVE_WINDOWS])dnl
AC_REQUIRE([CURL_INCLUDES_BSDSOCKET])dnl
AC_CHECK_HEADERS(sys/types.h sys/socket.h)
#
@@ -790,14 +667,11 @@ AC_DEFUN([CURL_CHECK_FUNC_SEND], [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
$curl_includes_bsdsocket
#ifdef HAVE_SYS_TYPES_H
@@ -837,14 +711,11 @@ AC_DEFUN([CURL_CHECK_MSG_NOSIGNAL], [
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -876,21 +747,18 @@ dnl -------------------------------------------------
dnl Check for timeval struct
AC_DEFUN([CURL_CHECK_STRUCT_TIMEVAL], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINSOCK2])dnl
+ AC_REQUIRE([CURL_CHECK_NATIVE_WINDOWS])dnl
AC_CHECK_HEADERS(sys/types.h sys/time.h sys/socket.h)
AC_CACHE_CHECK([for struct timeval], [curl_cv_struct_timeval], [
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -937,14 +805,11 @@ AC_DEFUN([TYPE_IN_ADDR_T], [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -979,14 +844,11 @@ AC_DEFUN([TYPE_IN_ADDR_T], [
esac
],[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -1197,7 +1059,7 @@ AC_DEFUN([CURL_CHECK_LIBS_CONNECT], [
AC_LANG_PROGRAM([[
$curl_includes_winsock2
$curl_includes_bsdsocket
- #if !defined(HAVE_WINDOWS_H) && !defined(HAVE_PROTO_BSDSOCKET_H)
+ #if !defined(_WIN32) && !defined(HAVE_PROTO_BSDSOCKET_H)
int connect(int, void*, int);
#endif
]],[[
@@ -1246,40 +1108,6 @@ cat >>confdefs.h <<_EOF
_EOF
])
-dnl CURL_CONFIGURE_PULL_SYS_POLL
-dnl -------------------------------------------------
-dnl The need for the sys/poll.h inclusion arises mainly to properly
-dnl interface AIX systems which define macros 'events' and 'revents'.
-
-AC_DEFUN([CURL_CONFIGURE_PULL_SYS_POLL], [
- AC_REQUIRE([CURL_INCLUDES_POLL])dnl
- #
- tst_poll_events_macro_defined="unknown"
- #
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
- $curl_includes_poll
- ]],[[
-#if defined(events) || defined(revents)
- return 0;
-#else
- force compilation error
-#endif
- ]])
- ],[
- tst_poll_events_macro_defined="yes"
- ],[
- tst_poll_events_macro_defined="no"
- ])
- #
- if test "$tst_poll_events_macro_defined" = "yes"; then
- if test "x$ac_cv_header_sys_poll_h" = "xyes"; then
- CURL_DEFINE_UNQUOTED([CURL_PULL_SYS_POLL_H])
- fi
- fi
- #
-])
-
dnl CURL_CHECK_FUNC_SELECT
dnl -------------------------------------------------
@@ -1294,15 +1122,12 @@ AC_DEFUN([CURL_CHECK_FUNC_SELECT], [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -1310,7 +1135,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SELECT], [
#include <sys/time.h>
#endif
#include <time.h>
-#ifndef HAVE_WINDOWS_H
+#ifndef _WIN32
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#elif defined(HAVE_UNISTD_H)
@@ -1374,70 +1199,6 @@ int main()
])
-dnl CURL_CHECK_VARIADIC_MACROS
-dnl -------------------------------------------------
-dnl Check compiler support of variadic macros
-
-AC_DEFUN([CURL_CHECK_VARIADIC_MACROS], [
- AC_CACHE_CHECK([for compiler support of C99 variadic macro style],
- [curl_cv_variadic_macros_c99], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__)
-#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__)
- int fun3(int arg1, int arg2, int arg3);
- int fun2(int arg1, int arg2);
- int fun3(int arg1, int arg2, int arg3)
- { return arg1 + arg2 + arg3; }
- int fun2(int arg1, int arg2)
- { return arg1 + arg2; }
- ]],[[
- int res3 = c99_vmacro3(1, 2, 3);
- int res2 = c99_vmacro2(1, 2);
- ]])
- ],[
- curl_cv_variadic_macros_c99="yes"
- ],[
- curl_cv_variadic_macros_c99="no"
- ])
- ])
- case "$curl_cv_variadic_macros_c99" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_VARIADIC_MACROS_C99, 1,
- [Define to 1 if compiler supports C99 variadic macro style.])
- ;;
- esac
- AC_CACHE_CHECK([for compiler support of old gcc variadic macro style],
- [curl_cv_variadic_macros_gcc], [
- AC_COMPILE_IFELSE([
- AC_LANG_PROGRAM([[
-#define gcc_vmacro3(first, args...) fun3(first, args)
-#define gcc_vmacro2(first, args...) fun2(first, args)
- int fun3(int arg1, int arg2, int arg3);
- int fun2(int arg1, int arg2);
- int fun3(int arg1, int arg2, int arg3)
- { return arg1 + arg2 + arg3; }
- int fun2(int arg1, int arg2)
- { return arg1 + arg2; }
- ]],[[
- int res3 = gcc_vmacro3(1, 2, 3);
- int res2 = gcc_vmacro2(1, 2);
- ]])
- ],[
- curl_cv_variadic_macros_gcc="yes"
- ],[
- curl_cv_variadic_macros_gcc="no"
- ])
- ])
- case "$curl_cv_variadic_macros_gcc" in
- yes)
- AC_DEFINE_UNQUOTED(HAVE_VARIADIC_MACROS_GCC, 1,
- [Define to 1 if compiler supports old gcc variadic macro style.])
- ;;
- esac
-])
-
-
dnl CURL_CHECK_CA_BUNDLE
dnl -------------------------------------------------
dnl Check if a default ca-bundle should be used
@@ -1611,17 +1372,15 @@ dnl -------------------------------------------------
dnl Check if curl's WIN32 large file will be used
AC_DEFUN([CURL_CHECK_WIN32_LARGEFILE], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINDOWS])dnl
+ AC_REQUIRE([CURL_CHECK_NATIVE_WINDOWS])dnl
AC_MSG_CHECKING([whether build target supports WIN32 file API])
curl_win32_file_api="no"
- if test "$curl_cv_header_windows_h" = "yes"; then
+ if test "$curl_cv_native_windows" = "yes"; then
if test x"$enable_largefile" != "xno"; then
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
]],[[
-#if !defined(_WIN32_WCE) && \
- (defined(__MINGW32__) || \
- (defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))))
+#if !defined(_WIN32_WCE) && (defined(__MINGW32__) || defined(_MSC_VER))
int dummy=1;
#else
WIN32 large file API not supported.
@@ -1670,10 +1429,10 @@ dnl -------------------------------------------------
dnl Check if curl's WIN32 crypto lib can be used
AC_DEFUN([CURL_CHECK_WIN32_CRYPTO], [
- AC_REQUIRE([CURL_CHECK_HEADER_WINDOWS])dnl
+ AC_REQUIRE([CURL_CHECK_NATIVE_WINDOWS])dnl
AC_MSG_CHECKING([whether build target supports WIN32 crypto API])
curl_win32_crypto_api="no"
- if test "$curl_cv_header_windows_h" = "yes"; then
+ if test "$curl_cv_native_windows" = "yes"; then
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
#undef inline
diff --git a/appveyor.sh b/appveyor.sh
new file mode 100644
index 000000000..87c9d572a
--- /dev/null
+++ b/appveyor.sh
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# shellcheck disable=SC3040,SC2039
+set -eux; [ -n "${BASH:-}${ZSH_NAME:-}" ] && set -o pipefail
+
+# build
+
+if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2022' ]; then
+ openssl_root_win='C:/OpenSSL-v30-Win64'
+else
+ openssl_root_win='C:/OpenSSL-v111-Win64'
+fi
+openssl_root="$(cygpath -u "${openssl_root_win}")"
+
+if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
+ options=''
+ [[ "${TARGET:-}" = *'ARM64'* ]] && SKIP_RUN='ARM64 architecture'
+ [ "${OPENSSL}" = 'ON' ] && options+=" -DOPENSSL_ROOT_DIR=${openssl_root_win}"
+ [ "${OPENSSL}" = 'ON' ] && options+=" -DOPENSSL_ROOT_DIR=${openssl_root_win}"
+ [ "${PRJ_CFG}" = 'Debug' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
+ [ "${PRJ_CFG}" = 'Release' ] && options+=' -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
+ [[ "${PRJ_GEN}" = *'Visual Studio'* ]] && options+=' -DCMAKE_VS_GLOBALS=TrackFileAccess=false'
+ # Fails to run without this run due to missing MSVCR90.dll
+ [ "${PRJ_GEN}" = 'Visual Studio 9 2008' ] && options+=' -DCURL_STATIC_CRT=ON'
+ # shellcheck disable=SC2086
+ cmake -B _bld "-G${PRJ_GEN}" ${TARGET:-} ${options} \
+ "-DCURL_USE_OPENSSL=${OPENSSL}" \
+ "-DCURL_USE_SCHANNEL=${SCHANNEL}" \
+ "-DHTTP_ONLY=${HTTP_ONLY}" \
+ "-DBUILD_SHARED_LIBS=${SHARED}" \
+ "-DBUILD_TESTING=${TESTING}" \
+ "-DENABLE_WEBSOCKETS=${WEBSOCKETS:-}" \
+ "-DCMAKE_UNITY_BUILD=${UNITY}" \
+ '-DCURL_WERROR=ON' \
+ "-DENABLE_DEBUG=${DEBUG}" \
+ "-DENABLE_UNICODE=${ENABLE_UNICODE}" \
+ '-DCMAKE_INSTALL_PREFIX=C:/CURL' \
+ "-DCMAKE_BUILD_TYPE=${PRJ_CFG}"
+ # shellcheck disable=SC2086
+ cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --clean-first -- ${BUILD_OPT:-}
+ if [ "${SHARED}" = 'ON' ]; then
+ cp -f -p _bld/lib/*.dll _bld/src/
+ fi
+ if [ "${OPENSSL}" = 'ON' ]; then
+ cp -f -p "${openssl_root}"/*.dll _bld/src/
+ fi
+ curl='_bld/src/curl.exe'
+elif [ "${BUILD_SYSTEM}" = 'VisualStudioSolution' ]; then
+ (
+ cd projects
+ ./generate.bat "${VC_VERSION}"
+ msbuild.exe -maxcpucount "-property:Configuration=${PRJ_CFG}" "Windows/${VC_VERSION}/curl-all.sln"
+ )
+ curl="build/Win32/${VC_VERSION}/${PRJ_CFG}/curld.exe"
+elif [ "${BUILD_SYSTEM}" = 'winbuild_vs2015' ]; then
+ ./buildconf.bat
+ (
+ cd winbuild
+ cat << EOF > _make.bat
+ call "C:/Program Files/Microsoft SDKs/Windows/v7.1/Bin/SetEnv.cmd" /x64
+ call "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/vcvarsall.bat" x86_amd64
+ nmake -f Makefile.vc mode=dll VC=14 "SSL_PATH=${openssl_root_win}" WITH_SSL=dll MACHINE=x64 DEBUG=${DEBUG} ENABLE_UNICODE=${ENABLE_UNICODE}
+EOF
+ ./_make.bat
+ rm _make.bat
+ )
+ curl="builds/libcurl-vc14-x64-${PATHPART}-dll-ssl-dll-ipv6-sspi/bin/curl.exe"
+elif [ "${BUILD_SYSTEM}" = 'winbuild_vs2017' ]; then
+ ./buildconf.bat
+ (
+ cd winbuild
+ cat << EOF > _make.bat
+ call "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvars64.bat"
+ nmake -f Makefile.vc mode=dll VC=14.10 "SSL_PATH=${openssl_root_win}" WITH_SSL=dll MACHINE=x64 DEBUG=${DEBUG} ENABLE_UNICODE=${ENABLE_UNICODE}
+EOF
+ ./_make.bat
+ rm _make.bat
+ )
+ curl="builds/libcurl-vc14.10-x64-${PATHPART}-dll-ssl-dll-ipv6-sspi/bin/curl.exe"
+elif [ "${BUILD_SYSTEM}" = 'autotools' ]; then
+ autoreconf -fi
+ (
+ mkdir _bld
+ cd _bld
+ # shellcheck disable=SC2086
+ ../configure ${CONFIG_ARGS:-}
+ make -j2 V=1
+ make -j2 V=1 examples
+ cd tests
+ make -j2 V=1
+ )
+ curl='_bld/src/curl.exe'
+fi
+
+find . -name '*.exe' -o -name '*.dll'
+if [ -z "${SKIP_RUN:-}" ]; then
+ "${curl}" --version
+else
+ echo "Skip running curl.exe. Reason: ${SKIP_RUN}"
+fi
+
+if false; then
+ for log in CMakeFiles/CMakeConfigureLog.yaml CMakeFiles/CMakeOutput.log CMakeFiles/CMakeError.log; do
+ [ -r "_bld/${log}" ] && cat "_bld/${log}"
+ done
+fi
+
+if [ "${TESTING}" = 'ON' ] && [ "${BUILD_SYSTEM}" = 'CMake' ]; then
+ cmake --build _bld --config "${PRJ_CFG}" --parallel 2 --target testdeps
+fi
+
+# test
+
+if [ "${TESTING}" = 'ON' ]; then
+ export TFLAGS=''
+ if [ -x "$(cygpath -u "${WINDIR}/System32/curl.exe")" ]; then
+ TFLAGS+=" -ac $(cygpath -u "${WINDIR}/System32/curl.exe")"
+ elif [ -x "$(cygpath -u "C:/msys64/usr/bin/curl.exe")" ]; then
+ TFLAGS+=" -ac $(cygpath -u "C:/msys64/usr/bin/curl.exe")"
+ fi
+ TFLAGS+=" ${DISABLED_TESTS:-}"
+ if [ "${BUILD_SYSTEM}" = 'CMake' ]; then
+ ls _bld/lib/*.dll >/dev/null 2>&1 && cp -f -p _bld/lib/*.dll _bld/tests/libtest/
+ cmake --build _bld --config "${PRJ_CFG}" --target test-ci
+ elif [ "${BUILD_SYSTEM}" = 'autotools' ]; then
+ (
+ cd _bld
+ make -j2 V=1 test-ci
+ )
+ else
+ (
+ TFLAGS="-a -p !flaky -r -rm ${TFLAGS}"
+ cd _bld/tests
+ ./runtests.pl
+ )
+ fi
+fi
diff --git a/appveyor.yml b/appveyor.yml
index 874bf7ce4..039e040a1 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -21,9 +21,12 @@
# SPDX-License-Identifier: curl
#
###########################################################################
+
# https://ci.appveyor.com/project/curlorg/curl/history
-# Appveyor configuration
-# https://www.appveyor.com/docs/appveyor-yml/
+# AppVeyor configuration:
+# https://www.appveyor.com/docs/appveyor-yml/
+# AppVeyor worker images:
+# https://www.appveyor.com/docs/windows-images-software/
version: 7.50.0.{build}
@@ -34,7 +37,7 @@ environment:
SHARED: 'OFF'
matrix:
# generated CMake-based Visual Studio Release builds
- - job_name: 'CMake, VS2008, Release x86, Schannel, Build-only'
+ - job_name: 'CMake, VS2008, Release, x86, Schannel, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 9 2008'
@@ -45,8 +48,7 @@ environment:
SHARED: 'ON'
TESTING: 'OFF'
DISABLED_TESTS: ''
- SKIP_RUN: 'Needs missing MSVCR90.dll'
- - job_name: 'CMake, VS2022, Release x64, OpenSSL, WebSockets, Unity, Build-only'
+ - job_name: 'CMake, VS2022, Release, x64, OpenSSL 3, WebSockets, Unity, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022'
@@ -61,7 +63,7 @@ environment:
DISABLED_TESTS: ''
WEBSOCKETS: 'ON'
UNITY: 'ON'
- - job_name: 'CMake, VS2022, Release arm64, Schannel, Static, Build-only'
+ - job_name: 'CMake, VS2022, Release, arm64, Schannel, Static, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022'
@@ -73,7 +75,7 @@ environment:
TESTING: 'OFF'
DISABLED_TESTS: ''
# generated CMake-based Visual Studio Debug builds
- - job_name: 'CMake, VS2010, Debug x64, no SSL, Static'
+ - job_name: 'CMake, VS2010, Debug, x64, no SSL, Static'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 10 2010 Win64'
@@ -82,9 +84,8 @@ environment:
ENABLE_UNICODE: 'OFF'
HTTP_ONLY: 'OFF'
TESTING: 'ON'
- DISABLED_TESTS: '!1139 !1501'
- ADD_PATH: 'C:\msys64\usr\bin'
- - job_name: 'CMake, VS2022, Debug x64, Schannel, Static, Unicode'
+ DISABLED_TESTS: '!1139 !1501 !1140 !1173 !1177 !1477'
+ - job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022'
@@ -94,9 +95,8 @@ environment:
ENABLE_UNICODE: 'ON'
HTTP_ONLY: 'OFF'
TESTING: 'ON'
- DISABLED_TESTS: '!1139 !1501'
- ADD_PATH: 'C:\msys64\usr\bin'
- - job_name: 'CMake, VS2022, Debug x64, no SSL, Static'
+ DISABLED_TESTS: '!1139 !1501 !1140 !1173 !1177 !1477'
+ - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022'
@@ -106,9 +106,8 @@ environment:
ENABLE_UNICODE: 'OFF'
HTTP_ONLY: 'OFF'
TESTING: 'ON'
- DISABLED_TESTS: '!1139 !1501'
- ADD_PATH: 'C:\msys64\usr\bin'
- - job_name: 'CMake, VS2022, Debug x64, no SSL, Static, HTTP only'
+ DISABLED_TESTS: '!1139 !1501 !1140 !1173 !1177 !1477'
+ - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, HTTP only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'Visual Studio 17 2022'
@@ -118,10 +117,9 @@ environment:
ENABLE_UNICODE: 'OFF'
HTTP_ONLY: 'ON'
TESTING: 'ON'
- DISABLED_TESTS: '!1139 !1501'
- ADD_PATH: 'C:\msys64\usr\bin'
+ DISABLED_TESTS: '!1139 !1501 !1140 !1173 !1177 !1477'
# generated CMake-based MSYS Makefiles builds (mingw cross-compiling)
- - job_name: 'CMake, mingw-w64, gcc 13, Debug x64, Schannel, Static, Unicode, Unity'
+ - job_name: 'CMake, mingw-w64, gcc 13, Debug, x64, Schannel, Static, Unicode, Unity'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: CMake
PRJ_GEN: 'MSYS Makefiles'
@@ -130,12 +128,12 @@ environment:
ENABLE_UNICODE: 'ON'
HTTP_ONLY: 'OFF'
TESTING: 'ON'
- DISABLED_TESTS: '!1086 !1139 !1451 !1501'
- ADD_PATH: 'C:\msys64\mingw64\bin;C:\msys64\usr\bin'
+ DISABLED_TESTS: '!1086 !1139 !1451 !1501 !1140 !1173 !1177 !1477'
+ ADD_PATH: 'C:/msys64/mingw64/bin'
MSYS2_ARG_CONV_EXCL: '/*'
BUILD_OPT: -k
UNITY: 'ON'
- - job_name: 'CMake, mingw-w64, gcc 7, Debug x64, Schannel, Static, Unicode'
+ - job_name: 'CMake, mingw-w64, gcc 7, Debug, x64, Schannel, Static, Unicode'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: CMake
PRJ_GEN: 'MSYS Makefiles'
@@ -144,11 +142,11 @@ environment:
ENABLE_UNICODE: 'ON'
HTTP_ONLY: 'OFF'
TESTING: 'ON'
- DISABLED_TESTS: '!1086 !1139 !1451 !1501'
- ADD_PATH: 'C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;C:\msys64\usr\bin'
+ DISABLED_TESTS: '!1086 !1139 !1451 !1501 !1140 !1173 !1177 !1477'
+ ADD_PATH: 'C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin'
MSYS2_ARG_CONV_EXCL: '/*'
BUILD_OPT: -k
- - job_name: 'CMake, mingw-w64, gcc 9, Debug x64, Schannel, Static, Unity'
+ - job_name: 'CMake, mingw-w64, gcc 9, Debug, x64, Schannel, Static, Unity'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: CMake
PRJ_GEN: 'MSYS Makefiles'
@@ -157,12 +155,13 @@ environment:
ENABLE_UNICODE: 'OFF'
HTTP_ONLY: 'OFF'
TESTING: 'ON'
- DISABLED_TESTS: '!1086 !1139 !1451 !1501'
- ADD_PATH: 'C:\msys64\mingw64\bin;C:\msys64\usr\bin'
+ # test 286 disabled due to https://github.com/curl/curl/issues/12040
+ DISABLED_TESTS: '~286 !1086 !1139 !1451 !1501 !1140 !1173 !1177 !1477'
+ ADD_PATH: 'C:/msys64/mingw64/bin'
MSYS2_ARG_CONV_EXCL: '/*'
BUILD_OPT: -k
UNITY: 'ON'
- - job_name: 'CMake, mingw-w64, gcc 6, Debug x86, Schannel, Static'
+ - job_name: 'CMake, mingw-w64, gcc 6, Debug, x86, Schannel, Static'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: CMake
PRJ_GEN: 'MSYS Makefiles'
@@ -171,61 +170,61 @@ environment:
ENABLE_UNICODE: 'OFF'
HTTP_ONLY: 'OFF'
TESTING: 'ON'
- DISABLED_TESTS: '!1086 !1139 !1451 !1501'
- ADD_PATH: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin;C:\msys64\usr\bin'
+ DISABLED_TESTS: '!1086 !1139 !1451 !1501 !1140 !1173 !1177 !1477'
+ ADD_PATH: 'C:/mingw-w64/i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32/bin'
MSYS2_ARG_CONV_EXCL: '/*'
BUILD_OPT: -k
# winbuild-based builds
- - job_name: 'winbuild, VS2015, Debug, x64, Build-only'
+ - job_name: 'winbuild, VS2015, Debug, x64, OpenSSL 1.1.1, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: winbuild_vs2015
DEBUG: 'yes'
PATHPART: debug
TESTING: 'OFF'
ENABLE_UNICODE: 'no'
- - job_name: 'winbuild, VS2015, Release, x64, Build-only'
+ - job_name: 'winbuild, VS2015, Release, x64, OpenSSL 1.1.1, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: winbuild_vs2015
DEBUG: 'no'
PATHPART: release
TESTING: 'OFF'
ENABLE_UNICODE: 'no'
- - job_name: 'winbuild, VS2017, Debug, x64, Build-only'
+ - job_name: 'winbuild, VS2017, Debug, x64, OpenSSL 1.1.1, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: winbuild_vs2017
DEBUG: 'yes'
PATHPART: debug
TESTING: 'OFF'
ENABLE_UNICODE: 'no'
- - job_name: 'winbuild, VS2017, Release, x64, Build-only'
+ - job_name: 'winbuild, VS2017, Release, x64, OpenSSL 1.1.1, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: winbuild_vs2017
DEBUG: 'no'
PATHPART: release
TESTING: 'OFF'
ENABLE_UNICODE: 'no'
- - job_name: 'winbuild, VS2015, Debug, x64, Unicode, Build-only'
+ - job_name: 'winbuild, VS2015, Debug, x64, OpenSSL 1.1.1, Unicode, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: winbuild_vs2015
DEBUG: 'yes'
PATHPART: debug
TESTING: 'OFF'
ENABLE_UNICODE: 'yes'
- - job_name: 'winbuild, VS2015, Release, x64, Unicode, Build-only'
+ - job_name: 'winbuild, VS2015, Release, x64, OpenSSL 1.1.1, Unicode, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015'
BUILD_SYSTEM: winbuild_vs2015
DEBUG: 'no'
PATHPART: release
TESTING: 'OFF'
ENABLE_UNICODE: 'yes'
- - job_name: 'winbuild, VS2017, Debug, x64, Unicode, Build-only'
+ - job_name: 'winbuild, VS2017, Debug, x64, OpenSSL 1.1.1, Unicode, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: winbuild_vs2017
DEBUG: 'yes'
PATHPART: debug
TESTING: 'OFF'
ENABLE_UNICODE: 'yes'
- - job_name: 'winbuild, VS2017, Release, x64, Unicode, Build-only'
+ - job_name: 'winbuild, VS2017, Release, x64, OpenSSL 1.1.1, Unicode, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: winbuild_vs2017
DEBUG: 'no'
@@ -233,7 +232,7 @@ environment:
TESTING: 'OFF'
ENABLE_UNICODE: 'yes'
# generated VisualStudioSolution-based builds
- - job_name: 'VisualStudioSolution, VS2017, Debug, x86, Build-only'
+ - job_name: 'VisualStudioSolution, VS2017, Debug, x86, Schannel, Build-only'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: VisualStudioSolution
PRJ_CFG: 'DLL Debug - DLL Windows SSPI - DLL WinIDN'
@@ -245,168 +244,42 @@ environment:
BUILD_SYSTEM: autotools
TESTING: 'ON'
DISABLED_TESTS: '!19 !1233'
- ADD_PATH: 'C:\msys64\usr\bin'
- CONFIG_ARGS: '--enable-debug --enable-werror --disable-threaded-resolver --disable-proxy --without-ssl --enable-websockets'
+ CONFIG_ARGS: '--enable-debug --enable-werror --disable-threaded-resolver --disable-proxy --without-ssl --enable-websockets --without-libpsl'
- job_name: 'autotools, msys2, Debug, x86_64, no SSL'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: autotools
TESTING: 'ON'
DISABLED_TESTS: '!19 !504 !704 !705 !1233'
- ADD_PATH: 'C:\msys64\usr\bin'
- CONFIG_ARGS: '--enable-debug --enable-werror --disable-threaded-resolver --without-ssl --enable-websockets'
+ CONFIG_ARGS: '--enable-debug --enable-werror --disable-threaded-resolver --without-ssl --enable-websockets --without-libpsl'
- job_name: 'autotools, msys2, Release, x86_64, no SSL'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017'
BUILD_SYSTEM: autotools
TESTING: 'ON'
DISABLED_TESTS: '!19 !504 !704 !705 !1233'
- ADD_PATH: 'C:\msys64\usr\bin'
- CONFIG_ARGS: '--enable-warnings --enable-werror --without-ssl --enable-websockets'
+ CONFIG_ARGS: '--enable-warnings --enable-werror --without-ssl --enable-websockets --without-libpsl'
# autotools-based Cygwin build
- job_name: 'autotools, cygwin, Debug, x86_64, no SSL'
APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022'
BUILD_SYSTEM: autotools
TESTING: 'ON'
DISABLED_TESTS: ''
- ADD_PATH: 'C:\cygwin64\bin'
- CONFIG_ARGS: '--enable-debug --enable-werror --disable-threaded-resolver --without-ssl --enable-websockets'
- POSIX_PATH_PREFIX: '/cygdrive'
+ ADD_SHELL: 'C:/cygwin64/bin'
+ CONFIG_ARGS: '--enable-debug --enable-werror --disable-threaded-resolver --without-ssl --enable-websockets --without-libpsl'
install:
- ps: |
- if($env:ADD_PATH -ne $null) {
- $env:PATH = "$env:ADD_PATH;$env:PATH"
- }
-
-build_script:
- - ps: |
- function Pull-BatchFile-Env {
- param([string]$Path, [string]$Parameters)
- $tempFile = [IO.Path]::GetTempFileName()
- cmd.exe /c " `"$Path`" $Parameters && set " > $tempFile
- Get-Content $tempFile | ForEach-Object { if($_ -match '^(.*?)=(.*)$') { Set-Content "env:\$($matches[1])" $matches[2] } }
- Remove-Item $tempFile
- }
-
- $ErrorActionPreference = 'Stop'
-
- $openssl_root = 'C:\OpenSSL-v111-Win64'
-
- if($env:BUILD_SYSTEM -eq 'CMake') {
-
- $options = @('-DCURL_WERROR=ON')
- $options += "-G$env:PRJ_GEN"
- if($env:TARGET -ne $null) {
- $options += "$env:TARGET"
- if($env:TARGET.Contains('ARM64')) {
- $env:SKIP_RUN = 'ARM64 architecture'
- }
- }
- $options += "-DCURL_USE_OPENSSL=$env:OPENSSL"
- if($env:OPENSSL -eq 'ON') {
- $options += "-DOPENSSL_ROOT_DIR=$openssl_root"
- }
- $options += "-DCURL_USE_SCHANNEL=$env:SCHANNEL"
- $options += "-DHTTP_ONLY=$env:HTTP_ONLY"
- $options += "-DBUILD_SHARED_LIBS=$env:SHARED"
- $options += "-DBUILD_TESTING=$env:TESTING"
- $options += "-DENABLE_WEBSOCKETS=$env:WEBSOCKETS"
- $options += "-DCMAKE_UNITY_BUILD=$env:UNITY"
- $options += "-DENABLE_DEBUG=$env:DEBUG"
- $options += "-DENABLE_UNICODE=$env:ENABLE_UNICODE"
- $options += '-DCMAKE_INSTALL_PREFIX=C:/CURL'
- $options += "-DCMAKE_BUILD_TYPE=$env:PRJ_CFG"
- if($env:PRJ_CFG -eq 'Debug') {
- $options += '-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG='
- }
- elseif ($env:PRJ_CFG -eq 'Release') {
- $options += '-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE='
- }
- if($env:PRJ_GEN.Contains('Visual Studio')) {
- $options += '-DCMAKE_VS_GLOBALS=TrackFileAccess=false'
- }
-
- cmake --version
- Write-Host 'CMake options:' $options
- cmake . $options
- cmake --build . --config $env:PRJ_CFG --parallel 2 --clean-first -- $env:BUILD_OPT
- if($env:SHARED -eq 'ON') {
- Copy-Item -Path 'C:\Projects\curl\lib\*.dll' -Destination 'C:\projects\curl\src'
- Copy-Item -Path 'C:\Projects\curl\lib\*.dll' -Destination 'C:\projects\curl\tests\libtest'
- }
- if($env:OPENSSL -eq 'ON') {
- Copy-Item -Path "$openssl_root\*.dll" -Destination 'C:\projects\curl\src'
- }
- $curl = '.\src\curl.exe'
- }
- elseif($env:BUILD_SYSTEM -eq 'VisualStudioSolution') {
- cd projects
- .\generate.bat $env:VC_VERSION
- msbuild.exe -maxcpucount "-property:Configuration=$env:PRJ_CFG" "Windows\$env:VC_VERSION\curl-all.sln"
- $curl = "..\build\Win32\$env:VC_VERSION\$env:PRJ_CFG\curld.exe"
- }
- elseif($env:BUILD_SYSTEM -eq 'winbuild_vs2015') {
- .\buildconf.bat
- cd winbuild
- Pull-BatchFile-Env 'C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd' /x64
- Pull-BatchFile-Env 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat' x86_amd64
- nmake /nologo /f Makefile.vc mode=dll VC=14 "SSL_PATH=$openssl_root" WITH_SSL=dll MACHINE=x64 DEBUG=$env:DEBUG ENABLE_UNICODE=$env:ENABLE_UNICODE
- $curl = "..\builds\libcurl-vc14-x64-$env:PATHPART-dll-ssl-dll-ipv6-sspi\bin\curl.exe"
- }
- elseif($env:BUILD_SYSTEM -eq 'winbuild_vs2017') {
- .\buildconf.bat
- cd winbuild
- Pull-BatchFile-Env 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat'
- nmake /nologo /f Makefile.vc mode=dll VC=14.10 "SSL_PATH=$openssl_root" WITH_SSL=dll MACHINE=x64 DEBUG=$env:DEBUG ENABLE_UNICODE=$env:ENABLE_UNICODE
- $curl = "..\builds\libcurl-vc14.10-x64-$env:PATHPART-dll-ssl-dll-ipv6-sspi\bin\curl.exe"
- }
- elseif($env:BUILD_SYSTEM -eq 'autotools') {
- & bash -e -c "cd $env:POSIX_PATH_PREFIX/c/projects/curl && autoreconf -fi 2>&1 && ./configure $env:CONFIG_ARGS 2>&1 && make V=1 && make V=1 examples && cd tests && make V=1"
- $curl = '.\src\curl.exe'
- }
-
- Get-ChildItem -Path C:\projects\curl -Include ('*.exe', '*.dll') -Recurse -Name
- if($env:SKIP_RUN -eq $null) {
- cmd.exe /c "`"$curl`" -V 2>&1"
- if(-not $?) {
- Write-Host "Error running curl: '$curl':" ("0x" + $LastExitCode.ToString("X"))
- exit 1
- }
+ if($env:ADD_SHELL -ne $null) {
+ $env:PATH = "$env:ADD_SHELL;$env:PATH"
}
else {
- Write-Host "Skip running curl.exe. Reason: $env:SKIP_RUN"
+ $env:PATH = "C:/msys64/usr/bin;$env:PATH"
}
-
- if($false) {
- if(Test-Path CMakeFiles/CMakeConfigureLog.yaml) { cat CMakeFiles/CMakeConfigureLog.yaml }
- if(Test-Path CMakeFiles/CMakeOutput.log) { cat CMakeFiles/CMakeOutput.log }
- if(Test-Path CMakeFiles/CMakeError.log) { cat CMakeFiles/CMakeError.log }
- if(Test-Path config.log) { cat config.log }
- }
-
- if($env:TESTING -eq 'ON' -and $env:BUILD_SYSTEM -eq 'CMake') {
- cmake --build . --config $env:PRJ_CFG --parallel 2 --target testdeps
+ if($env:ADD_PATH -ne $null) {
+ $env:PATH = "$env:ADD_PATH;$env:PATH"
}
-test_script:
- - ps: |
- if(Test-Path 'C:/msys64/usr/bin/curl.exe') {
- $acurl="-ac $env:POSIX_PATH_PREFIX/c/msys64/usr/bin/curl.exe"
- }
- if(Test-Path 'C:/Windows/System32/curl.exe') {
- $acurl="-ac $env:POSIX_PATH_PREFIX/c/Windows/System32/curl.exe"
- }
- if($env:TESTING -eq 'ON') {
- if($env:BUILD_SYSTEM -eq 'CMake') {
- $env:TFLAGS="$acurl $env:DISABLED_TESTS"
- cmake --build . --config $env:PRJ_CFG --target test-ci
- }
- elseif($env:BUILD_SYSTEM -eq 'autotools') {
- & bash -e -c "cd $env:POSIX_PATH_PREFIX/c/projects/curl && make V=1 TFLAGS='$acurl $env:DISABLED_TESTS' test-ci"
- }
- else {
- & bash -e -c "cd $env:POSIX_PATH_PREFIX/c/projects/curl/tests && ./runtests.pl -a -p !flaky -r -rm $acurl $env:DISABLED_TESTS"
- }
- }
+build_script:
+ - cmd: sh -c ./appveyor.sh
clone_depth: 10
diff --git a/configure b/configure
index 04d1de146..da9f3b70f 100755
--- a/configure
+++ b/configure
@@ -930,9 +930,13 @@ FISH_FUNCTIONS_DIR
ZSH_FUNCTIONS_DIR
USE_MSH3
USE_QUICHE
+USE_OPENSSL_H3
+USE_NGTCP2_H3
USE_NGHTTP3
+USE_OPENSSL_QUIC
USE_NGTCP2_CRYPTO_WOLFSSL
USE_NGTCP2_CRYPTO_GNUTLS
+USE_NGTCP2_CRYPTO_BORINGSSL
USE_NGTCP2_CRYPTO_QUICTLS
USE_NGTCP2
USE_NGHTTP2
@@ -958,6 +962,7 @@ USE_WOLFSSL
USE_MBEDTLS
HAVE_GNUTLS_SRP
USE_GNUTLS
+HAVE_OPENSSL_QUIC
HAVE_OPENSSL_SRP
RANDOM_FILE
SSL_LIBS
@@ -1000,13 +1005,13 @@ HAVE_WINDRES_TRUE
USE_WIN32_CRYPTO
USE_WIN32_SMALL_FILES
USE_WIN32_LARGE_FILES
-DOING_NATIVE_WINDOWS_FALSE
-DOING_NATIVE_WINDOWS_TRUE
BUILD_UNITTESTS_FALSE
BUILD_UNITTESTS_TRUE
CURLDEBUG_FALSE
CURLDEBUG_TRUE
CURL_CFLAG_EXTRAS
+DOING_NATIVE_WINDOWS_FALSE
+DOING_NATIVE_WINDOWS_TRUE
USE_EXPLICIT_LIB_DEPS_FALSE
USE_EXPLICIT_LIB_DEPS_TRUE
REQUIRE_LIB_DEPS
@@ -1244,6 +1249,7 @@ with_winidn
with_libidn2
with_nghttp2
with_ngtcp2
+with_openssl_quic
with_nghttp3
with_quiche
with_msh3
@@ -2140,7 +2146,7 @@ Optional Packages:
--without-ca-path Don't use a default CA path
--with-ca-fallback Use the built in CA store of the SSL library
--without-ca-fallback Don't use the built in CA store of the SSL library
- --without-libpsl disable support for libpsl cookie checking
+ --without-libpsl disable support for libpsl
--without-libgsasl disable libgsasl support for SCRAM
--with-libssh2=PATH Where to look for libssh2, PATH points to the
libssh2 installation; when possible, set the
@@ -2169,6 +2175,8 @@ Optional Packages:
--without-nghttp2 Disable nghttp2 usage
--with-ngtcp2=PATH Enable ngtcp2 usage
--without-ngtcp2 Disable ngtcp2 usage
+ --with-openssl-quic Enable OpenSSL QUIC usage
+ --without-openssl-quic Disable OpenSSL QUIC usage
--with-nghttp3=PATH Enable nghttp3 usage
--without-nghttp3 Disable nghttp3 usage
--with-quiche=PATH Enable quiche usage
@@ -6677,8 +6685,8 @@ curl_headers_msg="enabled (--disable-headers-api)"
curl_ws_msg="no (--enable-websockets)"
ssl_backends=
curl_h1_msg="enabled (internal)"
- curl_h2_msg="no (--with-nghttp2, --with-hyper)"
- curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-msh3)"
+ curl_h2_msg="no (--with-nghttp2)"
+ curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-openssl-quic, --with-msh3)"
enable_altsvc="yes"
hsts="yes"
@@ -7511,7 +7519,7 @@ printf "%s\n" "$ac_cv_path_EGREP" >&6; }
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if OS is AIX (to define _ALL_SOURCE)" >&5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if OS is AIX (to define _ALL_SOURCE)" >&5
printf %s "checking if OS is AIX (to define _ALL_SOURCE)... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -17684,7 +17692,11 @@ rm -f conftest.err conftest.i conftest.$ac_ext
if test "$curl_cv_have_def___INTEL_COMPILER" = "yes"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler version" >&5
+printf %s "checking compiler version... " >&6; }
compiler_num="$curl_cv_def___INTEL_COMPILER"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Intel C '$compiler_num'" >&5
+printf "%s\n" "Intel C '$compiler_num'" >&6; }
OLDCPPFLAGS=$CPPFLAGS
# CPPPFLAG comes from CURL_CPP_P
@@ -17855,18 +17867,41 @@ printf "%s\n" "yes" >&6; }
printf "%s\n" "no" >&6; }
compiler_id="CLANG"
fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler version" >&5
+printf %s "checking compiler version... " >&6; }
fullclangver=`$CC -v 2>&1 | grep version`
+ if echo $fullclangver | grep 'Apple' >/dev/null; then
+ appleclang=1
+ else
+ appleclang=0
+ fi
clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \([0-9]*\.[0-9]*\).*)/\1/'`
if test -z "$clangver"; then
- if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then
- clangver="3.7"
- else
- clangver=`echo $fullclangver | "$SED" 's/.*version \([0-9]*\.[0-9]*\).*/\1/'`
- fi
+ clangver=`echo $fullclangver | "$SED" 's/.*version \([0-9]*\.[0-9]*\).*/\1/'`
+ oldapple=0
+ else
+ oldapple=1
fi
clangvhi=`echo $clangver | cut -d . -f1`
clangvlo=`echo $clangver | cut -d . -f2`
compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null`
+ if test "$appleclang" = '1' && test "$oldapple" = '0'; then
+ if test "$compiler_num" -ge '1300'; then compiler_num='1200'
+ elif test "$compiler_num" -ge '1205'; then compiler_num='1101'
+ elif test "$compiler_num" -ge '1204'; then compiler_num='1000'
+ elif test "$compiler_num" -ge '1107'; then compiler_num='900'
+ elif test "$compiler_num" -ge '1103'; then compiler_num='800'
+ elif test "$compiler_num" -ge '1003'; then compiler_num='700'
+ elif test "$compiler_num" -ge '1001'; then compiler_num='600'
+ elif test "$compiler_num" -ge '904'; then compiler_num='500'
+ elif test "$compiler_num" -ge '902'; then compiler_num='400'
+ elif test "$compiler_num" -ge '803'; then compiler_num='309'
+ elif test "$compiler_num" -ge '703'; then compiler_num='308'
+ else compiler_num='307'
+ fi
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: clang '$compiler_num' (raw: '$fullclangver' / '$clangver')" >&5
+printf "%s\n" "clang '$compiler_num' (raw: '$fullclangver' / '$clangver')" >&6; }
flags_dbg_yes="-g"
flags_opt_all="-O -O0 -O1 -O2 -Os -O3 -O4"
flags_opt_yes="-O2"
@@ -17929,120 +17964,23 @@ rm -f conftest.err conftest.i conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
compiler_id="GNU_C"
- gccver=`$CC -dumpversion`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking compiler version" >&5
+printf %s "checking compiler version... " >&6; }
+ # strip '-suffix' parts, e.g. Ubuntu Windows cross-gcc returns '10-win32'
+ gccver=`$CC -dumpversion | sed -E 's/-.+$//'`
gccvhi=`echo $gccver | cut -d . -f1`
- gccvlo=`echo $gccver | cut -d . -f2`
+ if echo $gccver | grep -F '.' >/dev/null; then
+ gccvlo=`echo $gccver | cut -d . -f2`
+ else
+ gccvlo="0"
+ fi
compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: gcc '$compiler_num' (raw: '$gccver')" >&5
+printf "%s\n" "gcc '$compiler_num' (raw: '$gccver')" >&6; }
flags_dbg_yes="-g"
flags_opt_all="-O -O0 -O1 -O2 -O3 -Os -Og -Ofast"
flags_opt_yes="-O2"
flags_opt_off="-O0"
-
- OLDCPPFLAGS=$CPPFLAGS
- # CPPPFLAG comes from CURL_CPP_P
- CPPFLAGS="$CPPFLAGS $CPPPFLAG"
- if test -z "$SED"; then
- as_fn_error $? "SED not set. Cannot continue without SED being set." "$LINENO" 5
- fi
- if test -z "$GREP"; then
- as_fn_error $? "GREP not set. Cannot continue without GREP being set." "$LINENO" 5
- fi
-
- tmp_exp=""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#ifdef _WIN32
-CURL_DEF_TOKEN _WIN32
-#endif
-
-
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"
-then :
-
- tmp_exp=`eval "$ac_cpp conftest.$ac_ext" 2>/dev/null | \
- "$GREP" CURL_DEF_TOKEN 2>/dev/null | \
- "$SED" 's/.*CURL_DEF_TOKEN[ ][ ]*//' 2>/dev/null | \
- "$SED" 's/["][ ]*["]//g' 2>/dev/null`
- if test -z "$tmp_exp" || test "$tmp_exp" = "_WIN32"; then
- tmp_exp=""
- fi
-
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
- if test -z "$tmp_exp"; then
- curl_cv_have_def__WIN32=no
-
- else
- curl_cv_have_def__WIN32=yes
- curl_cv_def__WIN32=$tmp_exp
-
- fi
- CPPFLAGS=$OLDCPPFLAGS
-
- else
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
-printf "%s\n" "no" >&6; }
- fi
-
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler is LCC" >&5
-printf %s "checking if compiler is LCC... " >&6; }
-
- OLDCPPFLAGS=$CPPFLAGS
- # CPPPFLAG comes from CURL_CPP_P
- CPPFLAGS="$CPPFLAGS $CPPPFLAG"
- if test -z "$SED"; then
- as_fn_error $? "SED not set. Cannot continue without SED being set." "$LINENO" 5
- fi
- if test -z "$GREP"; then
- as_fn_error $? "GREP not set. Cannot continue without GREP being set." "$LINENO" 5
- fi
-
- tmp_exp=""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#ifdef __LCC__
-CURL_DEF_TOKEN __LCC__
-#endif
-
-
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"
-then :
-
- tmp_exp=`eval "$ac_cpp conftest.$ac_ext" 2>/dev/null | \
- "$GREP" CURL_DEF_TOKEN 2>/dev/null | \
- "$SED" 's/.*CURL_DEF_TOKEN[ ][ ]*//' 2>/dev/null | \
- "$SED" 's/["][ ]*["]//g' 2>/dev/null`
- if test -z "$tmp_exp" || test "$tmp_exp" = "__LCC__"; then
- tmp_exp=""
- fi
-
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
- if test -z "$tmp_exp"; then
- curl_cv_have_def___LCC__=no
-
- else
- curl_cv_have_def___LCC__=yes
- curl_cv_def___LCC__=$tmp_exp
-
- fi
- CPPFLAGS=$OLDCPPFLAGS
-
- if test "$curl_cv_have_def___LCC__" = "yes"; then
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-printf "%s\n" "yes" >&6; }
- compiler_id="LCC"
- flags_dbg_yes="-g"
- flags_opt_all=""
- flags_opt_yes=""
- flags_opt_off=""
else
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
@@ -18449,6 +18387,57 @@ _EOF
fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build target is a native Windows one" >&5
+printf %s "checking whether build target is a native Windows one... " >&6; }
+if test ${curl_cv_native_windows+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+
+int main (void)
+{
+
+#ifdef _WIN32
+ int dummy=1;
+#else
+ Not a native Windows build target.
+#endif
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ curl_cv_native_windows="yes"
+
+else $as_nop
+
+ curl_cv_native_windows="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_native_windows" >&5
+printf "%s\n" "$curl_cv_native_windows" >&6; }
+ if test "x$curl_cv_native_windows" = xyes; then
+ DOING_NATIVE_WINDOWS_TRUE=
+ DOING_NATIVE_WINDOWS_FALSE='#'
+else
+ DOING_NATIVE_WINDOWS_TRUE='#'
+ DOING_NATIVE_WINDOWS_FALSE=
+fi
+
+
+
squeeze() {
_sqz_result=""
eval _sqz_input=\$$1
@@ -18519,11 +18508,6 @@ squeeze() {
tmp_CFLAGS="$tmp_CFLAGS"
;;
#
- LCC)
- #
- tmp_CFLAGS="$tmp_CFLAGS -n"
- ;;
- #
SGI_MIPS_C)
#
tmp_CFLAGS="$tmp_CFLAGS"
@@ -19233,7 +19217,7 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
ac_var_added_warnings=""
- for warning in no-multichar sign-compare; do
+ for warning in sign-compare; do
ac_var_match_word="no"
for word1 in $CFLAGS; do
@@ -19251,6 +19235,7 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
squeeze tmp_CFLAGS
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-multichar"
ac_var_added_warnings=""
for warning in undef; do
@@ -19377,10 +19362,10 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
fi
#
- if test "$compiler_num" -ge "208"; then
+ if test "$compiler_num" -ge "207"; then
ac_var_added_warnings=""
- for warning in vla; do
+ for warning in address; do
ac_var_match_word="no"
for word1 in $CFLAGS; do
@@ -19398,12 +19383,9 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
squeeze tmp_CFLAGS
- fi
- #
- if test "$compiler_num" -ge "209"; then
ac_var_added_warnings=""
- for warning in shift-sign-overflow; do
+ for warning in attributes; do
ac_var_match_word="no"
for word1 in $CFLAGS; do
@@ -19421,9 +19403,6 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
squeeze tmp_CFLAGS
- fi
- #
- if test "$compiler_num" -ge "300"; then
ac_var_added_warnings=""
for warning in bad-function-cast; do
@@ -19466,6 +19445,26 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
ac_var_added_warnings=""
+ for warning in div-by-zero format-security; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
for warning in empty-body; do
ac_var_match_word="no"
@@ -19486,7 +19485,27 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
ac_var_added_warnings=""
- for warning in ignored-qualifiers; do
+ for warning in missing-field-initializers; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
+ for warning in missing-noreturn; do
ac_var_match_word="no"
for word1 in $CFLAGS; do
@@ -19506,6 +19525,47 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
ac_var_added_warnings=""
+ for warning in old-style-definition; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
+ for warning in redundant-decls; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case
+
+ ac_var_added_warnings=""
for warning in type-limits; do
ac_var_match_word="no"
@@ -19524,9 +19584,121 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
squeeze tmp_CFLAGS
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) # Not practical
+
+ ac_var_added_warnings=""
+ for warning in unreachable-code unused-parameter; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ fi
+ #
+ if test "$compiler_num" -ge "208"; then
+
+ ac_var_added_warnings=""
+ for warning in ignored-qualifiers; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
+ for warning in vla; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ fi
+ #
+ if test "$compiler_num" -ge "209"; then
+
+ ac_var_added_warnings=""
+ for warning in sign-conversion; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME
+
+ ac_var_added_warnings=""
+ for warning in shift-sign-overflow; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs
+ fi
+ #
+ if test "$compiler_num" -ge "300"; then
ac_var_added_warnings=""
- for warning in no-sign-conversion; do
+ for warning in language-extension-token; do
ac_var_match_word="no"
for word1 in $CFLAGS; do
@@ -19544,6 +19716,7 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
squeeze tmp_CFLAGS
+ tmp_CFLAGS="$tmp_CFLAGS -Wformat=2"
fi
#
if test "$compiler_num" -ge "302"; then
@@ -19567,6 +19740,26 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
squeeze tmp_CFLAGS
+
+ ac_var_added_warnings=""
+ for warning in sometimes-uninitialized; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
case $host_os in
cygwin* | mingw*)
;;
@@ -19598,6 +19791,26 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
if test "$compiler_num" -ge "304"; then
ac_var_added_warnings=""
+ for warning in header-guard; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
for warning in unused-const-variable; do
ac_var_match_word="no"
@@ -19618,6 +19831,49 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
fi
#
+ if test "$compiler_num" -ge "305"; then
+
+ ac_var_added_warnings=""
+ for warning in pragmas; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
+ for warning in unreachable-code-break; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ fi
+ #
if test "$compiler_num" -ge "306"; then
ac_var_added_warnings=""
@@ -19710,6 +19966,9 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
squeeze tmp_CFLAGS
fi
+ if test "$compiler_num" -ge "1000"; then
+ tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough" # we have silencing markup for clang 10.0 and above only
+ fi
fi
tmp_CFLAGS="$tmp_CFLAGS -Wno-pointer-bool-conversion"
;;
@@ -19724,7 +19983,6 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
GNU_C)
#
if test "$want_warnings" = "yes"; then
- tmp_CFLAGS="$tmp_CFLAGS -std=gnu89"
#
if test "x$cross_compiling" != "xyes" ||
test "$compiler_num" -ge "300"; then
@@ -20031,6 +20289,158 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS -Wstrict-aliasing=3"
fi
#
+ if test "$compiler_num" -ge "401"; then
+
+ ac_var_added_warnings=""
+ for warning in attributes; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
+ for warning in div-by-zero format-security; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
+ for warning in missing-field-initializers; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ case $host in
+ *-*-msys*)
+ ;;
+ *)
+
+ ac_var_added_warnings=""
+ for warning in missing-noreturn; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+ # Seen to clash with libtool-generated stub code
+ ;;
+ esac
+
+ ac_var_added_warnings=""
+ for warning in unreachable-code unused-parameter; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs
+
+ ac_var_added_warnings=""
+ for warning in pragmas; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
+ for warning in redundant-decls; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) # Not practical
+ fi
+ #
if test "$compiler_num" -ge "402"; then
ac_var_added_warnings=""
@@ -20057,6 +20467,26 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
if test "$compiler_num" -ge "403"; then
ac_var_added_warnings=""
+ for warning in address; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+
+ ac_var_added_warnings=""
for warning in type-limits old-style-declaration; do
ac_var_match_word="no"
@@ -20117,7 +20547,7 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
ac_var_added_warnings=""
- for warning in conversion; do
+ for warning in conversion trampolines; do
ac_var_match_word="no"
for word1 in $CFLAGS; do
@@ -20135,7 +20565,27 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
squeeze tmp_CFLAGS
- tmp_CFLAGS="$tmp_CFLAGS -Wno-sign-conversion"
+
+ ac_var_added_warnings=""
+ for warning in sign-conversion; do
+
+ ac_var_match_word="no"
+ for word1 in $CFLAGS; do
+ for word2 in -Wno-$warning -W$warning; do
+ if test "$word1" = "$word2"; then
+ ac_var_match_word="yes"
+ fi
+ done
+ done
+
+ if test "$ac_var_match_word" = "no"; then
+ ac_var_added_warnings="$ac_var_added_warnings -W$warning"
+ fi
+ done
+ tmp_CFLAGS="$tmp_CFLAGS $ac_var_added_warnings"
+ squeeze tmp_CFLAGS
+
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME
ac_var_added_warnings=""
for warning in vla; do
@@ -20160,7 +20610,7 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
fi
#
if test "$compiler_num" -ge "405"; then
- if test "$curl_cv_have_def__WIN32" = "yes"; then
+ if test "$curl_cv_native_windows" = "yes"; then
tmp_CFLAGS="$tmp_CFLAGS -Wno-pedantic-ms-format"
fi
fi
@@ -20344,9 +20794,7 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS -Wformat-overflow=2"
tmp_CFLAGS="$tmp_CFLAGS -Wformat-truncation=2"
- if test "$compiler_num" -lt "1200"; then
- tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough=4"
- fi
+ tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough"
fi
#
if test "$compiler_num" -ge "1000"; then
@@ -20448,13 +20896,6 @@ printf "%s\n" "$as_me: WARNING: compiler options rejected: $tmp_options" >&2;}
tmp_CFLAGS="$tmp_CFLAGS"
;;
#
- LCC)
- #
- if test "$want_warnings" = "yes"; then
- tmp_CFLAGS="$tmp_CFLAGS"
- fi
- ;;
- #
SGI_MIPS_C)
#
if test "$want_warnings" = "yes"; then
@@ -21099,243 +21540,10 @@ fi
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for windows.h" >&5
-printf %s "checking for windows.h... " >&6; }
-if test ${curl_cv_header_windows_h+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-
-int main (void)
-{
-
-#if defined(__CYGWIN__) || defined(__CEGCC__)
- HAVE_WINDOWS_H shall not be defined.
-#else
- int dummy=2*WINVER;
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_header_windows_h="yes"
-
-else $as_nop
-
- curl_cv_header_windows_h="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_windows_h" >&5
-printf "%s\n" "$curl_cv_header_windows_h" >&6; }
- case "$curl_cv_header_windows_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h
-
- ;;
- esac
-
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build target is a native Windows one" >&5
-printf %s "checking whether build target is a native Windows one... " >&6; }
-if test ${curl_cv_native_windows+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- if test "$curl_cv_header_windows_h" = "no"; then
- curl_cv_native_windows="no"
- else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-
-int main (void)
-{
-
-#if defined(__MINGW32__) || defined(__MINGW32CE__) || \
- (defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64)))
- int dummy=1;
-#else
- Not a native Windows build target.
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_native_windows="yes"
-
-else $as_nop
-
- curl_cv_native_windows="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- fi
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_native_windows" >&5
-printf "%s\n" "$curl_cv_native_windows" >&6; }
- if test "x$curl_cv_native_windows" = xyes; then
- DOING_NATIVE_WINDOWS_TRUE=
- DOING_NATIVE_WINDOWS_FALSE='#'
-else
- DOING_NATIVE_WINDOWS_TRUE='#'
- DOING_NATIVE_WINDOWS_FALSE=
-fi
-
-
-case X-"$curl_cv_native_windows" in
- X-yes)
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for winsock2.h" >&5
-printf %s "checking for winsock2.h... " >&6; }
-if test ${curl_cv_header_winsock2_h+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <winsock2.h>
-
-int main (void)
-{
-
-#if defined(__CYGWIN__) || defined(__CEGCC__) || defined(__MINGW32CE__)
- HAVE_WINSOCK2_H shall not be defined.
-#else
- int dummy=2*IPPROTO_ESP;
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_header_winsock2_h="yes"
-
-else $as_nop
-
- curl_cv_header_winsock2_h="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_winsock2_h" >&5
-printf "%s\n" "$curl_cv_header_winsock2_h" >&6; }
- case "$curl_cv_header_winsock2_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WINSOCK2_H 1" >>confdefs.h
-
- ;;
- esac
-
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ws2tcpip.h" >&5
-printf %s "checking for ws2tcpip.h... " >&6; }
-if test ${curl_cv_header_ws2tcpip_h+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-int main (void)
-{
-
-#if defined(__CYGWIN__) || defined(__CEGCC__) || defined(__MINGW32CE__)
- HAVE_WS2TCPIP_H shall not be defined.
-#else
- int dummy=2*IP_PKTINFO;
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_header_ws2tcpip_h="yes"
-
-else $as_nop
-
- curl_cv_header_ws2tcpip_h="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_ws2tcpip_h" >&5
-printf "%s\n" "$curl_cv_header_ws2tcpip_h" >&6; }
- case "$curl_cv_header_ws2tcpip_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WS2TCPIP_H 1" >>confdefs.h
-
- ;;
- esac
-
- ;;
- *)
- curl_cv_header_winsock2_h="no"
- curl_cv_header_ws2tcpip_h="no"
- ;;
-esac
-
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build target supports WIN32 file API" >&5
printf %s "checking whether build target supports WIN32 file API... " >&6; }
curl_win32_file_api="no"
- if test "$curl_cv_header_windows_h" = "yes"; then
+ if test "$curl_cv_native_windows" = "yes"; then
if test x"$enable_largefile" != "xno"; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -21345,9 +21553,7 @@ printf %s "checking whether build target supports WIN32 file API... " >&6; }
int main (void)
{
-#if !defined(_WIN32_WCE) && \
- (defined(__MINGW32__) || \
- (defined(_MSC_VER) && (defined(_WIN32) || defined(_WIN64))))
+#if !defined(_WIN32_WCE) && (defined(__MINGW32__) || defined(_MSC_VER))
int dummy=1;
#else
WIN32 large file API not supported.
@@ -21424,7 +21630,7 @@ printf "%s\n" "no" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build target supports WIN32 crypto API" >&5
printf %s "checking whether build target supports WIN32 crypto API... " >&6; }
curl_win32_crypto_api="no"
- if test "$curl_cv_header_windows_h" = "yes"; then
+ if test "$curl_cv_native_windows" = "yes"; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -22065,7 +22271,6 @@ then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Hyper support is experimental" >&5
printf "%s\n" "$as_me: Hyper support is experimental" >&6;}
curl_h1_msg="enabled (Hyper)"
- curl_h2_msg=$curl_h1_msg
HYPER_ENABLED=1
printf "%s\n" "#define USE_HYPER 1" >>confdefs.h
@@ -22694,10 +22899,8 @@ fi
if test "$HAVE_GETHOSTBYNAME" != "1"
then
- if test "$curl_cv_header_windows_h" = "yes"; then
- if test "$curl_cv_header_winsock2_h" = "yes"; then
- winsock_LIB="-lws2_32"
- fi
+ if test "$curl_cv_native_windows" = "yes"; then
+ winsock_LIB="-lws2_32"
if test ! -z "$winsock_LIB"; then
my_ac_save_LIBS=$LIBS
LIBS="$winsock_LIB $LIBS"
@@ -22707,15 +22910,12 @@ printf %s "checking for gethostbyname in $winsock_LIB... " >&6; }
/* end confdefs.h. */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
-#endif
int main (void)
{
@@ -22926,20 +23126,17 @@ fi
curl_includes_winsock2="\
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
+# include <winsock2.h>
#endif
/* includes end */"
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for windows.h" >&5
-printf %s "checking for windows.h... " >&6; }
-if test ${curl_cv_header_windows_h+y}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build target is a native Windows one" >&5
+printf %s "checking whether build target is a native Windows one... " >&6; }
+if test ${curl_cv_native_windows+y}
then :
printf %s "(cached) " >&6
else $as_nop
@@ -22948,19 +23145,14 @@ else $as_nop
/* end confdefs.h. */
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
int main (void)
{
-#if defined(__CYGWIN__) || defined(__CEGCC__)
- HAVE_WINDOWS_H shall not be defined.
+#ifdef _WIN32
+ int dummy=1;
#else
- int dummy=2*WINVER;
+ Not a native Windows build target.
#endif
;
@@ -22971,81 +23163,26 @@ _ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
- curl_cv_header_windows_h="yes"
+ curl_cv_native_windows="yes"
else $as_nop
- curl_cv_header_windows_h="no"
+ curl_cv_native_windows="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_windows_h" >&5
-printf "%s\n" "$curl_cv_header_windows_h" >&6; }
- case "$curl_cv_header_windows_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h
-
- ;;
- esac
-
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for winsock2.h" >&5
-printf %s "checking for winsock2.h... " >&6; }
-if test ${curl_cv_header_winsock2_h+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <winsock2.h>
-
-int main (void)
-{
-
-#if defined(__CYGWIN__) || defined(__CEGCC__) || defined(__MINGW32CE__)
- HAVE_WINSOCK2_H shall not be defined.
-#else
- int dummy=2*IPPROTO_ESP;
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_header_winsock2_h="yes"
-
-else $as_nop
-
- curl_cv_header_winsock2_h="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_native_windows" >&5
+printf "%s\n" "$curl_cv_native_windows" >&6; }
+ if test "x$curl_cv_native_windows" = xyes; then
+ DOING_NATIVE_WINDOWS_TRUE=
+ DOING_NATIVE_WINDOWS_FALSE='#'
+else
+ DOING_NATIVE_WINDOWS_TRUE='#'
+ DOING_NATIVE_WINDOWS_FALSE=
fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_winsock2_h" >&5
-printf "%s\n" "$curl_cv_header_winsock2_h" >&6; }
- case "$curl_cv_header_winsock2_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WINSOCK2_H 1" >>confdefs.h
- ;;
- esac
@@ -23089,7 +23226,7 @@ printf %s "checking for connect in libraries... " >&6; }
$curl_includes_winsock2
$curl_includes_bsdsocket
- #if !defined(HAVE_WINDOWS_H) && !defined(HAVE_PROTO_BSDSOCKET_H)
+ #if !defined(_WIN32) && !defined(HAVE_PROTO_BSDSOCKET_H)
int connect(int, void*, int);
#endif
@@ -24369,7 +24506,7 @@ else $as_nop
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -24421,7 +24558,7 @@ printf "%s\n" "#define HAVE_LBER_H 1" >>confdefs.h
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -24485,7 +24622,7 @@ else $as_nop
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -24550,7 +24687,7 @@ else $as_nop
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -24709,7 +24846,7 @@ printf %s "checking for LDAP libraries... " >&6; }
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -24939,7 +25076,7 @@ else $as_nop
/* are AF_INET6 and sockaddr_in6 available? */
#include <sys/types.h>
-#ifdef HAVE_WINSOCK2_H
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
@@ -24949,15 +25086,12 @@ else $as_nop
# include <netinet/in6.h>
#endif
#endif
-#include <stdlib.h> /* for exit() */
-main()
+
+int main(void)
{
struct sockaddr_in6 s;
(void)s;
- if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
- exit(1);
- else
- exit(0);
+ return socket(AF_INET6, SOCK_STREAM, 0) < 0;
}
@@ -24993,7 +25127,7 @@ printf %s "checking if struct sockaddr_in6 has sin6_scope_id member... " >&6; }
/* end confdefs.h. */
#include <sys/types.h>
-#ifdef HAVE_WINSOCK2_H
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
@@ -25527,10 +25661,6 @@ done
if test "x$ac_cv_header_gssapi_h" = xyes
then :
-
-printf "%s\n" "#define HAVE_GSSHEIMDAL 1" >>confdefs.h
-
-
else $as_nop
want_gss=no
@@ -25541,10 +25671,7 @@ printf "%s\n" "$as_me: WARNING: disabling GSS-API support since no header files
fi
else
-
-printf "%s\n" "#define HAVE_GSSMIT 1" >>confdefs.h
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if GSS-API headers declare GSS_C_NT_HOSTBASED_SERVICE" >&5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if GSS-API headers declare GSS_C_NT_HOSTBASED_SERVICE" >&5
printf %s "checking if GSS-API headers declare GSS_C_NT_HOSTBASED_SERVICE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -26090,7 +26217,7 @@ int main (void)
{
#if defined(AMISSL_CURRENT_VERSION) && defined(AMISSL_V3xx) && \
- defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
+ (OPENSSL_VERSION_NUMBER >= 0x30000000L) && \
defined(PROTO_AMISSL_H)
return 0;
#else
@@ -26827,6 +26954,7 @@ then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
ssl_msg="BoringSSL"
+ OPENSSL_IS_BORINGSSL=1
else $as_nop
@@ -26862,6 +26990,7 @@ then :
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
ssl_msg="AWS-LC"
+ OPENSSL_IS_BORINGSSL=1
else $as_nop
@@ -26918,7 +27047,7 @@ printf %s "checking for OpenSSL >= v3... " >&6; }
int main (void)
{
- #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+ #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
return 0;
#else
#error older than 3
@@ -26948,6 +27077,25 @@ fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
+
+ for ac_func in SSL_set_quic_use_legacy_codepoint
+do :
+ ac_fn_c_check_func "$LINENO" "SSL_set_quic_use_legacy_codepoint" "ac_cv_func_SSL_set_quic_use_legacy_codepoint"
+if test "x$ac_cv_func_SSL_set_quic_use_legacy_codepoint" = xyes
+then :
+ printf "%s\n" "#define HAVE_SSL_SET_QUIC_USE_LEGACY_CODEPOINT 1" >>confdefs.h
+ QUIC_ENABLED=yes
+fi
+
+done
+ if test "$QUIC_ENABLED" = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OpenSSL fork speaks QUIC API" >&5
+printf "%s\n" "$as_me: OpenSSL fork speaks QUIC API" >&6;}
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OpenSSL version does not speak QUIC API" >&5
+printf "%s\n" "$as_me: OpenSSL version does not speak QUIC API" >&6;}
+ fi
+
if test "$OPENSSL_ENABLED" = "1"; then
if test -n "$LIB_OPENSSL"; then
if test "x$cross_compiling" != "xyes"; then
@@ -27078,6 +27226,45 @@ fi
fi
+if test "$OPENSSL_ENABLED" = "1"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for QUIC support in OpenSSL" >&5
+printf %s "checking for QUIC support in OpenSSL... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+#include <openssl/ssl.h>
+
+int main (void)
+{
+
+ OSSL_QUIC_client_method();
+
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+printf "%s\n" "#define HAVE_OPENSSL_QUIC 1" >>confdefs.h
+
+ HAVE_OPENSSL_QUIC=1
+
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+fi
if test "x$OPT_GNUTLS" != xno; then
@@ -27323,6 +27510,7 @@ printf "%s\n" "#define USE_GNUTLS 1" >>confdefs.h
GNUTLS_ENABLED=1
USE_GNUTLS="yes"
ssl_msg="GnuTLS"
+ QUIC_ENABLED=yes
test gnutls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
else $as_nop
@@ -27914,6 +28102,7 @@ printf "%s\n" "#define USE_WOLFSSL 1" >>confdefs.h
WOLFSSL_ENABLED=1
USE_WOLFSSL="yes"
ssl_msg="WolfSSL"
+ QUIC_ENABLED=yes
test wolfssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
else $as_nop
@@ -28606,6 +28795,7 @@ else $as_nop
with_libpsl=yes
fi
+curl_psl_msg="no (libpsl disabled)"
if test $with_libpsl != "no"; then
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing psl_builtin" >&5
printf %s "checking for library containing psl_builtin... " >&6; }
@@ -28669,10 +28859,7 @@ printf "%s\n" "#define USE_LIBPSL 1" >>confdefs.h
else $as_nop
- curl_psl_msg="no (libpsl not found)";
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libpsl was not found" >&5
-printf "%s\n" "$as_me: WARNING: libpsl was not found" >&2;}
-
+ as_fn_error $? "libpsl was not found" "$LINENO" 5
fi
@@ -30634,6 +30821,11 @@ esac
curl_tcp2_msg="no (--with-ngtcp2)"
if test X"$want_tcp2" != Xno; then
+
+ if test "$QUIC_ENABLED" != "yes"; then
+ as_fn_error $? "the detected TLS library does not support QUIC, making --with-ngtcp2 a no-no" "$LINENO" 5
+ fi
+
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
@@ -30887,7 +31079,7 @@ fi
fi
-if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1"; then
+if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BORINGSSL" != "x1"; then
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
@@ -31140,6 +31332,259 @@ fi
fi
fi
+if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BORINGSSL" = "x1"; then
+ CLEANLDFLAGS="$LDFLAGS"
+ CLEANCPPFLAGS="$CPPFLAGS"
+ CLEANLIBS="$LIBS"
+
+
+ if test -n "$PKG_CONFIG"; then
+ PKGCONFIG="$PKG_CONFIG"
+ else
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PKGCONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $PKGCONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="$PATH:/usr/bin:/usr/local/bin"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKGCONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKGCONFIG=$ac_cv_path_PKGCONFIG
+if test -n "$PKGCONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
+printf "%s\n" "$PKGCONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKGCONFIG"; then
+ ac_pt_PKGCONFIG=$PKGCONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_PKGCONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $ac_pt_PKGCONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="$PATH:/usr/bin:/usr/local/bin"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PKGCONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG
+if test -n "$ac_pt_PKGCONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5
+printf "%s\n" "$ac_pt_PKGCONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKGCONFIG" = x; then
+ PKGCONFIG="no"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKGCONFIG=$ac_pt_PKGCONFIG
+ fi
+else
+ PKGCONFIG="$ac_cv_path_PKGCONFIG"
+fi
+
+ fi
+
+ if test "x$PKGCONFIG" != "xno"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libngtcp2_crypto_boringssl options with pkg-config" >&5
+printf %s "checking for libngtcp2_crypto_boringssl options with pkg-config... " >&6; }
+ itexists=`
+ if test -n "$want_tcp2_path"; then
+ PKG_CONFIG_LIBDIR="$want_tcp2_path"
+ export PKG_CONFIG_LIBDIR
+ fi
+ $PKGCONFIG --exists libngtcp2_crypto_boringssl >/dev/null 2>&1 && echo 1`
+
+ if test -z "$itexists"; then
+ PKGCONFIG="no"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found" >&5
+printf "%s\n" "found" >&6; }
+ fi
+ fi
+
+
+ if test "$PKGCONFIG" != "no" ; then
+ LIB_NGTCP2_CRYPTO_BORINGSSL=`
+ if test -n "$want_tcp2_path"; then
+ PKG_CONFIG_LIBDIR="$want_tcp2_path"
+ export PKG_CONFIG_LIBDIR
+ fi
+
+ $PKGCONFIG --libs-only-l libngtcp2_crypto_boringssl`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: -l is $LIB_NGTCP2_CRYPTO_BORINGSSL" >&5
+printf "%s\n" "$as_me: -l is $LIB_NGTCP2_CRYPTO_BORINGSSL" >&6;}
+
+ CPP_NGTCP2_CRYPTO_BORINGSSL=`
+ if test -n "$want_tcp2_path"; then
+ PKG_CONFIG_LIBDIR="$want_tcp2_path"
+ export PKG_CONFIG_LIBDIR
+ fi
+ $PKGCONFIG --cflags-only-I libngtcp2_crypto_boringssl`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: -I is $CPP_NGTCP2_CRYPTO_BORINGSSL" >&5
+printf "%s\n" "$as_me: -I is $CPP_NGTCP2_CRYPTO_BORINGSSL" >&6;}
+
+ LD_NGTCP2_CRYPTO_BORINGSSL=`
+ if test -n "$want_tcp2_path"; then
+ PKG_CONFIG_LIBDIR="$want_tcp2_path"
+ export PKG_CONFIG_LIBDIR
+ fi
+
+ $PKGCONFIG --libs-only-L libngtcp2_crypto_boringssl`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: -L is $LD_NGTCP2_CRYPTO_BORINGSSL" >&5
+printf "%s\n" "$as_me: -L is $LD_NGTCP2_CRYPTO_BORINGSSL" >&6;}
+
+ LDFLAGS="$LDFLAGS $LD_NGTCP2_CRYPTO_BORINGSSL"
+ CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_BORINGSSL"
+ LIBS="$LIB_NGTCP2_CRYPTO_BORINGSSL $LIBS"
+
+ if test "x$cross_compiling" != "xyes"; then
+ DIR_NGTCP2_CRYPTO_BORINGSSL=`echo $LD_NGTCP2_CRYPTO_BORINGSSL | $SED -e 's/^-L//'`
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ngtcp2_crypto_recv_client_initial_cb in -lngtcp2_crypto_boringssl" >&5
+printf %s "checking for ngtcp2_crypto_recv_client_initial_cb in -lngtcp2_crypto_boringssl... " >&6; }
+if test ${ac_cv_lib_ngtcp2_crypto_boringssl_ngtcp2_crypto_recv_client_initial_cb+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lngtcp2_crypto_boringssl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+#ifdef __cplusplus
+extern "C"
+#endif
+char ngtcp2_crypto_recv_client_initial_cb ();
+int main (void)
+{
+return ngtcp2_crypto_recv_client_initial_cb ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_ngtcp2_crypto_boringssl_ngtcp2_crypto_recv_client_initial_cb=yes
+else $as_nop
+ ac_cv_lib_ngtcp2_crypto_boringssl_ngtcp2_crypto_recv_client_initial_cb=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ngtcp2_crypto_boringssl_ngtcp2_crypto_recv_client_initial_cb" >&5
+printf "%s\n" "$ac_cv_lib_ngtcp2_crypto_boringssl_ngtcp2_crypto_recv_client_initial_cb" >&6; }
+if test "x$ac_cv_lib_ngtcp2_crypto_boringssl_ngtcp2_crypto_recv_client_initial_cb" = xyes
+then :
+
+ for ac_header in ngtcp2/ngtcp2_crypto.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "ngtcp2/ngtcp2_crypto.h" "ac_cv_header_ngtcp2_ngtcp2_crypto_h" "$ac_includes_default"
+if test "x$ac_cv_header_ngtcp2_ngtcp2_crypto_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NGTCP2_NGTCP2_CRYPTO_H 1" >>confdefs.h
+ NGTCP2_ENABLED=1
+
+printf "%s\n" "#define USE_NGTCP2_CRYPTO_BORINGSSL 1" >>confdefs.h
+
+ USE_NGTCP2_CRYPTO_BORINGSSL=1
+
+ CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGTCP2_CRYPTO_BORINGSSL"
+ export CURL_LIBRARY_PATH
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added $DIR_NGTCP2_CRYPTO_BORINGSSL to CURL_LIBRARY_PATH" >&5
+printf "%s\n" "$as_me: Added $DIR_NGTCP2_CRYPTO_BORINGSSL to CURL_LIBRARY_PATH" >&6;}
+
+fi
+
+done
+
+else $as_nop
+ LDFLAGS=$CLEANLDFLAGS
+ CPPFLAGS=$CLEANCPPFLAGS
+ LIBS=$CLEANLIBS
+
+fi
+
+
+ else
+ if test X"$want_tcp2" != Xdefault; then
+ as_fn_error $? "--with-ngtcp2 was specified but could not find ngtcp2_crypto_boringssl pkg-config file." "$LINENO" 5
+ fi
+ fi
+fi
+
if test "x$NGTCP2_ENABLED" = "x1" -a "x$GNUTLS_ENABLED" = "x1"; then
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
@@ -31647,10 +32092,50 @@ fi
fi
+OPT_OPENSSL_QUIC="no"
+
+if test "x$disable_http" = "xyes" -o "x$OPENSSL_ENABLED" != "x1"; then
+ # without HTTP or without openssl, no use
+ OPT_OPENSSL_QUIC="no"
+fi
+
+
+# Check whether --with-openssl-quic was given.
+if test ${with_openssl_quic+y}
+then :
+ withval=$with_openssl_quic; OPT_OPENSSL_QUIC=$withval
+fi
+
+case "$OPT_OPENSSL_QUIC" in
+ no)
+ want_openssl_quic="no"
+ ;;
+ yes)
+ want_openssl_quic="yes"
+ ;;
+esac
+
+curl_openssl_quic_msg="no (--with-openssl-quic)"
+if test "x$want_openssl_quic" = "xyes"; then
+
+ if test "$NGTCP2_ENABLED" = 1; then
+ as_fn_error $? "--with-openssl-quic and --with-ngtcp2 are mutually exclusive" "$LINENO" 5
+ fi
+ if test "$HAVE_OPENSSL_QUIC" != 1; then
+ as_fn_error $? "--with-openssl-quic requires quic support in OpenSSL" "$LINENO" 5
+ fi
+
+printf "%s\n" "#define USE_OPENSSL_QUIC 1" >>confdefs.h
+
+ USE_OPENSSL_QUIC=1
+
+fi
+
+
OPT_NGHTTP3="yes"
-if test "x$NGTCP2_ENABLED" = "x"; then
- # without ngtcp2, nghttp3 is of no use for us
+if test "x$USE_NGTCP2" = "x" -a "$USE_OPENSSL_QUIC" = "x"; then
+ # without ngtcp2 or openssl quic, nghttp3 is of no use for us
OPT_NGHTTP3="no"
fi
@@ -31677,6 +32162,7 @@ esac
curl_http3_msg="no (--with-nghttp3)"
if test X"$want_nghttp3" != Xno; then
+
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
@@ -31899,8 +32385,6 @@ do :
if test "x$ac_cv_header_nghttp3_nghttp3_h" = xyes
then :
printf "%s\n" "#define HAVE_NGHTTP3_NGHTTP3_H 1" >>confdefs.h
- curl_h3_msg="enabled (ngtcp2 + nghttp3)"
- NGHTTP3_ENABLED=1
printf "%s\n" "#define USE_NGHTTP3 1" >>confdefs.h
@@ -31910,7 +32394,6 @@ printf "%s\n" "#define USE_NGHTTP3 1" >>confdefs.h
export CURL_LIBRARY_PATH
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Added $DIR_NGHTTP3 to CURL_LIBRARY_PATH" >&5
printf "%s\n" "$as_me: Added $DIR_NGHTTP3 to CURL_LIBRARY_PATH" >&6;}
- experimental="$experimental HTTP3"
fi
@@ -31933,6 +32416,31 @@ fi
fi
+if test "x$NGTCP2_ENABLED" = "x1" -a "x$USE_NGHTTP3" = "x1"; then
+
+printf "%s\n" "#define USE_NGTCP2_H3 1" >>confdefs.h
+
+ USE_NGTCP2_H3=1
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: HTTP3 support is experimental" >&5
+printf "%s\n" "$as_me: HTTP3 support is experimental" >&6;}
+ curl_h3_msg="enabled (ngtcp2 + nghttp3)"
+fi
+
+
+if test "x$USE_OPENSSL_QUIC" = "x1" -a "x$USE_NGHTTP3" = "x1"; then
+ experimental="$experimental HTTP3"
+
+printf "%s\n" "#define USE_OPENSSL_H3 1" >>confdefs.h
+
+ USE_OPENSSL_H3=1
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: HTTP3 support is experimental" >&5
+printf "%s\n" "$as_me: HTTP3 support is experimental" >&6;}
+ curl_h3_msg="enabled (openssl + nghttp3)"
+fi
+
+
OPT_QUICHE="no"
if test "x$disable_http" = "xyes" -o "x$USE_NGTCP" = "x1"; then
@@ -31963,6 +32471,10 @@ esac
if test X"$want_quiche" != Xno; then
+ if test "$QUIC_ENABLED" != "yes"; then
+ as_fn_error $? "the detected TLS library does not support QUIC, making --with-quiche a no-no" "$LINENO" 5
+ fi
+
if test "$NGHTTP3_ENABLED" = 1; then
as_fn_error $? "--with-quiche and --with-ngtcp2 are mutually exclusive" "$LINENO" 5
fi
@@ -32262,9 +32774,21 @@ esac
if test X"$want_msh3" != Xno; then
+ if test "$curl_cv_native_windows" != "yes"; then
+ if test "$QUIC_ENABLED" != "yes"; then
+ as_fn_error $? "the detected TLS library does not support QUIC, making --with-msh3 a no-no" "$LINENO" 5
+ fi
+ if test "$OPENSSL_ENABLED" != "1"; then
+ as_fn_error $? "msh3 requires OpenSSL" "$LINENO" 5
+ fi
+ fi
+
if test "$NGHTTP3_ENABLED" = 1; then
as_fn_error $? "--with-msh3 and --with-ngtcp2 are mutually exclusive" "$LINENO" 5
fi
+ if test "$QUICHE_ENABLED" = 1; then
+ as_fn_error $? "--with-msh3 and --with-quiche are mutually exclusive" "$LINENO" 5
+ fi
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
@@ -33771,114 +34295,6 @@ printf "%s\n" "#define const /**/" >>confdefs.h
fi
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler support of C99 variadic macro style" >&5
-printf %s "checking for compiler support of C99 variadic macro style... " >&6; }
-if test ${curl_cv_variadic_macros_c99+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__)
-#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__)
- int fun3(int arg1, int arg2, int arg3);
- int fun2(int arg1, int arg2);
- int fun3(int arg1, int arg2, int arg3)
- { return arg1 + arg2 + arg3; }
- int fun2(int arg1, int arg2)
- { return arg1 + arg2; }
-
-int main (void)
-{
-
- int res3 = c99_vmacro3(1, 2, 3);
- int res2 = c99_vmacro2(1, 2);
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_variadic_macros_c99="yes"
-
-else $as_nop
-
- curl_cv_variadic_macros_c99="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_variadic_macros_c99" >&5
-printf "%s\n" "$curl_cv_variadic_macros_c99" >&6; }
- case "$curl_cv_variadic_macros_c99" in
- yes)
-
-printf "%s\n" "#define HAVE_VARIADIC_MACROS_C99 1" >>confdefs.h
-
- ;;
- esac
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compiler support of old gcc variadic macro style" >&5
-printf %s "checking for compiler support of old gcc variadic macro style... " >&6; }
-if test ${curl_cv_variadic_macros_gcc+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#define gcc_vmacro3(first, args...) fun3(first, args)
-#define gcc_vmacro2(first, args...) fun2(first, args)
- int fun3(int arg1, int arg2, int arg3);
- int fun2(int arg1, int arg2);
- int fun3(int arg1, int arg2, int arg3)
- { return arg1 + arg2 + arg3; }
- int fun2(int arg1, int arg2)
- { return arg1 + arg2; }
-
-int main (void)
-{
-
- int res3 = gcc_vmacro3(1, 2, 3);
- int res2 = gcc_vmacro2(1, 2);
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_variadic_macros_gcc="yes"
-
-else $as_nop
-
- curl_cv_variadic_macros_gcc="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_variadic_macros_gcc" >&5
-printf "%s\n" "$curl_cv_variadic_macros_gcc" >&6; }
- case "$curl_cv_variadic_macros_gcc" in
- yes)
-
-printf "%s\n" "#define HAVE_VARIADIC_MACROS_GCC 1" >>confdefs.h
-
- ;;
- esac
-
ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
if test "x$ac_cv_type_size_t" = xyes
then :
@@ -33922,15 +34338,12 @@ else $as_nop
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -34477,6 +34890,12 @@ else $as_nop
# The windows name?
ac_fn_c_check_type "$LINENO" "ADDRESS_FAMILY" "ac_cv_type_ADDRESS_FAMILY" "
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <winsock2.h>
+#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -34604,100 +35023,13 @@ fi
-curl_includes_poll="\
-/* includes start */
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_POLL_H
-# include <poll.h>
-#endif
-#ifdef HAVE_SYS_POLL_H
-# include <sys/poll.h>
-#endif
-/* includes end */"
- ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$curl_includes_poll
-"
-if test "x$ac_cv_header_sys_types_h" = xyes
-then :
- printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h
-
-fi
-ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$curl_includes_poll
-"
-if test "x$ac_cv_header_poll_h" = xyes
-then :
- printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h
-
-fi
-ac_fn_c_check_header_compile "$LINENO" "sys/poll.h" "ac_cv_header_sys_poll_h" "$curl_includes_poll
-"
-if test "x$ac_cv_header_sys_poll_h" = xyes
-then :
- printf "%s\n" "#define HAVE_SYS_POLL_H 1" >>confdefs.h
-
-fi
-
-
-
- #
- tst_poll_events_macro_defined="unknown"
- #
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
- $curl_includes_poll
-
-int main (void)
-{
-
-#if defined(events) || defined(revents)
- return 0;
-#else
- force compilation error
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- tst_poll_events_macro_defined="yes"
-
-else $as_nop
-
- tst_poll_events_macro_defined="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
- #
- if test "$tst_poll_events_macro_defined" = "yes"; then
- if test "x$ac_cv_header_sys_poll_h" = "xyes"; then
-
-cat >>confdefs.h <<_EOF
-#define CURL_PULL_SYS_POLL_H 1
-_EOF
-
- fi
- fi
- #
-
-
-
ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" "
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -34734,14 +35066,11 @@ else $as_nop
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -34799,14 +35128,11 @@ fi
ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" "
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -34854,15 +35180,12 @@ printf %s "checking for select... " >&6; }
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -34870,7 +35193,7 @@ printf %s "checking for select... " >&6; }
#include <sys/time.h>
#endif
#include <time.h>
-#ifndef HAVE_WINDOWS_H
+#ifndef _WIN32
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#elif defined(HAVE_UNISTD_H)
@@ -34939,14 +35262,11 @@ printf %s "checking for recv... " >&6; }
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
$curl_includes_bsdsocket
#ifdef HAVE_SYS_TYPES_H
@@ -35015,14 +35335,11 @@ printf %s "checking for send... " >&6; }
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
$curl_includes_bsdsocket
#ifdef HAVE_SYS_TYPES_H
@@ -35095,14 +35412,11 @@ else $as_nop
#undef inline
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
-#endif
#else
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -36135,78 +36449,18 @@ printf "%s\n" "no" >&6; }
curl_includes_ws2tcpip="\
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# ifdef HAVE_WS2TCPIP_H
-# include <ws2tcpip.h>
-# endif
-# endif
+# include <winsock2.h>
+# include <ws2tcpip.h>
#endif
/* includes end */"
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for windows.h" >&5
-printf %s "checking for windows.h... " >&6; }
-if test ${curl_cv_header_windows_h+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-
-int main (void)
-{
-
-#if defined(__CYGWIN__) || defined(__CEGCC__)
- HAVE_WINDOWS_H shall not be defined.
-#else
- int dummy=2*WINVER;
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_header_windows_h="yes"
-
-else $as_nop
-
- curl_cv_header_windows_h="no"
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_windows_h" >&5
-printf "%s\n" "$curl_cv_header_windows_h" >&6; }
- case "$curl_cv_header_windows_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h
-
- ;;
- esac
-
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for winsock2.h" >&5
-printf %s "checking for winsock2.h... " >&6; }
-if test ${curl_cv_header_winsock2_h+y}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build target is a native Windows one" >&5
+printf %s "checking whether build target is a native Windows one... " >&6; }
+if test ${curl_cv_native_windows+y}
then :
printf %s "(cached) " >&6
else $as_nop
@@ -36215,20 +36469,14 @@ else $as_nop
/* end confdefs.h. */
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <winsock2.h>
int main (void)
{
-#if defined(__CYGWIN__) || defined(__CEGCC__) || defined(__MINGW32CE__)
- HAVE_WINSOCK2_H shall not be defined.
+#ifdef _WIN32
+ int dummy=1;
#else
- int dummy=2*IPPROTO_ESP;
+ Not a native Windows build target.
#endif
;
@@ -36239,82 +36487,26 @@ _ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
- curl_cv_header_winsock2_h="yes"
+ curl_cv_native_windows="yes"
else $as_nop
- curl_cv_header_winsock2_h="no"
+ curl_cv_native_windows="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_winsock2_h" >&5
-printf "%s\n" "$curl_cv_header_winsock2_h" >&6; }
- case "$curl_cv_header_winsock2_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WINSOCK2_H 1" >>confdefs.h
-
- ;;
- esac
-
-
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ws2tcpip.h" >&5
-printf %s "checking for ws2tcpip.h... " >&6; }
-if test ${curl_cv_header_ws2tcpip_h+y}
-then :
- printf %s "(cached) " >&6
-else $as_nop
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-#undef inline
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-int main (void)
-{
-
-#if defined(__CYGWIN__) || defined(__CEGCC__) || defined(__MINGW32CE__)
- HAVE_WS2TCPIP_H shall not be defined.
-#else
- int dummy=2*IP_PKTINFO;
-#endif
-
- ;
- return 0;
-}
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-
- curl_cv_header_ws2tcpip_h="yes"
-
-else $as_nop
-
- curl_cv_header_ws2tcpip_h="no"
-
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_native_windows" >&5
+printf "%s\n" "$curl_cv_native_windows" >&6; }
+ if test "x$curl_cv_native_windows" = xyes; then
+ DOING_NATIVE_WINDOWS_TRUE=
+ DOING_NATIVE_WINDOWS_FALSE='#'
+else
+ DOING_NATIVE_WINDOWS_TRUE='#'
+ DOING_NATIVE_WINDOWS_FALSE=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $curl_cv_header_ws2tcpip_h" >&5
-printf "%s\n" "$curl_cv_header_ws2tcpip_h" >&6; }
- case "$curl_cv_header_ws2tcpip_h" in
- yes)
-
-printf "%s\n" "#define HAVE_WS2TCPIP_H 1" >>confdefs.h
-
- ;;
- esac
@@ -37038,10 +37230,10 @@ int main (void)
struct addrinfo *ai = 0;
int error;
- #ifdef HAVE_WINSOCK2_H
+ #ifdef _WIN32
WSADATA wsa;
- if (WSAStartup(MAKEWORD(2,2), &wsa))
- exit(2);
+ if(WSAStartup(MAKEWORD(2, 2), &wsa))
+ exit(2);
#endif
memset(&hints, 0, sizeof(hints));
@@ -37106,10 +37298,10 @@ int main (void)
struct addrinfo *ai = 0;
int error;
- #ifdef HAVE_WINSOCK2_H
+ #ifdef _WIN32
WSADATA wsa;
- if (WSAStartup(MAKEWORD(2,2), &wsa))
- exit(2);
+ if(WSAStartup(MAKEWORD(2, 2), &wsa))
+ exit(2);
#endif
memset(&hints, 0, sizeof(hints));
@@ -37764,7 +37956,7 @@ printf "%s\n" "no" >&6; }
curl_preprocess_callconv="\
/* preprocess start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# define FUNCALLCONV __stdcall
#else
# define FUNCALLCONV
@@ -39040,7 +39232,7 @@ curl_includes_arpa_inet="\
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
-#ifdef HAVE_WINSOCK2_H
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
@@ -40734,6 +40926,42 @@ printf "%s\n" "no" >&6; }
fi
+curl_includes_poll="\
+/* includes start */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
+/* includes end */"
+ ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$curl_includes_poll
+"
+if test "x$ac_cv_header_sys_types_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$curl_includes_poll
+"
+if test "x$ac_cv_header_poll_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/poll.h" "ac_cv_header_sys_poll_h" "$curl_includes_poll
+"
+if test "x$ac_cv_header_sys_poll_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_POLL_H 1" >>confdefs.h
+
+fi
+
+
+
#
tst_links_poll="unknown"
tst_proto_poll="unknown"
@@ -43538,8 +43766,7 @@ fi
-
- for ac_func in _fseeki64 arc4random fchmod fnmatch fseeko geteuid getpass_r getppid getpwuid getpwuid_r getrlimit gettimeofday if_nametoindex mach_absolute_time pipe sched_yield sendmsg setlocale setmode setrlimit snprintf utime utimes
+ for ac_func in _fseeki64 arc4random fnmatch fseeko geteuid getpass_r getppid getpwuid getpwuid_r getrlimit gettimeofday if_nametoindex mach_absolute_time pipe sched_yield sendmsg setlocale setmode setrlimit snprintf utime utimes
do :
as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -43598,6 +43825,15 @@ fi
done
+ac_fn_check_decl "$LINENO" "fseeko" "ac_cv_have_decl_fseeko" "#include <stdio.h>
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_fseeko" = xyes
+then :
+
+printf "%s\n" "#define HAVE_DECL_FSEEKO 1" >>confdefs.h
+
+fi
+
#
tst_method="unknown"
@@ -45417,12 +45653,15 @@ if test "x$USE_TLS_SRP" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi
-if test "x$USE_NGHTTP2" = "x1" -o "x$USE_HYPER" = "x1"; then
+if test "x$USE_NGHTTP2" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi
-if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1" \
- -o "x$USE_MSH3" = "x1"; then
+if test "x$USE_NGTCP2_H3" = "x1" -o "x$USE_QUICHE" = "x1" \
+ -o "x$USE_OPENSSL_H3" = "x1" -o "x$USE_MSH3" = "x1"; then
+ if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
+ as_fn_error $? "MultiSSL cannot be enabled with HTTP/3 and vice versa" "$LINENO" 5
+ fi
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
fi
@@ -45430,19 +45669,36 @@ if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES MultiSSL"
fi
-if test "x$https_proxy" != "xno"; then
- if test "x$OPENSSL_ENABLED" = "x1" \
- -o "x$GNUTLS_ENABLED" = "x1" \
- -o "x$SECURETRANSPORT_ENABLED" = "x1" \
- -o "x$RUSTLS_ENABLED" = "x1" \
- -o "x$BEARSSL_ENABLED" = "x1" \
- -o "x$SCHANNEL_ENABLED" = "x1" \
- -o "x$GNUTLS_ENABLED" = "x1" \
- -o "x$MBEDTLS_ENABLED" = "x1"; then
- SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
- elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then
- SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if this build supports HTTPS-proxy" >&5
+printf %s "checking if this build supports HTTPS-proxy... " >&6; }
+if test "x$CURL_DISABLE_HTTP" != "x1"; then
+ if test "x$https_proxy" != "xno"; then
+ if test "x$OPENSSL_ENABLED" = "x1" \
+ -o "x$GNUTLS_ENABLED" = "x1" \
+ -o "x$SECURETRANSPORT_ENABLED" = "x1" \
+ -o "x$RUSTLS_ENABLED" = "x1" \
+ -o "x$BEARSSL_ENABLED" = "x1" \
+ -o "x$SCHANNEL_ENABLED" = "x1" \
+ -o "x$GNUTLS_ENABLED" = "x1" \
+ -o "x$MBEDTLS_ENABLED" = "x1"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ fi
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ECH_ENABLED" = "x1"; then
@@ -45458,6 +45714,9 @@ fi
if test "$tst_atomic" = "yes"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe"
+elif test "x$USE_THREADS_POSIX" = "x1" -a \
+ "x$ac_cv_header_pthread_h" = "xyes"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -45490,7 +45749,7 @@ SUPPORT_FEATURES=`echo $SUPPORT_FEATURES | tr ' ' '\012' | sort | tr '\012' ' '`
if test "x$CURL_DISABLE_HTTP" != "x1"; then
- SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTP"
+ SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTP IPFS IPNS"
if test "x$SSL_ENABLED" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTPS"
fi
@@ -45927,6 +46186,10 @@ if test -z "${USE_EXPLICIT_LIB_DEPS_TRUE}" && test -z "${USE_EXPLICIT_LIB_DEPS_F
as_fn_error $? "conditional \"USE_EXPLICIT_LIB_DEPS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${DOING_NATIVE_WINDOWS_TRUE}" && test -z "${DOING_NATIVE_WINDOWS_FALSE}"; then
+ as_fn_error $? "conditional \"DOING_NATIVE_WINDOWS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${CURLDEBUG_TRUE}" && test -z "${CURLDEBUG_FALSE}"; then
as_fn_error $? "conditional \"CURLDEBUG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -45935,14 +46198,14 @@ if test -z "${BUILD_UNITTESTS_TRUE}" && test -z "${BUILD_UNITTESTS_FALSE}"; then
as_fn_error $? "conditional \"BUILD_UNITTESTS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
-if test -z "${DOING_NATIVE_WINDOWS_TRUE}" && test -z "${DOING_NATIVE_WINDOWS_FALSE}"; then
- as_fn_error $? "conditional \"DOING_NATIVE_WINDOWS\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
if test -z "${HAVE_WINDRES_TRUE}" && test -z "${HAVE_WINDRES_FALSE}"; then
as_fn_error $? "conditional \"HAVE_WINDRES\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${DOING_NATIVE_WINDOWS_TRUE}" && test -z "${DOING_NATIVE_WINDOWS_FALSE}"; then
+ as_fn_error $? "conditional \"DOING_NATIVE_WINDOWS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${HAVE_LIBZ_TRUE}" && test -z "${HAVE_LIBZ_FALSE}"; then
as_fn_error $? "conditional \"HAVE_LIBZ\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -45963,6 +46226,10 @@ if test -z "${CURL_LT_SHLIB_USE_VERSIONED_SYMBOLS_TRUE}" && test -z "${CURL_LT_S
as_fn_error $? "conditional \"CURL_LT_SHLIB_USE_VERSIONED_SYMBOLS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${DOING_NATIVE_WINDOWS_TRUE}" && test -z "${DOING_NATIVE_WINDOWS_FALSE}"; then
+ as_fn_error $? "conditional \"DOING_NATIVE_WINDOWS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${USE_MANUAL_TRUE}" && test -z "${USE_MANUAL_FALSE}"; then
as_fn_error $? "conditional \"USE_MANUAL\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/configure.ac b/configure.ac
index 2d71c838f..be66be9e9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -174,8 +174,8 @@ curl_headers_msg="enabled (--disable-headers-api)"
curl_ws_msg="no (--enable-websockets)"
ssl_backends=
curl_h1_msg="enabled (internal)"
- curl_h2_msg="no (--with-nghttp2, --with-hyper)"
- curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-msh3)"
+ curl_h2_msg="no (--with-nghttp2)"
+ curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-openssl-quic, --with-msh3)"
enable_altsvc="yes"
hsts="yes"
@@ -503,6 +503,7 @@ dnl platform/compiler/architecture specific checks/flags
dnl **********************************************************************
CURL_CHECK_COMPILER
+CURL_CHECK_NATIVE_WINDOWS
CURL_SET_COMPILER_BASIC_OPTS
CURL_SET_COMPILER_DEBUG_OPTS
CURL_SET_COMPILER_OPTIMIZE_OPTS
@@ -583,25 +584,6 @@ dnl **********************************************************************
dnl Compilation based checks should not be done before this point.
dnl **********************************************************************
-dnl **********************************************************************
-dnl Make sure that our checks for headers windows.h winsock2.h
-dnl and ws2tcpip.h take precedence over any other further checks which
-dnl could be done later using AC_CHECK_HEADER or AC_CHECK_HEADERS for
-dnl this specific header files. And do them before its results are used.
-dnl **********************************************************************
-
-CURL_CHECK_HEADER_WINDOWS
-CURL_CHECK_NATIVE_WINDOWS
-case X-"$curl_cv_native_windows" in
- X-yes)
- CURL_CHECK_HEADER_WINSOCK2
- CURL_CHECK_HEADER_WS2TCPIP
- ;;
- *)
- curl_cv_header_winsock2_h="no"
- curl_cv_header_ws2tcpip_h="no"
- ;;
-esac
CURL_CHECK_WIN32_LARGEFILE
CURL_CHECK_WIN32_CRYPTO
@@ -803,7 +785,6 @@ if test X"$want_hyper" != Xno; then
experimental="$experimental Hyper"
AC_MSG_NOTICE([Hyper support is experimental])
curl_h1_msg="enabled (Hyper)"
- curl_h2_msg=$curl_h1_msg
HYPER_ENABLED=1
AC_DEFINE(USE_HYPER, 1, [if hyper is in use])
AC_SUBST(USE_HYPER, [1])
@@ -1131,25 +1112,20 @@ fi
if test "$HAVE_GETHOSTBYNAME" != "1"
then
dnl This is for winsock systems
- if test "$curl_cv_header_windows_h" = "yes"; then
- if test "$curl_cv_header_winsock2_h" = "yes"; then
- winsock_LIB="-lws2_32"
- fi
+ if test "$curl_cv_native_windows" = "yes"; then
+ winsock_LIB="-lws2_32"
if test ! -z "$winsock_LIB"; then
my_ac_save_LIBS=$LIBS
LIBS="$winsock_LIB $LIBS"
AC_MSG_CHECKING([for gethostbyname in $winsock_LIB])
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
-#include <windows.h>
-#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
-#endif
]],[[
gethostbyname("localhost");
]])
@@ -1669,7 +1645,7 @@ AS_HELP_STRING([--disable-ipv6],[Disable IPv6 support]),
AC_RUN_IFELSE([AC_LANG_SOURCE([[
/* are AF_INET6 and sockaddr_in6 available? */
#include <sys/types.h>
-#ifdef HAVE_WINSOCK2_H
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
@@ -1679,15 +1655,12 @@ AS_HELP_STRING([--disable-ipv6],[Disable IPv6 support]),
# include <netinet/in6.h>
#endif
#endif
-#include <stdlib.h> /* for exit() */
-main()
+
+int main(void)
{
struct sockaddr_in6 s;
(void)s;
- if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
- exit(1);
- else
- exit(0);
+ return socket(AF_INET6, SOCK_STREAM, 0) < 0;
}
]])
],
@@ -1708,7 +1681,7 @@ if test "$ipv6" = yes; then
AC_MSG_CHECKING([if struct sockaddr_in6 has sin6_scope_id member])
AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[
#include <sys/types.h>
-#ifdef HAVE_WINSOCK2_H
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
@@ -1851,10 +1824,7 @@ AC_INCLUDES_DEFAULT
if test "x$not_mit" = "x1"; then
dnl MIT not found, check for Heimdal
AC_CHECK_HEADER(gssapi.h,
- [
- dnl found
- AC_DEFINE(HAVE_GSSHEIMDAL, 1, [if you have Heimdal])
- ],
+ [],
[
dnl no header found, disabling GSS
want_gss=no
@@ -1863,7 +1833,6 @@ AC_INCLUDES_DEFAULT
)
else
dnl MIT found
- AC_DEFINE(HAVE_GSSMIT, 1, [if you have MIT Kerberos])
dnl check if we have a really old MIT Kerberos version (<= 1.2)
AC_MSG_CHECKING([if GSS-API headers declare GSS_C_NT_HOSTBASED_SERVICE])
AC_COMPILE_IFELSE([
@@ -2085,17 +2054,16 @@ dnl **********************************************************************
AC_ARG_WITH(libpsl,
AS_HELP_STRING([--without-libpsl],
- [disable support for libpsl cookie checking]),
+ [disable support for libpsl]),
with_libpsl=$withval,
with_libpsl=yes)
+curl_psl_msg="no (libpsl disabled)"
if test $with_libpsl != "no"; then
AC_SEARCH_LIBS(psl_builtin, psl,
[curl_psl_msg="enabled";
AC_DEFINE([USE_LIBPSL], [1], [PSL support enabled])
],
- [curl_psl_msg="no (libpsl not found)";
- AC_MSG_WARN([libpsl was not found])
- ]
+ [AC_MSG_ERROR([libpsl was not found]) ]
)
fi
AM_CONDITIONAL([USE_LIBPSL], [test "$curl_psl_msg" = "enabled"])
@@ -2808,6 +2776,11 @@ esac
curl_tcp2_msg="no (--with-ngtcp2)"
if test X"$want_tcp2" != Xno; then
+
+ if test "$QUIC_ENABLED" != "yes"; then
+ AC_MSG_ERROR([the detected TLS library does not support QUIC, making --with-ngtcp2 a no-no])
+ fi
+
dnl backup the pre-ngtcp2 variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
@@ -2863,7 +2836,7 @@ if test X"$want_tcp2" != Xno; then
fi
-if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1"; then
+if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BORINGSSL" != "x1"; then
dnl backup the pre-ngtcp2_crypto_quictls variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
@@ -2918,6 +2891,61 @@ if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1"; then
fi
fi
+if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BORINGSSL" = "x1"; then
+ dnl backup the pre-ngtcp2_crypto_boringssl variables
+ CLEANLDFLAGS="$LDFLAGS"
+ CLEANCPPFLAGS="$CPPFLAGS"
+ CLEANLIBS="$LIBS"
+
+ CURL_CHECK_PKGCONFIG(libngtcp2_crypto_boringssl, $want_tcp2_path)
+
+ if test "$PKGCONFIG" != "no" ; then
+ LIB_NGTCP2_CRYPTO_BORINGSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-l libngtcp2_crypto_boringssl`
+ AC_MSG_NOTICE([-l is $LIB_NGTCP2_CRYPTO_BORINGSSL])
+
+ CPP_NGTCP2_CRYPTO_BORINGSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path]) dnl
+ $PKGCONFIG --cflags-only-I libngtcp2_crypto_boringssl`
+ AC_MSG_NOTICE([-I is $CPP_NGTCP2_CRYPTO_BORINGSSL])
+
+ LD_NGTCP2_CRYPTO_BORINGSSL=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-L libngtcp2_crypto_boringssl`
+ AC_MSG_NOTICE([-L is $LD_NGTCP2_CRYPTO_BORINGSSL])
+
+ LDFLAGS="$LDFLAGS $LD_NGTCP2_CRYPTO_BORINGSSL"
+ CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_BORINGSSL"
+ LIBS="$LIB_NGTCP2_CRYPTO_BORINGSSL $LIBS"
+
+ if test "x$cross_compiling" != "xyes"; then
+ DIR_NGTCP2_CRYPTO_BORINGSSL=`echo $LD_NGTCP2_CRYPTO_BORINGSSL | $SED -e 's/^-L//'`
+ fi
+ AC_CHECK_LIB(ngtcp2_crypto_boringssl, ngtcp2_crypto_recv_client_initial_cb,
+ [
+ AC_CHECK_HEADERS(ngtcp2/ngtcp2_crypto.h,
+ NGTCP2_ENABLED=1
+ AC_DEFINE(USE_NGTCP2_CRYPTO_BORINGSSL, 1, [if ngtcp2_crypto_boringssl is in use])
+ AC_SUBST(USE_NGTCP2_CRYPTO_BORINGSSL, [1])
+ CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGTCP2_CRYPTO_BORINGSSL"
+ export CURL_LIBRARY_PATH
+ AC_MSG_NOTICE([Added $DIR_NGTCP2_CRYPTO_BORINGSSL to CURL_LIBRARY_PATH])
+ )
+ ],
+ dnl not found, revert back to clean variables
+ LDFLAGS=$CLEANLDFLAGS
+ CPPFLAGS=$CLEANCPPFLAGS
+ LIBS=$CLEANLIBS
+ )
+
+ else
+ dnl no ngtcp2_crypto_boringssl pkg-config found, deal with it
+ if test X"$want_tcp2" != Xdefault; then
+ dnl To avoid link errors, we do not allow --with-ngtcp2 without
+ dnl a pkgconfig file
+ AC_MSG_ERROR([--with-ngtcp2 was specified but could not find ngtcp2_crypto_boringssl pkg-config file.])
+ fi
+ fi
+fi
+
if test "x$NGTCP2_ENABLED" = "x1" -a "x$GNUTLS_ENABLED" = "x1"; then
dnl backup the pre-ngtcp2_crypto_gnutls variables
CLEANLDFLAGS="$LDFLAGS"
@@ -3029,13 +3057,52 @@ if test "x$NGTCP2_ENABLED" = "x1" -a "x$WOLFSSL_ENABLED" = "x1"; then
fi
dnl **********************************************************************
+dnl Check for OpenSSL QUIC
+dnl **********************************************************************
+
+OPT_OPENSSL_QUIC="no"
+
+if test "x$disable_http" = "xyes" -o "x$OPENSSL_ENABLED" != "x1"; then
+ # without HTTP or without openssl, no use
+ OPT_OPENSSL_QUIC="no"
+fi
+
+AC_ARG_WITH(openssl-quic,
+AS_HELP_STRING([--with-openssl-quic],[Enable OpenSSL QUIC usage])
+AS_HELP_STRING([--without-openssl-quic],[Disable OpenSSL QUIC usage]),
+ [OPT_OPENSSL_QUIC=$withval])
+case "$OPT_OPENSSL_QUIC" in
+ no)
+ dnl --without-openssl-quic option used
+ want_openssl_quic="no"
+ ;;
+ yes)
+ dnl --with-openssl-quic option used
+ want_openssl_quic="yes"
+ ;;
+esac
+
+curl_openssl_quic_msg="no (--with-openssl-quic)"
+if test "x$want_openssl_quic" = "xyes"; then
+
+ if test "$NGTCP2_ENABLED" = 1; then
+ AC_MSG_ERROR([--with-openssl-quic and --with-ngtcp2 are mutually exclusive])
+ fi
+ if test "$HAVE_OPENSSL_QUIC" != 1; then
+ AC_MSG_ERROR([--with-openssl-quic requires quic support in OpenSSL])
+ fi
+ AC_DEFINE(USE_OPENSSL_QUIC, 1, [if openssl QUIC is in use])
+ AC_SUBST(USE_OPENSSL_QUIC, [1])
+fi
+
+dnl **********************************************************************
dnl Check for nghttp3 (HTTP/3 with ngtcp2)
dnl **********************************************************************
OPT_NGHTTP3="yes"
-if test "x$NGTCP2_ENABLED" = "x"; then
- # without ngtcp2, nghttp3 is of no use for us
+if test "x$USE_NGTCP2" = "x" -a "$USE_OPENSSL_QUIC" = "x"; then
+ # without ngtcp2 or openssl quic, nghttp3 is of no use for us
OPT_NGHTTP3="no"
fi
@@ -3062,6 +3129,7 @@ esac
curl_http3_msg="no (--with-nghttp3)"
if test X"$want_nghttp3" != Xno; then
+
dnl backup the pre-nghttp3 variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
@@ -3092,14 +3160,11 @@ if test X"$want_nghttp3" != Xno; then
AC_CHECK_LIB(nghttp3, nghttp3_conn_client_new_versioned,
[
AC_CHECK_HEADERS(nghttp3/nghttp3.h,
- curl_h3_msg="enabled (ngtcp2 + nghttp3)"
- NGHTTP3_ENABLED=1
AC_DEFINE(USE_NGHTTP3, 1, [if nghttp3 is in use])
AC_SUBST(USE_NGHTTP3, [1])
CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGHTTP3"
export CURL_LIBRARY_PATH
AC_MSG_NOTICE([Added $DIR_NGHTTP3 to CURL_LIBRARY_PATH])
- experimental="$experimental HTTP3"
)
],
dnl not found, revert back to clean variables
@@ -3120,6 +3185,29 @@ if test X"$want_nghttp3" != Xno; then
fi
dnl **********************************************************************
+dnl Check for ngtcp2 and nghttp3 (HTTP/3 with ngtcp2 + nghttp3)
+dnl **********************************************************************
+
+if test "x$NGTCP2_ENABLED" = "x1" -a "x$USE_NGHTTP3" = "x1"; then
+ AC_DEFINE(USE_NGTCP2_H3, 1, [if ngtcp2 + nghttp3 is in use])
+ AC_SUBST(USE_NGTCP2_H3, [1])
+ AC_MSG_NOTICE([HTTP3 support is experimental])
+ curl_h3_msg="enabled (ngtcp2 + nghttp3)"
+fi
+
+dnl **********************************************************************
+dnl Check for OpenSSL and nghttp3 (HTTP/3 with nghttp3 using OpenSSL QUIC)
+dnl **********************************************************************
+
+if test "x$USE_OPENSSL_QUIC" = "x1" -a "x$USE_NGHTTP3" = "x1"; then
+ experimental="$experimental HTTP3"
+ AC_DEFINE(USE_OPENSSL_H3, 1, [if openssl quic + nghttp3 is in use])
+ AC_SUBST(USE_OPENSSL_H3, [1])
+ AC_MSG_NOTICE([HTTP3 support is experimental])
+ curl_h3_msg="enabled (openssl + nghttp3)"
+fi
+
+dnl **********************************************************************
dnl Check for quiche (QUIC)
dnl **********************************************************************
@@ -3153,6 +3241,10 @@ esac
if test X"$want_quiche" != Xno; then
+ if test "$QUIC_ENABLED" != "yes"; then
+ AC_MSG_ERROR([the detected TLS library does not support QUIC, making --with-quiche a no-no])
+ fi
+
if test "$NGHTTP3_ENABLED" = 1; then
AC_MSG_ERROR([--with-quiche and --with-ngtcp2 are mutually exclusive])
fi
@@ -3251,9 +3343,22 @@ esac
if test X"$want_msh3" != Xno; then
+ dnl msh3 on non-Windows needs an OpenSSL with the QUIC API
+ if test "$curl_cv_native_windows" != "yes"; then
+ if test "$QUIC_ENABLED" != "yes"; then
+ AC_MSG_ERROR([the detected TLS library does not support QUIC, making --with-msh3 a no-no])
+ fi
+ if test "$OPENSSL_ENABLED" != "1"; then
+ AC_MSG_ERROR([msh3 requires OpenSSL])
+ fi
+ fi
+
if test "$NGHTTP3_ENABLED" = 1; then
AC_MSG_ERROR([--with-msh3 and --with-ngtcp2 are mutually exclusive])
fi
+ if test "$QUICHE_ENABLED" = 1; then
+ AC_MSG_ERROR([--with-msh3 and --with-quiche are mutually exclusive])
+ fi
dnl backup the pre-msh3 variables
CLEANLDFLAGS="$LDFLAGS"
@@ -3418,7 +3523,6 @@ dnl default includes
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
-CURL_CHECK_VARIADIC_MACROS
AC_TYPE_SIZE_T
CURL_CHECK_STRUCT_TIMEVAL
@@ -3476,6 +3580,12 @@ AC_CHECK_TYPE(sa_family_t,
AC_DEFINE(CURL_SA_FAMILY_T, ADDRESS_FAMILY, [IP address type in sockaddr]),
AC_DEFINE(CURL_SA_FAMILY_T, unsigned short, [IP address type in sockaddr]),
[
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <winsock2.h>
+#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
@@ -3519,8 +3629,6 @@ CURL_RUN_IFELSE(
AC_MSG_RESULT([no])
])
-CURL_CONFIGURE_PULL_SYS_POLL
-
TYPE_IN_ADDR_T
TYPE_SOCKADDR_STORAGE
@@ -3581,11 +3689,9 @@ AC_CHECK_DECLS([getpwuid_r], [], [AC_DEFINE(HAVE_DECL_GETPWUID_R_MISSING, 1, "Se
[[#include <pwd.h>
#include <sys/types.h>]])
-
AC_CHECK_FUNCS([\
_fseeki64 \
arc4random \
- fchmod \
fnmatch \
fseeko \
geteuid \
@@ -3628,6 +3734,15 @@ AC_CHECK_FUNCS([\
fi
])
+dnl On Android, the only way to know if fseeko can be used is to see if it is
+dnl declared or not (for this API level), as the symbol always exists in the
+dnl lib.
+AC_CHECK_DECL([fseeko],
+ [AC_DEFINE([HAVE_DECL_FSEEKO], [1],
+ [Define to 1 if you have the fseeko declaration])],
+ [],
+ [[#include <stdio.h>]])
+
CURL_CHECK_NONBLOCKING_SOCKET
dnl ************************************************************
@@ -4570,12 +4685,15 @@ if test "x$USE_TLS_SRP" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP"
fi
-if test "x$USE_NGHTTP2" = "x1" -o "x$USE_HYPER" = "x1"; then
+if test "x$USE_NGHTTP2" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
fi
-if test "x$USE_NGTCP2" = "x1" -o "x$USE_QUICHE" = "x1" \
- -o "x$USE_MSH3" = "x1"; then
+if test "x$USE_NGTCP2_H3" = "x1" -o "x$USE_QUICHE" = "x1" \
+ -o "x$USE_OPENSSL_H3" = "x1" -o "x$USE_MSH3" = "x1"; then
+ if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
+ AC_MSG_ERROR([MultiSSL cannot be enabled with HTTP/3 and vice versa])
+ fi
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3"
fi
@@ -4583,20 +4701,31 @@ if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES MultiSSL"
fi
+AC_MSG_CHECKING([if this build supports HTTPS-proxy])
dnl if not explicitly turned off, HTTPS-proxy comes with some TLS backends
-if test "x$https_proxy" != "xno"; then
- if test "x$OPENSSL_ENABLED" = "x1" \
- -o "x$GNUTLS_ENABLED" = "x1" \
- -o "x$SECURETRANSPORT_ENABLED" = "x1" \
- -o "x$RUSTLS_ENABLED" = "x1" \
- -o "x$BEARSSL_ENABLED" = "x1" \
- -o "x$SCHANNEL_ENABLED" = "x1" \
- -o "x$GNUTLS_ENABLED" = "x1" \
- -o "x$MBEDTLS_ENABLED" = "x1"; then
- SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
- elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then
- SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
+if test "x$CURL_DISABLE_HTTP" != "x1"; then
+ if test "x$https_proxy" != "xno"; then
+ if test "x$OPENSSL_ENABLED" = "x1" \
+ -o "x$GNUTLS_ENABLED" = "x1" \
+ -o "x$SECURETRANSPORT_ENABLED" = "x1" \
+ -o "x$RUSTLS_ENABLED" = "x1" \
+ -o "x$BEARSSL_ENABLED" = "x1" \
+ -o "x$SCHANNEL_ENABLED" = "x1" \
+ -o "x$GNUTLS_ENABLED" = "x1" \
+ -o "x$MBEDTLS_ENABLED" = "x1"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
+ AC_MSG_RESULT([yes])
+ elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$WOLFSSL_FULL_BIO" = "x1"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ else
+ AC_MSG_RESULT([no])
fi
+else
+ AC_MSG_RESULT([no])
fi
if test "x$ECH_ENABLED" = "x1"; then
@@ -4612,6 +4741,9 @@ fi
if test "$tst_atomic" = "yes"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe"
+elif test "x$USE_THREADS_POSIX" = "x1" -a \
+ "x$ac_cv_header_pthread_h" = "xyes"; then
+ SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe"
else
AC_COMPILE_IFELSE([
AC_LANG_PROGRAM([[
@@ -4635,7 +4767,7 @@ AC_SUBST(SUPPORT_FEATURES)
dnl For supported protocols in pkg-config file
if test "x$CURL_DISABLE_HTTP" != "x1"; then
- SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTP"
+ SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTP IPFS IPNS"
if test "x$SSL_ENABLED" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTPS"
fi
diff --git a/docs/.gitignore b/docs/.gitignore
index 8d0bfb31b..a087be744 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -2,7 +2,5 @@
#
# SPDX-License-Identifier: curl
-*.html
-*.pdf
-curl.1
-*.1.dist
+*.1
+*.3
diff --git a/docs/ALTSVC.md b/docs/ALTSVC.md
index b9117e4d4..18d2d2ad9 100644
--- a/docs/ALTSVC.md
+++ b/docs/ALTSVC.md
@@ -24,16 +24,16 @@ space separated fields.
## Fields
1. The ALPN id for the source origin
-2. The host name for the source origin
+2. The hostname for the source origin
3. The port number for the source origin
4. The ALPN id for the destination host
-5. The host name for the destination host
+5. The hostname for the destination host
6. The host number for the destination host
7. The expiration date and time of this entry within double quotes. The date format is "YYYYMMDD HH:MM:SS" and the time zone is GMT.
8. Boolean (1 or 0) if "persist" was set for this entry
9. Integer priority value (not currently used)
-If the host name is an IPv6 numerical address, it is stored with brackets such
+If the hostname is an IPv6 numerical address, it is stored with brackets such
as `[::1]`.
# TODO
diff --git a/docs/BINDINGS.md b/docs/BINDINGS.md
index 57f87a5f8..7f5da4219 100644
--- a/docs/BINDINGS.md
+++ b/docs/BINDINGS.md
@@ -125,6 +125,8 @@ Ruby: [curb](https://github.com/taf2/curb) written by Ross Bamford,
[Tcl](https://web.archive.org/web/20160826011806/mirror.yellow5.com/tclcurl/) Tclcurl by Andrés García
+[Vibe](https://github.com/ttytm/vibe) HTTP requests through libcurl in V
+
[Visual Basic](https://sourceforge.net/projects/libcurl-vb/) libcurl-vb by Jeffrey Phillips
[Visual Foxpro](https://web.archive.org/web/20130730181523/www.ctl32.com.ar/libcurl.asp) by Carlos Alloatti
diff --git a/docs/BUFQ.md b/docs/BUFQ.md
index 5ff9e28b8..1a95a884c 100644
--- a/docs/BUFQ.md
+++ b/docs/BUFQ.md
@@ -115,11 +115,18 @@ Note that a `bufq` length and it being "full" are only loosely related. A simple
* read 1 bytes from it, it will still report "full"
* read 999 more bytes from it, and it will no longer be "full"
-The reason for this is that full really means: *bufq uses max_chunks and the last one cannot be written to*.
-
-So when you read 1 byte from the head chunk in the example above, the head still hold 999 unread bytes. Only when those are also read, can the head chunk be removed and a new tail be added.
-
-There is another variation to this. If you initialized a `bufq` with option `BUFQ_OPT_SOFT_LIMIT`, it will allow writes **beyond** the `max_chunks`. It will report **full**, but one can **still** write. This option is necessary, if partial writes need to be avoided. But it means that you will need other checks to keep the `bufq` from growing ever larger and larger.
+The reason for this is that full really means: *bufq uses max_chunks and the
+last one cannot be written to*.
+
+When you read 1 byte from the head chunk in the example above, the head still
+hold 999 unread bytes. Only when those are also read, can the head chunk be
+removed and a new tail be added.
+
+There is another variation to this. If you initialized a `bufq` with option
+`BUFQ_OPT_SOFT_LIMIT`, it will allow writes **beyond** the `max_chunks`. It
+will report **full**, but one can **still** write. This option is necessary,
+if partial writes need to be avoided. It means that you will need other checks
+to keep the `bufq` from growing ever larger and larger.
## pools
diff --git a/docs/BUGS.md b/docs/BUGS.md
index 2a8c56fe6..7333baafe 100644
--- a/docs/BUGS.md
+++ b/docs/BUGS.md
@@ -5,7 +5,7 @@
Curl and libcurl keep being developed. Adding features and changing code
means that bugs will sneak in, no matter how hard we try to keep them out.
- Of course there are lots of bugs left. And lots of misfeatures.
+ Of course there are lots of bugs left. Not to mention misfeatures.
To help us make curl the stable and solid product we want it to be, we need
bug reports and bug fixes.
diff --git a/docs/CIPHERS.md b/docs/CIPHERS.md
index 27de94036..f616f4972 100644
--- a/docs/CIPHERS.md
+++ b/docs/CIPHERS.md
@@ -363,10 +363,10 @@ individual TLS 1.3 cipher suites since Schannel does not support it directly.
`TLS_AES_128_CCM_8_SHA256`
`TLS_AES_128_CCM_SHA256`
-Note if you set TLS 1.3 ciphers without also setting the minimum TLS version to
-1.3 then it's possible Schannel may negotiate an earlier TLS version and cipher
-suite if your libcurl and OS settings allow it. You can set the minimum TLS
-version by using `CURLOPT_SSLVERSION` or `--tlsv1.3`.
+Note if you set TLS 1.3 ciphers without also setting the minimum TLS version
+to 1.3 then it is possible Schannel may negotiate an earlier TLS version and
+cipher suite if your libcurl and OS settings allow it. You can set the minimum
+TLS version by using `CURLOPT_SSLVERSION` or `--tlsv1.3`.
## BearSSL
diff --git a/docs/CLIENT-WRITERS.md b/docs/CLIENT-WRITERS.md
new file mode 100644
index 000000000..7a928826c
--- /dev/null
+++ b/docs/CLIENT-WRITERS.md
@@ -0,0 +1,104 @@
+# curl client writers
+
+Client writers is a design in the internals of libcurl, not visible in its public API. They were started
+in curl v8.5.0. This document describes the concepts, its high level implementation and the motivations.
+
+## Naming
+
+`libcurl` operates between clients and servers. A *client* is the application using libcurl, like the command line tool `curl` itself. Data to be uploaded to a server is **read** from the client and **send** to the server, the servers response is **received** by `libcurl` and then **written** to the client.
+
+With this naming established, client writers are concerned with writing responses from the server to the application. Applications register callbacks via `CURLOPT_WRITEFUNCTION` and `CURLOPT_HEADERFUNCTION` to be invoked by `libcurl` when the response is received.
+
+## Invoking
+
+All code in `libcurl` that handles response data is ultimately expected to forward this data via `Curl_client_write()` to the application. The exact prototype of this function is:
+
+```
+CURLcode Curl_client_write(struct Curl_easy *data, int type, char *buf, size_t blen);
+```
+The `type` argument specifies what the bytes in `buf` actually are. The following bits are defined:
+
+```
+#define CLIENTWRITE_BODY (1<<0) /* non-meta information, BODY */
+#define CLIENTWRITE_INFO (1<<1) /* meta information, not a HEADER */
+#define CLIENTWRITE_HEADER (1<<2) /* meta information, HEADER */
+#define CLIENTWRITE_STATUS (1<<3) /* a special status HEADER */
+#define CLIENTWRITE_CONNECT (1<<4) /* a CONNECT related HEADER */
+#define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */
+#define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
+```
+
+The main types here are `CLIENTWRITE_BODY` and `CLIENTWRITE_HEADER`. They are
+mutually exclusive. The other bits are enhancements to `CLIENTWRITE_HEADER` to
+specify what the header is about. They are only used in HTTP and related
+protocols (RTSP and WebSocket).
+
+The implementation of `Curl_client_write()` uses a chain of *client writer* instances to process the call and make sure that the bytes reach the proper application callbacks. This is similar to the design of connection filters: client writers can be chained to process the bytes written through them. The definition is:
+
+```
+struct Curl_cwtype {
+ const char *name;
+ CURLcode (*do_init)(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+ CURLcode (*do_write)(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes);
+ void (*do_close)(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+};
+
+struct Curl_cwriter {
+ const struct Curl_cwtype *cwt; /* type implementation */
+ struct Curl_cwriter *next; /* Downstream writer. */
+ Curl_cwriter_phase phase; /* phase at which it operates */
+};
+```
+
+`Curl_cwriter` is a writer instance with a `next` pointer to form the chain. It has a type `cwt` which provides the implementation. The main callback is `do_write()` that processes the data and calls then the `next` writer. The others are for setup and tear down.
+
+## Phases and Ordering
+
+Since client writers may transform the bytes written through them, the order in which the are called is relevant for the outcome. When a writer is created, one property it gets is the `phase` in which it operates. Writer phases are defined like:
+
+```
+typedef enum {
+ CURL_CW_RAW, /* raw data written, before any decoding */
+ CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
+ CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
+ CURL_CW_CONTENT_DECODE, /* remove content-encodings */
+ CURL_CW_CLIENT /* data written to client */
+} Curl_cwriter_phase;
+```
+
+If a writer for phase `PROTOCOL` is added to the chain, it is always added *after* any `RAW` or `TRANSFER_DECODE` and *before* any `CONTENT_DECODE` and `CLIENT` phase writer. If there is already a writer for the same phase present, the new writer is inserted just before that one.
+
+All transfers have a chain of 3 writers by default. A specific protocol handler may alter that by adding additional writers. The 3 standard writers are (name, phase):
+
+1. `"raw", CURL_CW_RAW `: if the transfer is verbose, it forwards the body data to the debug function.
+1. `"download", CURL_CW_PROTOCOL`: checks that protocol limits are kept and updates progress counters. When a download has a known length, it checks that it is not exceeded and errors otherwise.
+1. `"client", CURL_CW_CLIENT`: the main work horse. It invokes the application callbacks or writes to the configured file handles. It chops large writes into smaller parts, as documented for `CURLOPT_WRITEFUNCTION`. If also handles *pausing* of transfers when the application callback returns `CURL_WRITEFUNC_PAUSE`.
+
+With these writers always in place, libcurl's protocol handlers automatically have these implemented.
+
+## Enhanced Use
+
+HTTP is the protocol in curl that makes use of the client writer chain by adding writers to it. When the `libcurl` application set `CURLOPT_ACCEPT_ENCODING` (as `curl` does with `--compressed`), the server is offered an `Accept-Encoding` header with the algorithms supported. The server then may choose to send the response body compressed. For example using `gzip` or `brotli` or even both.
+
+In the server's response, there then will be a `Content-Encoding` header listing the encoding applied. If supported by `libcurl` it will then decompress the content before writing it out to the client. How does it do that?
+
+The HTTP protocol will add client writers in phase `CURL_CW_CONTENT_DECODE` on seeing such a header. For each encoding listed, it will add the corresponding writer. The response from the server is then passed through `Curl_client_write()` to the writers that decode it. If several encodings had been applied the writer chain decodes them in the proper order.
+
+When the server provides a `Content-Length` header, that value applies to the *compressed* content. So length checks on the response bytes must happen *before* it gets decoded. That is why this check happens in phase `CURL_CW_PROTOCOL` which always is ordered before writers in phase `CURL_CW_CONTENT_DECODE`.
+
+What else?
+
+Well, HTTP servers may also apply a `Transfer-Encoding` to the body of a response. The most well-known one is `chunked`, but algorithms like `gzip` and friends could also be applied. The difference to content encodings is that decoding needs to happen *before* protocol checks, for example on length, are done.
+
+That is why transfer decoding writers are added for phase `CURL_CW_TRANSFER_DECODE`. Which makes their operation happen *before* phase `CURL_CW_PROTOCOL` where length may be checked.
+
+## Summary
+
+By adding the common behavior of all protocols into `Curl_client_write()` we make sure that they do apply everywhere. Protocol handler have less to worry about. Changes to default behavior can be done without affecting handler implementations.
+
+Having a writer chain as implementation allows protocol handlers with extra needs, like HTTP, to add to this for special behavior. The common way of writing the actual response data stays the same.
+
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index dd2c6dc74..9c0b37691 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -22,5 +22,9 @@
#
###########################################################################
#add_subdirectory(examples)
-add_subdirectory(libcurl)
-add_subdirectory(cmdline-opts)
+if(BUILD_LIBCURL_DOCS)
+ add_subdirectory(libcurl)
+endif()
+if(ENABLE_CURL_MANUAL AND BUILD_CURL_EXE)
+ add_subdirectory(cmdline-opts)
+endif()
diff --git a/docs/CODE_STYLE.md b/docs/CODE_STYLE.md
index 9cdf0d17e..e6af36093 100644
--- a/docs/CODE_STYLE.md
+++ b/docs/CODE_STYLE.md
@@ -221,7 +221,7 @@ too long, the statement too hard to read, or due to other style guidelines
above. In such a case the statement will span multiple lines.
If a continuation line is part of an expression or sub-expression then you
-should align on the appropriate column so that it's easy to tell what part of
+should align on the appropriate column so that it is easy to tell what part of
the statement it is. Operators should not start continuation lines. In other
cases follow the 2-space indent guideline. Here are some examples from
libcurl:
diff --git a/docs/CONNECTION-FILTERS.md b/docs/CONNECTION-FILTERS.md
index c4b11dbb0..a145d42c0 100644
--- a/docs/CONNECTION-FILTERS.md
+++ b/docs/CONNECTION-FILTERS.md
@@ -1,16 +1,26 @@
# curl connection filters
-Connection filters is a design in the internals of curl, not visible in its public API. They were added
-in curl v7.xx.x. This document describes the concepts, its high level implementation and the motivations.
+Connection filters is a design in the internals of curl, not visible in its
+public API. They were added in curl v7.87.0. This document describes the
+concepts, its high level implementation and the motivations.
## Filters
-A "connection filter" is a piece of code that is responsible for handling a range of operations
-of curl's connections: reading, writing, waiting on external events, connecting and closing down - to name the most important ones.
+A "connection filter" is a piece of code that is responsible for handling a
+range of operations of curl's connections: reading, writing, waiting on
+external events, connecting and closing down - to name the most important
+ones.
-The most important feat of connection filters is that they can be stacked on top of each other (or "chained" if you prefer that metaphor). In the common scenario that you want to retrieve a `https:` url with curl, you need 2 basic things to send the request and get the response: a TCP connection, represented by a `socket` and a SSL instance en- and decrypt over that socket. You write your request to the SSL instance, which encrypts and writes that data to the socket, which then sends the bytes over the network.
+The most important feat of connection filters is that they can be stacked on
+top of each other (or "chained" if you prefer that metaphor). In the common
+scenario that you want to retrieve a `https:` URL with curl, you need 2 basic
+things to send the request and get the response: a TCP connection, represented
+by a `socket` and a SSL instance en- and decrypt over that socket. You write
+your request to the SSL instance, which encrypts and writes that data to the
+socket, which then sends the bytes over the network.
-With connection filters, curl's internal setup will look something like this (cf for connection filter):
+With connection filters, curl's internal setup will look something like this
+(cf for connection filter):
```
Curl_easy *data connectdata *conn cf-ssl cf-socket
@@ -27,7 +37,7 @@ While connection filters all do different things, they look the same from the "o
Same is true for filters. Each filter has a pointer to the `next` filter. When SSL has encrypted the data, it does not write to a socket, it writes to the next filter. If that is indeed a socket, or a file, or an HTTP/2 connection is of no concern to the SSL filter.
-And this allows the stacking, as in:
+This allows stacking, as in:
```
Direct:
@@ -110,18 +120,123 @@ The `recv` implementation is equivalent.
## Filter Types
-The (currently) existing filter types are: SOCKET, SOCKET-ACCEPT, SSL, HTTP-PROXY and SOCKS-PROXY. Vital to establishing and read/writing a connection. But filters are also a good way to implement tasks for *managing* a connection:
+The currently existing filter types (curl 8.5.0) are:
-* **Statistics**: a filter that counts the number of bytes sent/received. Place one in front of SOCKET and one higher up and get the number of raw and "easy" bytes transferred. They may track the speed as well, or number of partial writes, etc.
-* **Timeout**: enforce timeouts, e.g. fail if a connection cannot be established in a certain amount of time.
-* **Progress**: report progress on a connection.
-* **Pacing**: limit read/write rates.
-* **Testing**: simulate network condition or failures.
+* `TCP`, `UDP`, `UNIX`: filters that operate on a socket, providing raw I/O.
+* `SOCKET-ACCEPT`: special TCP socket that has a socket that has been `accept()`ed in a `listen()`
+* `SSL`: filter that applies TLS en-/decryption and handshake. Manages the underlying TLS backend implementation.
+* `HTTP-PROXY`, `H1-PROXY`, `H2-PROXY`: the first manages the connection to an
+ HTTP proxy server and uses the other depending on which ALPN protocol has
+ been negotiated.
+* `SOCKS-PROXY`: filter for the various SOCKS proxy protocol variations
+* `HAPROXY`: filter for the protocol of the same name, providing client IP information to a server.
+* `HTTP/2`: filter for handling multiplexed transfers over an HTTP/2 connection
+* `HTTP/3`: filter for handling multiplexed transfers over an HTTP/3+QUIC connection
+* `HAPPY-EYEBALLS`: meta filter that implements IPv4/IPv6 "happy eyeballing". It creates up to 2 sub-filters that race each other for a connection.
+* `SETUP`: meta filter that manages the creation of sub-filter chains for a specific transport (e.g. TCP or QUIC).
+* `HTTPS-CONNECT`: meta filter that races a TCP+TLS and a QUIC connection against each other to determine if HTTP/1.1, HTTP/2 or HTTP/3 shall be used for a transfer.
-As you see, filters are a good way to add functionality to curl's internal handling of transfers without impact on other code.
+Meta filters are combining other filters for a specific purpose, mostly during connection establishment. Other filters like `TCP`, `UDP` and `UNIX` are only to be found at the end of filter chains. SSL filters provide encryption, of course. Protocol filters change the bytes sent and received.
-## Easy Filters?
+## Filter Flags
-Some things that curl needs to manage are not directly tied to a specific connection but the property of the `Curl_easy` handle, e.g. a particular transfer. When using HTTP/2 or HTTP/3, many transfers can use the same connection. If one wants to monitor of the transfer itself or restricting its speed alone, a connection filter is not the right place to do this.
+Filter types carry flags that inform what they do. These are (for now):
+
+* `CF_TYPE_IP_CONNECT`: this filter type talks directly to a server. This does not have to be the server the transfer wants to talk to. For example when a proxy server is used.
+* `CF_TYPE_SSL`: this filter type provides encryption.
+* `CF_TYPE_MULTIPLEX`: this filter type can manage multiple transfers in parallel.
+
+Filter types can combine these flags. For example, the HTTP/3 filter types have `CF_TYPE_IP_CONNECT`, `CF_TYPE_SSL` and `CF_TYPE_MULTIPLEX` set.
+
+Flags are useful to extrapolate properties of a connection. To check if a connection is encrypted, libcurl inspect the filter chain in place, top down, for `CF_TYPE_SSL`. If it finds `CF_TYPE_IP_CONNECT` before any `CF_TYPE_SSL`, the connection is not encrypted.
+
+For example, `conn1` is for a `http:` request using a tunnel through a HTTP/2 `https:` proxy. `conn2` is a `https:` HTTP/2 connection to the same proxy. `conn3` uses HTTP/3 without proxy. The filter chains would look like this (simplified):
+
+```
+conn1 --> `HTTP-PROXY` --> `H2-PROXY` --> `SSL` --> `TCP`
+flags: `IP_CONNECT` `SSL` `IP_CONNECT`
+
+conn2 --> `HTTP/2` --> `SSL` --> `HTTP-PROXY` --> `H2-PROXY` --> `SSL` --> `TCP`
+flags: `SSL` `IP_CONNECT` `SSL` `IP_CONNECT`
+
+conn3 --> `HTTP/3`
+flags: `SSL|IP_CONNECT`
+```
+
+Inspecting the filter chains, `conn1` is seen as unencrypted, since it contains an `IP_CONNECT` filter before any `SSL`. `conn2` is clearly encrypted as an `SSL` flagged filter is seen first. `conn3` is also encrypted as the `SSL` flag is checked before the presence of `IP_CONNECT`.
+
+Similar checks can determine if a connection is multiplexed or not.
+
+## Filter Tracing
+
+Filters may make use of special trace macros like `CURL_TRC_CF(data, cf, msg, ...)`. With `data` being the transfer and `cf` being the filter instance. These traces are normally not active and their execution is guarded so that they are cheap to ignore.
+
+Users of `curl` may activate them by adding the name of the filter type to the
+`--trace-config` argument. For example, in order to get more detailed tracing
+of an HTTP/2 request, invoke curl with:
+
+```
+> curl -v --trace-config ids,time,http/2 https://curl.se
+```
+Which will give you trace output with time information, transfer+connection ids and details from the `HTTP/2` filter. Filter type names in the trace config are case insensitive. You may use `all` to enable tracing for all filter types. When using `libcurl` you may call `curl_global_trace(config_string)` at the start of your application to enable filter details.
+
+## Meta Filters
+
+Meta filters is a catch-all name for filter types that do not change the transfer data in any way but provide other important services to curl. In general, it is possible to do all sorts of silly things with them. One of the commonly used, important things is "eyeballing".
+
+The `HAPPY-EYEBALLS` filter is involved in the connect phase. Its job is to
+try the various IPv4 and IPv6 addresses that are known for a server. If only
+one address family is known (or configured), it tries the addresses one after
+the other with timeouts calculated from the amount of addresses and the
+overall connect timeout.
+
+When more than one address family is to be tried, it splits the address list into IPv4 and IPv6 and makes parallel attempts. The connection filter chain will look like this:
+
+```
+* create connection for http://curl.se
+conn[curl.se] --> SETUP[TCP] --> HAPPY-EYEBALLS --> NULL
+* start connect
+conn[curl.se] --> SETUP[TCP] --> HAPPY-EYEBALLS --> NULL
+ - ballerv4 --> TCP[151.101.1.91]:443
+ - ballerv6 --> TCP[2a04:4e42:c00::347]:443
+* v6 answers, connected
+conn[curl.se] --> SETUP[TCP] --> HAPPY-EYEBALLS --> TCP[2a04:4e42:c00::347]:443
+* transfer
+```
+
+The modular design of connection filters and that we can plug them into each other is used to control the parallel attempts. When a `TCP` filter does not connect (in time), it is torn down and another one is created for the next address. This keeps the `TCP` filter simple.
+
+The `HAPPY-EYEBALLS` on the other hand stays focused on its side of the problem. We can use it also to make other type of connection by just giving it another filter type to try and have happy eyeballing for QUIC:
+
+```
+* create connection for --http3-only https://curl.se
+conn[curl.se] --> SETUP[QUIC] --> HAPPY-EYEBALLS --> NULL
+* start connect
+conn[curl.se] --> SETUP[QUIC] --> HAPPY-EYEBALLS --> NULL
+ - ballerv4 --> HTTP/3[151.101.1.91]:443
+ - ballerv6 --> HTTP/3[2a04:4e42:c00::347]:443
+* v6 answers, connected
+conn[curl.se] --> SETUP[QUIC] --> HAPPY-EYEBALLS --> HTTP/3[2a04:4e42:c00::347]:443
+* transfer
+```
+
+When we plug these two variants together, we get the `HTTPS-CONNECT` filter
+type that is used for `--http3` when **both** HTTP/3 and HTTP/2 or HTTP/1.1
+shall be attempted:
+
+```
+* create connection for --http3 https://curl.se
+conn[curl.se] --> HTTPS-CONNECT --> NULL
+* start connect
+conn[curl.se] --> HTTPS-CONNECT --> NULL
+ - SETUP[QUIC] --> HAPPY-EYEBALLS --> NULL
+ - ballerv4 --> HTTP/3[151.101.1.91]:443
+ - ballerv6 --> HTTP/3[2a04:4e42:c00::347]:443
+ - SETUP[TCP] --> HAPPY-EYEBALLS --> NULL
+ - ballerv4 --> TCP[151.101.1.91]:443
+ - ballerv6 --> TCP[2a04:4e42:c00::347]:443
+* v4 QUIC answers, connected
+conn[curl.se] --> HTTPS-CONNECT --> SETUP[QUIC] --> HAPPY-EYEBALLS --> HTTP/3[151.101.1.91]:443
+* transfer
+```
-So we might add "easy filters" one day. Who knows?
diff --git a/docs/CONTRIBUTE.md b/docs/CONTRIBUTE.md
index 72d319001..29d98cf10 100644
--- a/docs/CONTRIBUTE.md
+++ b/docs/CONTRIBUTE.md
@@ -101,9 +101,9 @@ archive is quite OK as well.
### Documentation
Writing docs is dead boring and one of the big problems with many open source
-projects. But someone's gotta do it. It makes things a lot easier if you
-submit a small description of your fix or your new features with every
-contribution so that it can be swiftly added to the package documentation.
+projects but someone's gotta do it. It makes things a lot easier if you submit
+a small description of your fix or your new features with every contribution
+so that it can be swiftly added to the package documentation.
The documentation is always made in man pages (nroff formatted) or plain
ASCII files. All HTML files on the website and in the release archives are
@@ -116,7 +116,7 @@ features are working as they are supposed to. To maintain this situation and
improve it, all new features and functions that are added need to be tested
in the test suite. Every feature that is added should get at least one valid
test case that verifies that it works as documented. If every submitter also
-posts a few test cases, it will not end up as a heavy burden on a single person!
+posts a few test cases, it will not end up as a heavy burden on a single person.
If you do not have test cases or perhaps you have done something that is hard
to write tests for, do explain exactly how you have otherwise tested and
@@ -240,10 +240,10 @@ make sure that you have your own user and email setup correctly in git before
you commit.
Add whichever header lines as appropriate, with one line per person if more
-than one person was involved. There is no need to credit yourself unless you are
-using --author=... which hides your identity. Do not include people's e-mail
-addresses in headers to avoid spam, unless they are already public from a
-previous commit; saying `{userid} on github` is OK.
+than one person was involved. There is no need to credit yourself unless you
+are using --author=... which hides your identity. Do not include people's
+email addresses in headers to avoid spam, unless they are already public from
+a previous commit; saying `{userid} on github` is OK.
### Write Access to git Repository
diff --git a/docs/CURLDOWN.md b/docs/CURLDOWN.md
new file mode 100644
index 000000000..2e89eed6a
--- /dev/null
+++ b/docs/CURLDOWN.md
@@ -0,0 +1,125 @@
+# curldown
+
+A markdown-like syntax for libcurl man pages.
+
+## Purpose
+
+A text format for writing libcurl documentation in the shape of man pages.
+
+Make it easier for users to contribute and write documentation. A format that
+is easier on the eye in its source format.
+
+Make it harder to do syntactical mistakes.
+
+Use a format that allows creating man pages that end up looking exactly like
+the man pages did when we wrote them in nroff format.
+
+Take advantage of the fact that people these days are accustomed to markdown
+by using a markdown-like syntax.
+
+This allows us to fix issues in the nroff format easier since now we generate
+them. For example: escaping minus to prevent them from being turned into
+Unicode by man.
+
+Generate nroff output that looks (next to) *identical* to the previous files,
+so that the look, existing test cases, HTML conversions, existing
+infrastructure etc remain mostly intact.
+
+Contains meta-data in a structured way to allow better output (for example the
+see also information) and general awareness of what the file is about.
+
+## File extension
+
+Since curldown looks similar to markdown, we use `.md` extensions on the
+files.
+
+## Conversion
+
+Convert **from curldown to nroff** with `cd2nroff`. Generates nroff man pages.
+
+Convert **from nroff to curldown** with `nroff2cd`. This is only meant to be
+used for the initial conversion to curldown and should ideally never be needed
+again.
+
+Convert, check or clean up an existing curldown to nicer, better, cleaner
+curldown with **cd2cd**.
+
+Mass-convert all curldown files to nroff in specified directories with
+`cdall`:
+
+ cdall [dir1] [dir2] [dir3] ..
+
+## Known issues
+
+The `cd2nroff` tool does not yet handle *italics* or **bold** where the start
+and the end markers are used on separate lines.
+
+The `nroff2cd` tool generates code style quotes for all `.fi` sections since
+the nroff format does not carry a distinction.
+
+# Format
+
+Each curldown starts with a header with meta-data:
+
+ ---
+ c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+ SPDX-License-Identifier: curl
+ Title: CURLOPT_AWS_SIGV4
+ Section: 3
+ Source: libcurl
+ See-also:
+ - CURLOPT_HEADEROPT (3)
+ - CURLOPT_HTTPAUTH (3)
+ ---
+
+All curldown files *must* have all the headers present and at least one
+`See-also:` entry specified.
+
+Following the header in the file, is the manual page using markdown-like
+syntax:
+
+~~~
+ # NAME
+ a page - this is a page descriving something
+
+ # SYNOPSIS
+ ~~~c
+ #include <curl/curl.h>
+
+ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AWS_SIGV4, char *param);
+ ~~~
+~~~
+
+Quoted source code should start with `~~~c` and end with `~~~` while regular
+quotes can start with `~~~` or just be indented with 4 spaces.
+
+Headers at top-level `#` get converted to `.SH`.
+
+`nroff2cd` supports the `##` next level header which gets converted to `.IP`.
+
+Write bold words or phrases within `**` like:
+
+ This is a **bold** word.
+
+Write italics like:
+
+ This is *italics*.
+
+Due to how man pages do not support backticks especially formatted, such
+occurrences in the source will instead just use italics in the generated
+output:
+
+ This `word` appears in italics.
+
+When generating the nroff output, the tooling will remove superfluous newlines,
+meaning they can be used freely in the source file to make the text more
+readable.
+
+All mentioned curl symbols that have their own man pages, like
+`curl_easy_perform(3)` will automatically be rendered using italics in the
+output without having to enclose it with asterisks. This helps ensuring that
+they get converted to links properly later in the HTML version on the website,
+as converted with `roffit`. This makes the curldown text easier to read even
+when mentioning many curl symbols.
+
+This auto-linking works for patterns matching `(lib|)curl[^ ]*(3)`.
diff --git a/docs/DEPRECATE.md b/docs/DEPRECATE.md
index c932fadbc..fcbd92a31 100644
--- a/docs/DEPRECATE.md
+++ b/docs/DEPRECATE.md
@@ -6,6 +6,21 @@ email the
as soon as possible and explain to us why this is a problem for you and
how your use case cannot be satisfied properly using a workaround.
+## NTLM_WB auth
+
+This NTLM authentication method is powered by a separate tool,
+`ntlm_auth`. Barely anyone uses this method. It was always a quirky
+implementation (including fork + exec), it has limited portability and we do
+not test it in the test suite and CI.
+
+We keep the native NTLM implementation.
+
+Due to a mistake, the `NTLM_WB` functionality is missing in builds since 8.4.0
+(October 2023). It needs to be manually patched to work. See [PR
+12479](https://github.com/curl/curl/pull/12479).
+
+curl will remove the support for NTLM_WB auth in April 2024.
+
## space-separated `NOPROXY` patterns
When specifying patterns/domain names for curl that should *not* go through a
diff --git a/docs/EXPERIMENTAL.md b/docs/EXPERIMENTAL.md
index 6b7145df6..de694013d 100644
--- a/docs/EXPERIMENTAL.md
+++ b/docs/EXPERIMENTAL.md
@@ -19,6 +19,6 @@ Experimental support in curl means:
## Experimental features right now
- The Hyper HTTP backend
- - HTTP/3 support and options
+ - HTTP/3 support (using the quiche or msh3 backends)
- The rustls backend
- WebSocket
diff --git a/docs/FEATURES.md b/docs/FEATURES.md
index 9f763d3a7..4a589e164 100644
--- a/docs/FEATURES.md
+++ b/docs/FEATURES.md
@@ -12,11 +12,11 @@
## libcurl
- - full URL syntax with no length limit
+ - URL RFC 3986 syntax
- custom maximum download time
- custom least download speed acceptable
- custom output result after completion
- - guesses protocol from host name unless specified
+ - guesses protocol from hostname unless specified
- uses .netrc
- progress bar with time statistics while downloading
- "standard" proxy environment variables support
@@ -82,8 +82,8 @@
- active/passive using PORT, EPRT, PASV or EPSV
- single file size information (compare to HTTP HEAD)
- 'type=' URL support
- - dir listing
- - dir listing names-only
+ - directory listing
+ - directory listing names-only
- upload
- upload append
- upload via http-proxy as HTTP PUT
@@ -94,7 +94,7 @@
- via HTTP proxy, HTTPS proxy or SOCKS proxy
- all operations can be tunneled through proxy
- customizable to retrieve file modification date
- - no dir depth limit
+ - no directory depth limit
## FTPS (1)
diff --git a/docs/GOVERNANCE.md b/docs/GOVERNANCE.md
index dd09de456..0f7029e82 100644
--- a/docs/GOVERNANCE.md
+++ b/docs/GOVERNANCE.md
@@ -179,4 +179,4 @@ this.
### Stop being a maintainer
If you (appear to) not be active in the project anymore, you may be removed as
-a maintainer. Thank you for your service!
+a maintainer. Thank you for your service.
diff --git a/docs/HISTORY.md b/docs/HISTORY.md
index f39c45ea1..d28217ca6 100644
--- a/docs/HISTORY.md
+++ b/docs/HISTORY.md
@@ -327,7 +327,7 @@ April: added the cyassl backend (later renamed to WolfSSL)
January: the curl tool defaults to HTTP/2 for HTTPS URLs
- December: curl 7.52.0 introduced support for HTTPS-proxy!
+ December: curl 7.52.0 introduced support for HTTPS-proxy
First TLS 1.3 support
diff --git a/docs/HSTS.md b/docs/HSTS.md
index e54102493..5f0e62459 100644
--- a/docs/HSTS.md
+++ b/docs/HSTS.md
@@ -10,13 +10,13 @@ HTTP Strict-Transport-Security. Added as experimental in curl
## Behavior
libcurl features an in-memory cache for HSTS hosts, so that subsequent
-HTTP-only requests to a host name present in the cache will get internally
+HTTP-only requests to a hostname present in the cache will get internally
"redirected" to the HTTPS version.
## `curl_easy_setopt()` options:
- `CURLOPT_HSTS_CTRL` - enable HSTS for this easy handle
- - `CURLOPT_HSTS` - specify file name where to store the HSTS cache on close
+ - `CURLOPT_HSTS` - specify filename where to store the HSTS cache on close
(and possibly read from at startup)
## curl command line options
diff --git a/docs/HTTP-COOKIES.md b/docs/HTTP-COOKIES.md
index d6fd87d20..a91e824d5 100644
--- a/docs/HTTP-COOKIES.md
+++ b/docs/HTTP-COOKIES.md
@@ -34,6 +34,25 @@
over plain HTTP for this host. curl does this to match how popular browsers
work with secure cookies.
+## Super cookies
+
+ A single cookie can be set for a domain that matches multiple hosts. Like if
+ set for `example.com` it gets sent to both `aa.example.com` as well as
+ `bb.example.com`.
+
+ A challenge with this concept is that there are certain domains for which
+ cookies should not be allowed at all, because they are *Public
+ Suffixes*. Similarly, a client never accepts cookies set directly for the
+ top-level domain like for example `.com`. Cookies set for *too broad*
+ domains are generally referred to as *super cookies*.
+
+ If curl is built with PSL (**Public Suffix List**) support, it detects and
+ discards cookies that are specified for such suffix domains that should not
+ be allowed to have cookies.
+
+ if curl is *not* built with PSL support, it has no ability to stop super
+ cookies.
+
## Cookies saved to disk
Netscape once created a file format for storing cookies on disk so that they
diff --git a/docs/HTTP3.md b/docs/HTTP3.md
index 41d757f05..851a0c468 100644
--- a/docs/HTTP3.md
+++ b/docs/HTTP3.md
@@ -9,18 +9,21 @@ book describing the protocols involved.
## QUIC libraries
-QUIC libraries we are experimenting with:
+QUIC libraries we are using:
[ngtcp2](https://github.com/ngtcp2/ngtcp2)
-[quiche](https://github.com/cloudflare/quiche)
+[quiche](https://github.com/cloudflare/quiche) - **EXPERIMENTAL**
-[msh3](https://github.com/nibanks/msh3) (with [msquic](https://github.com/microsoft/msquic))
+[OpenSSL 3.2+ QUIC](https://github.com/openssl/openssl) - **EXPERIMENTAL**
+
+[msh3](https://github.com/nibanks/msh3) (with [msquic](https://github.com/microsoft/msquic)) - **EXPERIMENTAL**
## Experimental
-HTTP/3 and QUIC support in curl is considered **EXPERIMENTAL** until further
-notice. It needs to be enabled at build-time.
+HTTP/3 support in curl is considered **EXPERIMENTAL** until further notice
+when built to use *quiche* or *msh3*. Only the *ngtcp2* backend is not
+experimental.
Further development and tweaking of the HTTP/3 support in curl will happen in
the master branch using pull-requests, just like ordinary changes.
@@ -28,22 +31,23 @@ the master branch using pull-requests, just like ordinary changes.
To fix before we remove the experimental label:
- the used QUIC library needs to consider itself non-beta
- - it's fine to "leave" individual backends as experimental if necessary
+ - it is fine to "leave" individual backends as experimental if necessary
# ngtcp2 version
Building curl with ngtcp2 involves 3 components: `ngtcp2` itself, `nghttp3` and a QUIC supporting TLS library. The supported TLS libraries are covered below.
-For now, `ngtcp2` and `nghttp3` are still *experimental* which means their evolution bring breaking changes. Therefore, the proper version of both libraries need to be used when building curl. These are
+ * `ngtcp2`: v1.2.0
+ * `nghttp3`: v1.1.0
- * `ngtcp2`: v0.19.1
- * `nghttp3`: v0.15.0
+## Build with quictls
-## Build with OpenSSL
+OpenSSL does not offer the required APIs for building a QUIC client. You need
+to use a TLS library that has such APIs and that works with *ngtcp2*.
-Build (patched) OpenSSL
+Build quictls
- % git clone --depth 1 -b openssl-3.0.10+quic https://github.com/quictls/openssl
+ % git clone --depth 1 -b openssl-3.1.4+quic https://github.com/quictls/openssl
% cd openssl
% ./config enable-tls1_3 --prefix=<somewhere1>
% make
@@ -52,7 +56,7 @@ Build (patched) OpenSSL
Build nghttp3
% cd ..
- % git clone -b v0.15.0 https://github.com/ngtcp2/nghttp3
+ % git clone -b v1.1.0 https://github.com/ngtcp2/nghttp3
% cd nghttp3
% autoreconf -fi
% ./configure --prefix=<somewhere2> --enable-lib-only
@@ -62,7 +66,7 @@ Build nghttp3
Build ngtcp2
% cd ..
- % git clone -b v0.19.1 https://github.com/ngtcp2/ngtcp2
+ % git clone -b v1.2.0 https://github.com/ngtcp2/ngtcp2
% cd ngtcp2
% autoreconf -fi
% ./configure PKG_CONFIG_PATH=<somewhere1>/lib/pkgconfig:<somewhere2>/lib/pkgconfig LDFLAGS="-Wl,-rpath,<somewhere1>/lib" --prefix=<somewhere3> --enable-lib-only
@@ -95,7 +99,7 @@ Build GnuTLS
Build nghttp3
% cd ..
- % git clone -b v0.15.0 https://github.com/ngtcp2/nghttp3
+ % git clone -b v1.1.0 https://github.com/ngtcp2/nghttp3
% cd nghttp3
% autoreconf -fi
% ./configure --prefix=<somewhere2> --enable-lib-only
@@ -105,7 +109,7 @@ Build nghttp3
Build ngtcp2
% cd ..
- % git clone -b v0.19.1 https://github.com/ngtcp2/ngtcp2
+ % git clone -b v1.2.0 https://github.com/ngtcp2/ngtcp2
% cd ngtcp2
% autoreconf -fi
% ./configure PKG_CONFIG_PATH=<somewhere1>/lib/pkgconfig:<somewhere2>/lib/pkgconfig LDFLAGS="-Wl,-rpath,<somewhere1>/lib" --prefix=<somewhere3> --enable-lib-only --with-gnutls
@@ -136,7 +140,7 @@ Build wolfSSL
Build nghttp3
% cd ..
- % git clone -b v0.15.0 https://github.com/ngtcp2/nghttp3
+ % git clone -b v1.1.0 https://github.com/ngtcp2/nghttp3
% cd nghttp3
% autoreconf -fi
% ./configure --prefix=<somewhere2> --enable-lib-only
@@ -146,7 +150,7 @@ Build nghttp3
Build ngtcp2
% cd ..
- % git clone -b v0.19.1 https://github.com/ngtcp2/ngtcp2
+ % git clone -b v1.2.0 https://github.com/ngtcp2/ngtcp2
% cd ngtcp2
% autoreconf -fi
% ./configure PKG_CONFIG_PATH=<somewhere1>/lib/pkgconfig:<somewhere2>/lib/pkgconfig LDFLAGS="-Wl,-rpath,<somewhere1>/lib" --prefix=<somewhere3> --enable-lib-only --with-wolfssl
@@ -165,13 +169,15 @@ Build curl
# quiche version
+quiche support is **EXPERIMENTAL**
+
Since the quiche build manages its dependencies, curl can be built against the latest version. You are *probably* able to build against their main branch, but in case of problems, we recommend their latest release tag.
## build
Build quiche and BoringSSL:
- % git clone --recursive https://github.com/cloudflare/quiche
+ % git clone --recursive -b 0.20.0 https://github.com/cloudflare/quiche
% cd quiche
% cargo build --package quiche --release --features ffi,pkg-config-meta,qlog
% mkdir quiche/deps/boringssl/src/lib
@@ -189,12 +195,48 @@ Build curl:
If `make install` results in `Permission denied` error, you will need to prepend it with `sudo`.
+# OpenSSL version
+
+quiche QUIC support is **EXPERIMENTAL**
+
+Build OpenSSL 3.2.0
+
+ % cd ..
+ % git clone -b openssl-3.2.0 https://github.com/openssl/openssl
+ % cd openssl
+ % ./config enable-tls1_3 --prefix=<somewhere> --libdir=<somewhere>/lib
+ % make install
+
+Build nghttp3
+
+ % cd ..
+ % git clone -b v1.1.0 https://github.com/ngtcp2/nghttp3
+ % cd nghttp3
+ % autoreconf -fi
+ % ./configure --prefix=<somewhere2> --enable-lib-only
+ % make
+ % make install
+
+Build curl:
+
+ % cd ..
+ % git clone https://github.com/curl/curl
+ % cd curl
+ % autoreconf -fi
+ % ./configure --with-openssl=<somewhere> --with-openssl-quic --with-nghttp3=<somewhere2>
+ % make
+ % make install
+
+ If `make install` results in `Permission denied` error, you will need to prepend it with `sudo`.
+
# msh3 (msquic) version
**Note**: The msquic HTTP/3 backend is immature and is not properly functional
one as of September 2023. Feel free to help us test it and improve it, but
there is no point in filing bugs about it just yet.
+msh3 support is **EXPERIMENTAL**
+
## Build Linux (with quictls fork of OpenSSL)
Build msh3:
@@ -299,9 +341,9 @@ handshake or time out.
Note that all this happens in addition to IP version happy eyeballing. If the
name resolution for the server gives more than one IP address, curl will try
-all those until one succeeds - just as with all other protocols. And if those
-IP addresses contain both IPv6 and IPv4, those attempts will happen, delayed,
-in parallel (the actual eyeballing).
+all those until one succeeds - just as with all other protocols. If those IP
+addresses contain both IPv6 and IPv4, those attempts will happen, delayed, in
+parallel (the actual eyeballing).
## Known Bugs
diff --git a/docs/HYPER.md b/docs/HYPER.md
index 1c3b0dded..9932c1bbf 100644
--- a/docs/HYPER.md
+++ b/docs/HYPER.md
@@ -57,6 +57,10 @@ The hyper backend does not support
- leading whitespace in first HTTP/1 response header
- HTTP/0.9
- HTTP/2 upgrade using HTTP:// URLs. Aka 'h2c'
+- HTTP/2 in general. Hyper has support for HTTP/2 but the curl side
+ needs changes so that a `hyper_clientconn` can last for the duration
+ of a connection. Probably this means turning the Hyper HTTP/2 backend
+ into a connection filter.
## Remaining issues
diff --git a/docs/INSTALL-CMAKE.md b/docs/INSTALL-CMAKE.md
new file mode 100644
index 000000000..6dad38740
--- /dev/null
+++ b/docs/INSTALL-CMAKE.md
@@ -0,0 +1,133 @@
+ _ _ ____ _
+ ___| | | | _ \| |
+ / __| | | | |_) | |
+ | (__| |_| | _ <| |___
+ \___|\___/|_| \_\_____|
+
+ How To Compile with CMake
+
+# Building with CMake
+
+This document describes how to configure, build and install curl and libcurl
+from source code using the CMake build tool. To build with CMake, you will
+of course have to first install CMake. The minimum required version of CMake
+is specified in the file `CMakeLists.txt` found in the top of the curl
+source tree. Once the correct version of CMake is installed you can follow
+the instructions below for the platform you are building on.
+
+CMake builds can be configured either from the command line, or from one of
+CMake's GUIs.
+
+# Current flaws in the curl CMake build
+
+Missing features in the CMake build:
+
+ - Builds libcurl without large file support
+ - Does not support all SSL libraries (only OpenSSL, Schannel, Secure
+ Transport, and mbedTLS, WolfSSL)
+ - Does not allow different resolver backends (no c-ares build support)
+ - No RTMP support built
+ - Does not allow build curl and libcurl debug enabled
+ - Does not allow a custom CA bundle path
+ - Does not allow you to disable specific protocols from the build
+ - Does not find or use krb4 or GSS
+ - Rebuilds test files too eagerly, but still cannot run the tests
+ - Does not detect the correct `strerror_r` flavor when cross-compiling
+ (issue #1123)
+
+# Configuring
+
+A CMake configuration of curl is similar to the autotools build of curl.
+It consists of the following steps after you have unpacked the source.
+
+## Using `cmake`
+
+You can configure for in source tree builds or for a build tree
+that is apart from the source tree.
+
+ - Build in the source tree.
+
+ $ cmake -B .
+
+ - Build in a separate directory (parallel to the curl source tree in this
+ example). The build directory will be created for you.
+
+ $ cmake -B ../curl-build
+
+### Fallback for CMake before version 3.13
+
+CMake before version 3.13 does not support the `-B` option. In that case,
+you must create the build directory yourself, `cd` to it and run `cmake`
+from there:
+
+ $ mkdir ../curl-build
+ $ cd ../curl-build
+ $ cmake ../curl
+
+If you want to build in the source tree, it is enough to do this:
+
+ $ cmake .
+
+## Using `ccmake`
+
+CMake comes with a curses based interface called `ccmake`. To run `ccmake`
+on a curl use the instructions for the command line cmake, but substitute
+`ccmake` for `cmake`.
+
+This will bring up a curses interface with instructions on the bottom of the
+screen. You can press the "c" key to configure the project, and the "g" key
+to generate the project. After the project is generated, you can run make.
+
+## Using `cmake-gui`
+
+CMake also comes with a Qt based GUI called `cmake-gui`. To configure with
+`cmake-gui`, you run `cmake-gui` and follow these steps:
+
+ 1. Fill in the "Where is the source code" combo box with the path to
+ the curl source tree.
+ 2. Fill in the "Where to build the binaries" combo box with the path to
+ the directory for your build tree, ideally this should not be the same
+ as the source tree, but a parallel directory called curl-build or
+ something similar.
+ 3. Once the source and binary directories are specified, press the
+ "Configure" button.
+ 4. Select the native build tool that you want to use.
+ 5. At this point you can change any of the options presented in the GUI.
+ Once you have selected all the options you want, click the "Generate"
+ button.
+
+# Building
+
+Build (you have to specify the build directory).
+
+ $ cmake --build ../curl-build
+
+### Fallback for CMake before version 3.13
+
+CMake before version 3.13 does not support the `--build` option. In that
+case, you have to `cd` to the build directory and use the building tool that
+corresponds to the build files that CMake generated for you. This example
+assumes that CMake generates `Makefile`:
+
+ $ cd ../curl-build
+ $ make
+
+# Testing
+
+(The test suite does not yet work with the cmake build)
+
+# Installing
+
+Install to default location (you have to specify the build directory).
+
+ $ cmake --install ../curl-build
+
+### Fallback for CMake before version 3.15
+
+CMake before version 3.15 does not support the `--install` option. In that
+case, you have to `cd` to the build directory and use the building tool that
+corresponds to the build files that CMake generated for you. This example
+assumes that CMake generates `Makefile`:
+
+ $ cd ../curl-build
+ $ make install
diff --git a/docs/INSTALL.cmake b/docs/INSTALL.cmake
deleted file mode 100644
index 4e7f706a9..000000000
--- a/docs/INSTALL.cmake
+++ /dev/null
@@ -1,89 +0,0 @@
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
- How To Compile with CMake
-
-Building with CMake
-==========================
- This document describes how to compile, build and install curl and libcurl
- from source code using the CMake build tool. To build with CMake, you will
- of course have to first install CMake. The minimum required version of
- CMake is specified in the file CMakeLists.txt found in the top of the curl
- source tree. Once the correct version of CMake is installed you can follow
- the instructions below for the platform you are building on.
-
- CMake builds can be configured either from the command line, or from one
- of CMake's GUI's.
-
-Current flaws in the curl CMake build
-=====================================
-
- Missing features in the cmake build:
-
- - Builds libcurl without large file support
- - Does not support all SSL libraries (only OpenSSL, Schannel,
- Secure Transport, and mbedTLS, WolfSSL)
- - Does not allow different resolver backends (no c-ares build support)
- - No RTMP support built
- - Does not allow build curl and libcurl debug enabled
- - Does not allow a custom CA bundle path
- - Does not allow you to disable specific protocols from the build
- - Does not find or use krb4 or GSS
- - Rebuilds test files too eagerly, but still cannot run the tests
- - Does not detect the correct strerror_r flavor when cross-compiling (issue #1123)
-
-
-Command Line CMake
-==================
- A CMake build of curl is similar to the autotools build of curl. It
- consists of the following steps after you have unpacked the source.
-
- 1. Create an out of source build tree parallel to the curl source
- tree and change into that directory
-
- $ mkdir curl-build
- $ cd curl-build
-
- 2. Run CMake from the build tree, giving it the path to the top of
- the curl source tree. CMake will pick a compiler for you. If you
- want to specify the compile, you can set the CC environment
- variable prior to running CMake.
-
- $ cmake ../curl
- $ make
-
- 3. Install to default location:
-
- $ make install
-
- (The test suite does not work with the cmake build)
-
-ccmake
-=========
- CMake comes with a curses based interface called ccmake. To run ccmake on
- a curl use the instructions for the command line cmake, but substitute
- ccmake ../curl for cmake ../curl. This will bring up a curses interface
- with instructions on the bottom of the screen. You can press the "c" key
- to configure the project, and the "g" key to generate the project. After
- the project is generated, you can run make.
-
-cmake-gui
-=========
- CMake also comes with a Qt based GUI called cmake-gui. To configure with
- cmake-gui, you run cmake-gui and follow these steps:
- 1. Fill in the "Where is the source code" combo box with the path to
- the curl source tree.
- 2. Fill in the "Where to build the binaries" combo box with the path
- to the directory for your build tree, ideally this should not be the
- same as the source tree, but a parallel directory called curl-build or
- something similar.
- 3. Once the source and binary directories are specified, press the
- "Configure" button.
- 4. Select the native build tool that you want to use.
- 5. At this point you can change any of the options presented in the
- GUI. Once you have selected all the options you want, click the
- "Generate" button.
- 6. Run the native build tool that you used CMake to generate.
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 7e3a2698d..336d654e0 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -123,8 +123,8 @@ If you are a curl developer and use gcc, you might want to enable more debug
options with the `--enable-debug` option.
curl can be built to use a whole range of libraries to provide various useful
-services, and configure will try to auto-detect a decent default. But if you
-want to alter it, you can select how to deal with each individual library.
+services, and configure will try to auto-detect a decent default. If you want
+to alter it, you can select how to deal with each individual library.
## Select TLS backend
@@ -146,7 +146,7 @@ you cannot add another OpenSSL fork (or wolfSSL) simply because they have
conflicting identical symbol names.
When you build with multiple TLS backends, you can select the active one at
-run-time when curl starts up.
+runtime when curl starts up.
## configure finding libs in wrong directory
@@ -162,6 +162,8 @@ library check.
# Windows
+Building for Windows XP is required as a minimum.
+
## Building Windows DLLs and C runtime (CRT) linkage issues
As a general rule, building a DLL with static CRT linkage is highly
@@ -172,8 +174,8 @@ library check.
KB140584 is a must for any Windows developer. Especially important is full
understanding if you are not going to follow the advice given above.
- - [How To Use the C Run-Time](https://support.microsoft.com/help/94248/how-to-use-the-c-run-time)
- - [Run-Time Library Compiler Options](https://docs.microsoft.com/cpp/build/reference/md-mt-ld-use-run-time-library)
+ - [How To Use the C Runtime](https://support.microsoft.com/help/94248/how-to-use-the-c-run-time)
+ - [Runtime Library Compiler Options](https://docs.microsoft.com/cpp/build/reference/md-mt-ld-use-run-time-library)
- [Potential Errors Passing CRT Objects Across DLL Boundaries](https://docs.microsoft.com/cpp/c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries)
If your app is misbehaving in some strange way, or it is suffering from memory
@@ -183,54 +185,6 @@ multi-threaded dynamic C runtime.
If you get linkage errors read section 5.7 of the FAQ document.
-## mingw-w64
-
-Make sure that mingw-w64's bin directory is in the search path, for example:
-
-```cmd
-set PATH=c:\mingw-w64\bin;%PATH%
-```
-
-then run `mingw32-make mingw32` in the root dir. There are other
-make targets available to build libcurl with more features, use:
-
- - `mingw32-make mingw32-zlib` to build with Zlib support;
- - `mingw32-make mingw32-ssl-zlib` to build with SSL and Zlib enabled;
- - `mingw32-make mingw32-ssh2-ssl-zlib` to build with SSH2, SSL, Zlib;
- - `mingw32-make mingw32-ssh2-ssl-sspi-zlib` to build with SSH2, SSL, Zlib
- and SSPI support.
-
-If you have any problems linking libraries or finding header files, be sure
-to verify that the provided `Makefile.mk` files use the proper paths, and
-adjust as necessary. It is also possible to override these paths with
-environment variables, for example:
-
-```cmd
-set ZLIB_PATH=c:\zlib-1.2.12
-set OPENSSL_PATH=c:\openssl-3.0.5
-set LIBSSH2_PATH=c:\libssh2-1.10.0
-```
-
-It is also possible to build with other LDAP installations than MS LDAP;
-currently it is possible to build with native Win32 OpenLDAP, or with the
-*Novell CLDAP* SDK. If you want to use these you need to set these vars:
-
-```cmd
-set CPPFLAGS=-Ic:/openldap/include -DCURL_HAS_OPENLDAP_LDAPSDK
-set LDFLAGS=-Lc:/openldap/lib
-set LIBS=-lldap -llber
-```
-
-or for using the Novell SDK:
-
-```cmd
-set CPPFLAGS=-Ic:/openldapsdk/inc -DCURL_HAS_NOVELL_LDAPSDK
-set LDFLAGS=-Lc:/openldapsdk/lib/mscvc
-set LIBS=-lldapsdk -lldapssl -lldapx
-```
-
-If you want to enable LDAPS support then append `-ldaps` to the make target.
-
## Cygwin
Almost identical to the Unix installation. Run the configure script in the
@@ -386,14 +340,14 @@ In all above, the built libraries and executables can be found in the
# Android
-When building curl for Android it's recommended to use a Linux/macOS environment
-since using curl's `configure` script is the easiest way to build curl
-for Android. Before you can build curl for Android, you need to install the
-Android NDK first. This can be done using the SDK Manager that is part of
-Android Studio. Once you have installed the Android NDK, you need to figure out
-where it has been installed and then set up some environment variables before
-launching `configure`. On macOS, those variables could look like this to compile
-for `aarch64` and API level 29:
+When building curl for Android it is recommended to use a Linux/macOS
+environment since using curl's `configure` script is the easiest way to build
+curl for Android. Before you can build curl for Android, you need to install
+the Android NDK first. This can be done using the SDK Manager that is part of
+Android Studio. Once you have installed the Android NDK, you need to figure
+out where it has been installed and then set up some environment variables
+before launching `configure`. On macOS, those variables could look like this
+to compile for `aarch64` and API level 29:
```bash
export ANDROID_NDK_HOME=~/Library/Android/sdk/ndk/25.1.8937393 # Point into your NDK.
@@ -413,13 +367,13 @@ to adjust those variables accordingly. After that you can build curl like this:
./configure --host aarch64-linux-android --with-pic --disable-shared
-Note that this will not give you SSL/TLS support. If you need SSL/TLS, you have
-to build curl against a SSL/TLS layer, e.g. OpenSSL, because it's impossible for
-curl to access Android's native SSL/TLS layer. To build curl for Android using
-OpenSSL, follow the OpenSSL build instructions and then install `libssl.a` and
-`libcrypto.a` to `$TOOLCHAIN/sysroot/usr/lib` and copy `include/openssl` to
-`$TOOLCHAIN/sysroot/usr/include`. Now you can build curl for Android using
-OpenSSL like this:
+Note that this will not give you SSL/TLS support. If you need SSL/TLS, you
+have to build curl against a SSL/TLS layer, e.g. OpenSSL, because it is
+impossible for curl to access Android's native SSL/TLS layer. To build curl
+for Android using OpenSSL, follow the OpenSSL build instructions and then
+install `libssl.a` and `libcrypto.a` to `$TOOLCHAIN/sysroot/usr/lib` and copy
+`include/openssl` to `$TOOLCHAIN/sysroot/usr/include`. Now you can build curl
+for Android using OpenSSL like this:
```bash
LIBS="-lssl -lcrypto -lc++" # For OpenSSL/BoringSSL. In general, you will need to the SSL/TLS layer's transitive dependencies if you are linking statically.
@@ -524,7 +478,12 @@ disabling support for some feature:
- `--disable-alt-svc` (HTTP Alt-Svc)
- `--disable-ares` (the C-ARES DNS library)
- `--disable-cookies` (HTTP cookies)
- - `--disable-crypto-auth` (cryptographic authentication)
+ - `--disable-basic-auth` (cryptographic authentication)
+ - `--disable-bearer-auth` (cryptographic authentication)
+ - `--disable-digest-auth` (cryptographic authentication)
+ - `--disable-kerberos-auth` (cryptographic authentication)
+ - `--disable-negotiate-auth` (cryptographic authentication)
+ - `--disable-aws` (cryptographic authentication)
- `--disable-dateparse` (date parsing for time conditionals)
- `--disable-dnsshuffle` (internal server load spreading)
- `--disable-doh` (DNS-over-HTTP)
@@ -589,29 +548,29 @@ that are not automatically detected:
- `--disable-libcurl-option` !`--libcurl`
- `--disable-verbose` !verbose\ logs
-# PORTS
+# Ports
This is a probably incomplete list of known CPU architectures and operating
systems that curl has been compiled for. If you know a system curl compiles
and runs on, that is not listed, please let us know!
-## 92 Operating Systems
+## 101 Operating Systems
- AIX, AmigaOS, Android, Aros, BeOS, Blackberry 10, Blackberry Tablet OS,
- Cell OS, Chrome OS, Cisco IOS, Cygwin, DG/UX, Dragonfly BSD, DR DOS, eCOS,
- FreeBSD, FreeDOS, FreeRTOS, Fuchsia, Garmin OS, Genode, Haiku, HardenedBSD,
- HP-UX, Hurd, Illumos, Integrity, iOS, ipadOS, IRIX, Linux, Lua RTOS,
- Mac OS 9, macOS, Mbed, Micrium, MINIX, MorphOS, MPE/iX, MS-DOS, NCR MP-RAS,
- NetBSD, Netware, Nintendo Switch, NonStop OS, NuttX, Omni OS, OpenBSD,
- OpenStep, Orbis OS, OS/2, OS/400, OS21, Plan 9, PlayStation Portable, QNX,
- Qubes OS, ReactOS, Redox, RICS OS, RTEMS, Sailfish OS, SCO Unix, Serenity,
- SINIX-Z, Solaris, SunOS, Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS,
- ucLinux, Ultrix, UNICOS, UnixWare, VMS, vxWorks, watchOS, WebOS,
- Wii system software, Windows, Windows CE, Xbox System, Xenix, Zephyr,
- z/OS, z/TPF, z/VM, z/VSE
+ AIX, AmigaOS, Android, ArcoOS, Aros, Atari FreeMiNT, BeOS, Blackberry 10,
+ Blackberry Tablet OS, Cell OS, CheriBSD, Chrome OS, Cisco IOS, DG/UX,
+ Dragonfly BSD, DR DOS, eCOS, FreeBSD, FreeDOS, FreeRTOS, Fuchsia, Garmin OS,
+ Genode, Haiku, HardenedBSD, HP-UX, Hurd, Illumos, Integrity, iOS, ipadOS, IRIX,
+ Linux, Lua RTOS, Mac OS 9, macOS, Mbed, Meego, Micrium, MINIX, Moblin, MorphOS,
+ MPE/iX, MS-DOS, NCR MP-RAS, NetBSD, Netware, NextStep, Nintendo Switch,
+ NonStop OS, NuttX, OpenBSD, OpenStep, Orbis OS, OS/2, OS/400, OS21, Plan 9,
+ PlayStation Portable, QNX, Qubes OS, ReactOS, Redox, RICS OS, ROS, RTEMS,
+ Sailfish OS, SCO Unix, Serenity, SINIX-Z, SkyOS, Solaris, Sortix, SunOS,
+ Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS, ucLinux, Ultrix, UNICOS,
+ UnixWare, VMS, vxWorks, watchOS, Wear OS, WebOS, Wii system software, Wii U,
+ Windows, Windows CE, Xbox System, Xenix, Zephyr, z/OS, z/TPF, z/VM, z/VSE
-## 26 CPU Architectures
+## 28 CPU Architectures
- Alpha, ARC, ARM, AVR32, CompactRISC, Elbrus, ETRAX, HP-PA, Itanium,
+ Alpha, ARC, ARM, AVR32, C-SKY, CompactRISC, Elbrus, ETRAX, HP-PA, Itanium,
LoongArch, m68k, m88k, MicroBlaze, MIPS, Nios, OpenRISC, POWER, PowerPC,
- RISC-V, s390, SH4, SPARC, Tilera, VAX, x86, Xtensa
+ RISC-V, s390, SH4, SPARC, Tilera, VAX, x86, Xtensa, z/arch
diff --git a/docs/IPFS.md b/docs/IPFS.md
index be8c597d9..aa3fb278c 100644
--- a/docs/IPFS.md
+++ b/docs/IPFS.md
@@ -19,12 +19,29 @@ By explicitly requesting [application/vnd.ipld.raw](https://www.iana.org/assignm
This enables users to use untrusted, public gateways without worrying they might return invalid/malicious bytes.
## IPFS and IPNS protocol handling
-There are various ways to access data from the IPFS network. One such way is through the concept of public "[gateways](https://docs.ipfs.tech/concepts/ipfs-gateway/#overview)". The short version is that entities can offer gateway services. An example here that is hosted by Protocol Labs (who also makes IPFS) is `dweb.link` and `ipfs.io`. Both sites expose gateway functionality. Getting a file through `ipfs.io` looks like this: `https://ipfs.io/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi`
-If you were to be [running your own IPFS node](https://docs.ipfs.tech/how-to/command-line-quick-start/) then you, by default, also have a [local gateway](https://specs.ipfs.tech/http-gateways/) running. In it's default configuration the earlier example would then also work in this link: `http://127.0.0.1:8080/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi`
+There are various ways to access data from the IPFS network. One such way is
+through the concept of public
+"[gateways](https://docs.ipfs.tech/concepts/ipfs-gateway/#overview)". The
+short version is that entities can offer gateway services. An example here
+that is hosted by Protocol Labs (who also makes IPFS) is `dweb.link` and
+`ipfs.io`. Both sites expose gateway functionality. Getting a file through
+`ipfs.io` looks like this:
+`https://ipfs.io/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi`
+
+If you were to be [running your own IPFS
+node](https://docs.ipfs.tech/how-to/command-line-quick-start/) then you, by
+default, also have a [local gateway](https://specs.ipfs.tech/http-gateways/)
+running. In its default configuration the earlier example would then also work
+in this link:
+
+`http://127.0.0.1:8080/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi`
## cURL handling of the IPFS protocols
-The IPFS integration in cURL hides this gateway logic for you. So instead of providing a full URL to a file on IPFS like this:
+
+The IPFS integration in cURL hides this gateway logic for you. Instead of
+providing a full URL to a file on IPFS like this:
+
```
curl http://127.0.0.1:8080/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi
```
@@ -34,49 +51,75 @@ You can provide it with the IPFS protocol instead:
curl ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi
```
-With the IPFS protocol way of asking a file, cURL still needs to know the gateway. curl essentially just rewrites the IPFS based URL to a gateway URL.
+With the IPFS protocol way of asking a file, cURL still needs to know the
+gateway. curl essentially just rewrites the IPFS based URL to a gateway URL.
### IPFS_GATEWAY environment variable
-If the `IPFS_GATEWAY` environment variable is found, it's value is used as gateway.
+
+If the `IPFS_GATEWAY` environment variable is found, its value is used as
+gateway.
### Automatic gateway detection
When you provide no additional details to cURL then cURL will:
-1. First look for the `IPFS_GATEWAY` environment variable and use that if it's set.
-2. Look for the file: `~/.ipfs/gateway`. If it can find that file then it means that you have a local gateway running and that file contains the URL to your local gateway.
+1. First look for the `IPFS_GATEWAY` environment variable and use that if it
+ is set.
+2. Look for the file: `~/.ipfs/gateway`. If it can find that file then it
+ means that you have a local gateway running and that file contains the URL
+ to your local gateway.
-If cURL fails you'll be presented with an error message and a link to this page to the option most applicable to solving the issue.
+If cURL fails you will be presented with an error message and a link to this
+page to the option most applicable to solving the issue.
### `--ipfs-gateway` argument
-You can also provide a `--ipfs-gateway` argument to cURL. This overrules any other gateway setting. curl won't fallback to the other options if the provided gateway didn't work.
+
+You can also provide a `--ipfs-gateway` argument to cURL. This overrules any
+other gateway setting. curl will not fallback to the other options if the
+provided gateway did not work.
## Gateway redirects
-A gateway could redirect to another place. For example, `dweb.link` redirects [path based](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#path-gateway) requests to [subdomain based](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway) ones. So a request to:
-```
-curl ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi --ipfs-gateway https://dweb.link
-```
+
+A gateway could redirect to another place. For example, `dweb.link` redirects
+[path based](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#path-gateway)
+requests to [subdomain
+based](https://docs.ipfs.tech/how-to/address-ipfs-on-web/#subdomain-gateway)
+ones. A request using:
+
+ curl ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi --ipfs-gateway https://dweb.link
+
Which would be translated to:
-```
-https://dweb.link/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi
-```
+
+ https://dweb.link/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi
+
Will redirect to:
-```
-https://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi.ipfs.dweb.link
-```
+
+ https://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi.ipfs.dweb.link
+
If you trust this behavior from your gateway of choice then passing the `-L` option will follow the redirect.
## Error messages and hints
+
Depending on the arguments, cURL could present the user with an error.
### Gateway file and environment variable
-cURL tried to look for the file: `~/.ipfs/gateway` but couldn't find it. It also tried to look for the `IPFS_GATEWAY` environment variable but couldn't find that either. This happens when no extra arguments are passed to cURL and letting it try to figure it out [automatically](#Automatic-gateway-detection).
-Any IPFS implementation that has gateway support should expose it's URL in `~/.ipfs/gateway`. If you are already running a gateway, make sure it exposes the file where cURL expects to find it.
+cURL tried to look for the file: `~/.ipfs/gateway` but could not find it. It
+also tried to look for the `IPFS_GATEWAY` environment variable but could not
+find that either. This happens when no extra arguments are passed to cURL and
+letting it try to figure it out [automatically](#automatic-gateway-detection).
-Alternatively you could set the `IPFS_GATEWAY` environment variable or pass the `--ipfs-gateway` flag to the cURL command.
+Any IPFS implementation that has gateway support should expose its URL in
+`~/.ipfs/gateway`. If you are already running a gateway, make sure it exposes
+the file where cURL expects to find it.
+
+Alternatively you could set the `IPFS_GATEWAY` environment variable or pass
+the `--ipfs-gateway` flag to the cURL command.
### Malformed gateway URL
-The command executed evaluates in an invalid URL. This could be anywhere in the URL, but a likely point is a wrong gateway URL.
-Inspect your URL.
-Alternatively opt to go for the [automatic](#Automatic-gateway-detection) gateway detection.
+The command executed evaluates in an invalid URL. This could be anywhere in
+the URL, but a likely point is a wrong gateway URL.
+
+Inspect the URL set via the `IPFS_GATEWAY` environment variable or passed with
+the `--ipfs-gateway` flag. Alternatively opt to go for the
+[automatic](#automatic-gateway-detection) gateway detection.
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 395426b4d..f91ff63bb 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -12,7 +12,6 @@ check the changelog of the current development status, as one or more of these
problems may have been fixed or changed somewhat since this was written.
1. HTTP
- 1.1 hyper memory-leaks
1.2 hyper is slow
1.5 Expect-100 meets 417
@@ -93,7 +92,6 @@ problems may have been fixed or changed somewhat since this was written.
15.1 cmake outputs: no version information available
15.2 support build with GnuTLS
15.3 unusable tool_hugehelp.c with MinGW
- 15.4 build docs/curl.1
15.6 uses -lpthread instead of Threads::Threads
15.7 generated .pc file contains strange entries
15.8 libcurl.pc uses absolute library paths
@@ -102,10 +100,6 @@ problems may have been fixed or changed somewhat since this was written.
16. aws-sigv4
16.1 aws-sigv4 does not sign requests with * correctly
- 16.2 aws-sigv4 does not sign requests with valueless queries correctly
- 16.3 aws-sigv4 is missing the amz-content-sha256 header
- 16.4 aws-sigv4 does not sort query string parameters before signing
- 16.5 aws-sigv4 does not sign requests with empty URL query correctly
16.6 aws-sigv4 does not behave well with AWS VPC Lattice
17. HTTP/2
@@ -115,6 +109,9 @@ problems may have been fixed or changed somewhat since this was written.
18. HTTP/3
18.1 connection migration does not work
+ 19. RTSP
+ 19.1 Some methods do not support response bodies
+
==============================================================================
1. HTTP
@@ -530,12 +527,6 @@ problems may have been fixed or changed somewhat since this was written.
see https://github.com/curl/curl/issues/3125
-15.4 build docs/curl.1
-
- The cmake build does not create the docs/curl.1 file and therefore must rely on
- it being there already. This makes the --manual option not work and test
- cases like 1139 cannot function.
-
15.6 uses -lpthread instead of Threads::Threads
See https://github.com/curl/curl/issues/6166
@@ -579,22 +570,6 @@ problems may have been fixed or changed somewhat since this was written.
https://github.com/curl/curl/issues/7559
-16.2 aws-sigv4 does not sign requests with valueless queries correctly
-
- https://github.com/curl/curl/issues/8107
-
-16.3 aws-sigv4 is missing the amz-content-sha256 header
-
- https://github.com/curl/curl/issues/8810
-
-16.4 aws-sigv4 does not sort query string parameters before signing
-
- https://github.com/curl/curl/issues/9717
-
-16.5 aws-sigv4 does not sign requests with empty URL query correctly
-
- https://github.com/curl/curl/issues/10129
-
16.6 aws-sigv4 does not behave well with AWS VPC Lattice
https://github.com/curl/curl/issues/11007
@@ -623,3 +598,13 @@ problems may have been fixed or changed somewhat since this was written.
18.1 connection migration does not work
https://github.com/curl/curl/issues/7695
+
+19. RTSP
+
+19.1 Some methods do not support response bodies
+
+ The RTSP implementation is written to assume that a number of RTSP methods
+ will always get responses without bodies, even though there seems to be no
+ indication in the RFC that this is always the case.
+
+ https://github.com/curl/curl/issues/12414
diff --git a/docs/MANUAL.md b/docs/MANUAL.md
index 8de4bd702..e7b4bb7af 100644
--- a/docs/MANUAL.md
+++ b/docs/MANUAL.md
@@ -10,7 +10,7 @@ Get a README file from an FTP server:
curl ftp://ftp.example.com/README
-Get a web page from a server using port 8000:
+Get a webpage from a server using port 8000:
curl http://www.example.com:8000/
@@ -63,12 +63,12 @@ Get a file from an SMB server:
## Download to a File
-Get a web page and store in a local file with a specific name:
+Get a webpage and store in a local file with a specific name:
curl -o thatpage.html http://www.example.com/
-Get a web page and store in a local file, make the local file get the name of
-the remote document (if no file name part is specified in the URL, this will
+Get a webpage and store in a local file, make the local file get the name of
+the remote document (if no filename part is specified in the URL, this will
fail):
curl -O http://www.example.com/index.html
@@ -224,7 +224,7 @@ Upload data from a specified file, login with user and password:
curl -T uploadfile -u user:passwd ftp://ftp.example.com/myfile
-Upload a local file to the remote site, and use the local file name at the
+Upload a local file to the remote site, and use the local filename at the
remote site too:
curl -T uploadfile -u user:passwd ftp://ftp.example.com/
@@ -266,7 +266,7 @@ the actual data).
curl -v ftp://ftp.example.com/
To get even more details and information on what curl does, try using the
-`--trace` or `--trace-ascii` options with a given file name to log to, like
+`--trace` or `--trace-ascii` options with a given filename to log to, like
this:
curl --trace trace.txt www.haxx.se
@@ -347,7 +347,7 @@ multipart/form-data type. This latter type supports things like file upload.
`-F` accepts parameters like `-F "name=contents"`. If you want the contents to
be read from a file, use `@filename` as contents. When specifying a file, you
can also specify the file content type by appending `;type=<mime type>` to the
-file name. You can also post the contents of several files in one field. For
+filename. You can also post the contents of several files in one field. For
example, the field name `coolfiles` is used to send three files, with
different content types using the following syntax:
@@ -360,7 +360,7 @@ earlier file if several files are specified in a list) or else it will use the
default type `application/octet-stream`.
Emulate a fill-in form with `-F`. Let's say you fill in three fields in a
-form. One field is a file name which to post, one field is your name and one
+form. One field is a filename which to post, one field is your name and one
field is a file description. We want to post the file we have written named
`cooltext.txt`. To let curl do the posting of this data instead of your
favorite browser, you have to read the HTML source of the form page and find
@@ -556,7 +556,7 @@ transfer stalls during periods.
## Config File
Curl automatically tries to read the `.curlrc` file (or `_curlrc` file on
-Microsoft Windows systems) from the user's home dir on startup.
+Microsoft Windows systems) from the user's home directory on startup.
The config file could be made up with normal command line switches, but you
can also specify the long options without the dashes to make it more
@@ -592,7 +592,7 @@ URL by making a config file similar to:
url = "http://help.with.curl.example.com/curlhelp.html"
You can specify another config file to be read by using the `-K`/`--config`
-flag. If you set config file name to `-` it will read the config from stdin,
+flag. If you set config filename to `-` it will read the config from stdin,
which can be handy if you want to hide options from being visible in process
tables etc:
@@ -601,7 +601,7 @@ tables etc:
## Extra Headers
When using curl in your own programs, you may end up needing to pass on your
-own custom headers when getting a web page. You can do this by using the `-H`
+own custom headers when getting a webpage. You can do this by using the `-H`
flag.
Example, send the header `X-you-and-me: yes` to the server when getting a
@@ -626,11 +626,11 @@ directory at your ftp site, do:
curl ftp://user:passwd@my.example.com/README
If you want the README file from the root directory of that same site, you
-need to specify the absolute file name:
+need to specify the absolute filename:
curl ftp://user:passwd@my.example.com//README
-(I.e with an extra slash in front of the file name.)
+(I.e with an extra slash in front of the filename.)
## SFTP and SCP and Path Names
@@ -676,7 +676,7 @@ Download with `PORT` but use 192.168.0.10 as our IP address to use:
## Network Interface
-Get a web page from a server using a specified port for the interface:
+Get a webpage from a server using a specified port for the interface:
curl --interface eth0:1 http://www.example.com/
@@ -829,7 +829,7 @@ set in (only an asterisk, `*` matches all hosts)
NO_PROXY
-If the host name matches one of these strings, or the host is within the
+If the hostname matches one of these strings, or the host is within the
domain of one of these strings, transactions with that node will not be done
over proxy. When a domain is used, it needs to start with a period. A user can
specify that both www.example.com and foo.example.com should not use a proxy
@@ -888,7 +888,7 @@ command line similar to:
curl telnet://remote.example.com
-And enter the data to pass to the server on stdin. The result will be sent to
+Enter the data to pass to the server on stdin. The result will be sent to
stdout or to the file you specify with `-o`.
You might want the `-N`/`--no-buffer` option to switch off the buffered output
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 5454e8330..fbe94c40e 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -26,24 +26,21 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
# EXTRA_DIST breaks with $(abs_builddir) so build it using this variable
# but distribute it (using the relative file name) in the next variable
-man_MANS = $(abs_builddir)/curl.1
+man_MANS = $(abs_builddir)/curl.1 mk-ca-bundle.1
noinst_man_MANS = curl.1 mk-ca-bundle.1
dist_man_MANS = curl-config.1
-GENHTMLPAGES = curl.html curl-config.html mk-ca-bundle.html
-PDFPAGES = curl.pdf curl-config.pdf mk-ca-bundle.pdf
-MANDISTPAGES = curl.1.dist curl-config.1.dist
-
-HTMLPAGES = $(GENHTMLPAGES)
+CURLPAGES = curl-config.md mk-ca-bundle.md
# Build targets in this file (.) before cmdline-opts to ensure that
# the curl.1 rule below runs first
-SUBDIRS = . cmdline-opts
-DIST_SUBDIRS = $(SUBDIRS) examples libcurl
+SUBDIRS = . cmdline-opts libcurl
+DIST_SUBDIRS = $(SUBDIRS) examples
-CLEANFILES = $(GENHTMLPAGES) $(PDFPAGES) $(MANDISTPAGES) curl.1
+CLEANFILES = $(man_MANS) curl.1 curl-config.1 mk-ca-bundle.1
+nodist_MANS = $(CLEANFILES)
EXTRA_DIST = \
- $(noinst_man_MANS) \
+ $(CURLPAGES) \
ALTSVC.md \
BINDINGS.md \
BUFREF.md \
@@ -55,9 +52,11 @@ EXTRA_DIST = \
CODE_OF_CONDUCT.md \
CODE_REVIEW.md \
CODE_STYLE.md \
+ CLIENT-WRITERS.md \
CONNECTION-FILTERS.md \
CONTRIBUTE.md \
CURL-DISABLE.md \
+ CURLDOWN.md \
DEPRECATE.md \
DYNBUF.md \
EARLY-RELEASE.md \
@@ -73,7 +72,7 @@ EXTRA_DIST = \
HTTP3.md \
HYPER.md \
INSTALL \
- INSTALL.cmake \
+ INSTALL-CMAKE.md \
INSTALL.md \
INTERNALS.md \
KNOWN_BUGS \
@@ -97,9 +96,14 @@ EXTRA_DIST = \
VULN-DISCLOSURE-POLICY.md \
WEBSOCKET.md
-MAN2HTML= roffit $< >$@
+CD2NROFF = $(top_srcdir)/scripts/cd2nroff $< >$@
+
+CD2 = $(CD2_$(V))
+CD2_0 = @echo " RENDER " $@;
+CD2_1 =
+CD2_ = $(CD2_0)
-SUFFIXES = .1 .html .pdf
+SUFFIXES = .1 .md
# $(abs_builddir) is to disable VPATH when searching for this file, which
# would otherwise find the copy in $(srcdir) which breaks the $(HUGE)
@@ -111,24 +115,14 @@ SUFFIXES = .1 .html .pdf
# have changed.
$(abs_builddir)/curl.1:
if test "$(top_builddir)x" != "$(top_srcdir)x" -a -e "$(srcdir)/curl.1"; then \
- $(INSTALL_DATA) "$(srcdir)/curl.1" $@; fi
+ $(INSTALL_DATA) "$(srcdir)/curl.1" $@ \
+ && touch -r "$(srcdir)/curl.1" $@; fi
cd cmdline-opts && $(MAKE)
-html: $(HTMLPAGES)
- cd libcurl && $(MAKE) html
-
-pdf: $(PDFPAGES)
- cd libcurl && $(MAKE) pdf
-
-.1.html:
- $(MAN2HTML)
+.md.1:
+ $(CD2)$(CD2NROFF)
-.1.pdf:
- @(foo=`echo $@ | sed -e 's/\.[0-9]$$//g'`; \
- groff -Tps -man $< >$$foo.ps; \
- ps2pdf $$foo.ps $@; \
- rm $$foo.ps; \
- echo "converted $< to $@")
+curl-config.1: curl-config.md
distclean:
rm -f $(CLEANFILES)
diff --git a/docs/NEW-PROTOCOL.md b/docs/NEW-PROTOCOL.md
index a8b227d3c..223815b6d 100644
--- a/docs/NEW-PROTOCOL.md
+++ b/docs/NEW-PROTOCOL.md
@@ -7,7 +7,7 @@ protocols and it is the Internet transfer machine for the world.
In the curl project we love protocols and we love supporting many protocols
and doing it well.
-So how do you proceed to add a new protocol and what are the requirements?
+How do you proceed to add a new protocol and what are the requirements?
## No fixed set of requirements
diff --git a/docs/PARALLEL-TRANSFERS.md b/docs/PARALLEL-TRANSFERS.md
index 337fab5fa..03ceb8f82 100644
--- a/docs/PARALLEL-TRANSFERS.md
+++ b/docs/PARALLEL-TRANSFERS.md
@@ -38,9 +38,9 @@ Example:
## Behavior differences
Connections are shared fine between different easy handles, but the
-"authentication contexts" are not. So for example doing HTTP Digest auth with
-one handle for a particular transfer and then continue on with another handle
-that reuses the same connection, the second handle cannot send the necessary
+"authentication contexts" are not. For example doing HTTP Digest auth with one
+handle for a particular transfer and then continue on with another handle that
+reuses the same connection, the second handle cannot send the necessary
Authorization header at once since the context is only kept in the original
easy handle.
diff --git a/docs/SECURITY-ADVISORY.md b/docs/SECURITY-ADVISORY.md
index 0ddc38b90..6344d2222 100644
--- a/docs/SECURITY-ADVISORY.md
+++ b/docs/SECURITY-ADVISORY.md
@@ -35,7 +35,7 @@ The eleven fields for each CVE in `vuln.pm` are, in order:
### `Makefile`
-The new CVE web page file name needs to be added in the `Makefile`'s `CVELIST`
+The new CVE webpage filename needs to be added in the `Makefile`'s `CVELIST`
macro.
When the markdown is in place and the `Makefile` and `vuln.pm` are updated,
diff --git a/docs/SSLCERTS.md b/docs/SSLCERTS.md
index 4094e2fec..7087e1eaf 100644
--- a/docs/SSLCERTS.md
+++ b/docs/SSLCERTS.md
@@ -103,9 +103,9 @@ server, do one of the following:
certificate store or use it stand-alone as described. Just remember that
the security is no better than the way you obtained the certificate.
- 4. If you are using the curl command line tool, you can specify your own CA
- cert file by setting the environment variable `CURL_CA_BUNDLE` to the path
- of your choice.
+ 4. If you are using the curl command line tool and the TLS backend is not
+ Schannel then you can specify your own CA cert file by setting the
+ environment variable `CURL_CA_BUNDLE` to the path of your choice.
If you are using the curl command line tool on Windows, curl will search
for a CA cert file named "curl-ca-bundle.crt" in these directories and in
@@ -116,10 +116,10 @@ server, do one of the following:
4. Windows Directory (e.g. C:\windows)
5. all directories along %PATH%
- 5. Get a better/different/newer CA cert bundle! One option is to extract the
- one a recent Firefox browser uses by running 'make ca-bundle' in the curl
- build tree root, or possibly download a version that was generated this
- way for you: [CA Extract](https://curl.se/docs/caextract.html)
+ 5. Get another CA cert bundle. One option is to extract the one a recent
+ Firefox browser uses by running 'make ca-bundle' in the curl build tree
+ root, or possibly download a version that was generated this way for you:
+ [CA Extract](https://curl.se/docs/caextract.html)
Neglecting to use one of the above methods when dealing with a server using a
certificate that is not signed by one of the certificates in the installed CA
diff --git a/docs/THANKS b/docs/THANKS
index 0bf9474a4..eee2ec51a 100644
--- a/docs/THANKS
+++ b/docs/THANKS
@@ -71,6 +71,7 @@ Alessandro Vesely
Alex aka WindEagle
Alex Baines
Alex Bligh
+Alex Bozarth
Alex Chan
Alex Crichton
Alex Fishman
@@ -78,6 +79,7 @@ Alex Gaynor
Alex Grebenschikov
Alex Gruz
Alex Kiernan
+Alex Klyubin
Alex Konev
Alex Malinovich
Alex Mayorga
@@ -90,6 +92,7 @@ Alex Samorukov
Alex Suykov
Alex Vinnik
Alex Xu
+Alexander Bartel
Alexander Beedie
Alexander Chuykov
Alexander Dyagilev
@@ -111,6 +114,7 @@ Alexandre Ferrieux
Alexandre Pion
Alexey Borzov
Alexey Eremikhin
+Alexey Larikov
Alexey Melnichuk
Alexey Pesternikov
Alexey Savchuk
@@ -130,6 +134,7 @@ Alona Rossen
Amaury Denoyelle
amishmm on github
Amit Katyal
+Ammar Faizi
Amol Pattekar
Amr Shahin
Anatol Belski
@@ -202,6 +207,7 @@ Andy Stamp
Andy Tsouladze
Angus Mackay
anio on github
+annalee
anon00000000 on github
anshnd on github
Anssi Kolehmainen
@@ -227,6 +233,7 @@ Antoni Villalonga
Antonio Larrosa
Antony74 on github
Antti Hätälä
+Anubhav Rai
apparentorder on github
April King
arainchik on github
@@ -285,6 +292,7 @@ Basuke Suzuki
baumanj on github
bdry on github
beckenc on github
+Ben
Ben Boeckel
Ben Darnell
Ben Fritz
@@ -349,6 +357,7 @@ Bob Schader
bobmitchell1956 on github
Bodo Bergmann
Bogdan Nicula
+boilingoden
Boris Kuschel
Boris Okunskiy
Boris Rasin
@@ -367,6 +376,7 @@ Brandon Dong
Brandon Wang
BratSinot on github
Brendan Jurd
+Brennan Kinney
Brent Beardsley
Brian Akins
Brian Bergeron
@@ -398,11 +408,13 @@ Bryan Henderson
Bryan Kemp
bsammon on github
bsergean on github
+bubbleguuum on github
Bubu on github
buzo-ffm on github
bxac on github
Bylon2 on github
Byrial Jensen
+Cajus Pollmeier
Caleb Raitto
Calvin Buckley
calvin2021y on github
@@ -422,6 +434,7 @@ Carlo Cannas
Carlo Marcelo Arenas Belón
Carlo Teubner
Carlo Wood
+Carlos Henrique Lima Melara
Carlos ORyan
Carsten Lange
Casey Bodley
@@ -434,9 +447,11 @@ Cering on github
Cesar Eduardo Barros
Chad Monroe
Chandrakant Bagul
+Chara White
Charles Cazabon
Charles Kerr
Charles Romestant
+Charlie C
Chen Prog
Cherish98 on github
Chester Liu
@@ -457,6 +472,7 @@ Chris Maltby
Chris Mumford
Chris Paulson-Ellis
Chris Roberts
+Chris Sauer
Chris Smowton
Chris Talbot
Chris Young
@@ -649,6 +665,7 @@ David Sanderson
David Schweikert
David Shaw
David Strauss
+David Suter
David Tarendash
David Thiel
David Walser
@@ -672,6 +689,7 @@ Denis Laxalde
Denis Ollier
Dennis Clarke
Dennis Felsing
+dependabot[bot]
Derek Higgins
Derzsi Dániel
Desmond O. Chang
@@ -780,6 +798,7 @@ Edward Sheldrake
Edward Thomson
Eelco Dolstra
Eetu Ojanen
+eeverettrbx on github
Egon Eckert
Egor Pugin
Ehren Bendler
@@ -806,8 +825,10 @@ Emiliano Ida
Emilio Cobos Álvarez
Emilio López
Emmanuel Tychon
+Enno Boland
Enrico Scholz
Enrik Berkhan
+enWILLYado on github
eppesuig
Eramoto Masaya
Eric Cooper
@@ -868,6 +889,7 @@ Fabrice Fontaine
Fabrizio Ammollo
Fahim Chandurwala
Faizur Rahman
+Faraz Fallahi
Farzin on github
Fata Nugraha
Fawad Mirza
@@ -930,6 +952,7 @@ FuccDucc on github
Fujii Hironori
fullincome on github
fundawang on github
+Gabe
Gabriel Corona
Gabriel Kuri
Gabriel Simmer
@@ -1042,16 +1065,19 @@ Hannes Magnusson
Hanno Böck
Hanno Kranzhoff
Hans Steegers
+Hans-Christian Egtvedt
Hans-Christian Noren Egtvedt
Hans-Jurgen May
Hao Wu
Hardeep Singh
Haris Okanovic
Harold Stuart
+Harry Mallon
Harry Sarson
Harry Sintonen
Harshal Pradhan
Hauke Duden
+Haydar Alaidrus
Hayden Roche
He Qin
Heikki Korpela
@@ -1070,6 +1096,7 @@ Henry Ludemann
Henry Roeland
Herve Amblard
HexTheDragon
+hgdagon on github
Hide Ishikawa
Hidemoto Nakada
highmtworks on github
@@ -1103,6 +1130,9 @@ Ian Lynagh
Ian Spence
Ian Turner
Ian Wilkes
+iAroc on github
+iconoclasthero
+icy17 on github
Ignacio Vazquez-Abrams
Igor Franchuk
Igor Khristophorov
@@ -1139,6 +1169,7 @@ Ishan SinghLevett
Ithubg on github
Ivan Avdeev
Ivan Tsybulin
+ivanfywang
IvanoG on github
Ivo Bellin Salarin
iz8mbw on github
@@ -1198,6 +1229,7 @@ Jan Venekamp
Jan Verbeek
Jan-Piet Mens
JanB on github
+janko-js on github
Janne Blomqvist
Janne Johansson
Jared Jennings
@@ -1219,6 +1251,7 @@ Javier Navarro
Javier Sixto
Jay Austin
Jay Dommaschk
+Jay Wu
Jayesh A Shah
Jaz Fresh
JazJas on github
@@ -1273,12 +1306,14 @@ Jerry Krinock
Jerry Wu
Jes Badwal
Jesper Jensen
+Jess Lowe
Jesse Chisholm
Jesse Noller
Jesse Tan
jethrogb on github
jhoyla on github
Jie He
+Jiehong on github
Jilayne Lovejoy
Jim Beveridge
Jim Drash
@@ -1467,10 +1502,12 @@ Kane York
Kang Lin
Kang-Jin Lee
Kantanat Wannapaka
+Kareem
Kari Pahula
Karl Chen
Karl Moerder
Karol Pietrzak
+Kartatz on Github
Karthikdasari0423
Karthikdasari0423 on github
Kartik Mahajan
@@ -1512,6 +1549,7 @@ Kim Minjoong
Kim Rinnewitz
Kim Vandry
Kimmo Kinnunen
+kirbyn17 on hackerone
Kirill Efimov
Kirill Marchuk
Kjell Ericson
@@ -1570,6 +1608,7 @@ Lars J. Aas
Lars Johannesen
Lars Nilsson
Lars Torben Wilson
+Lau
Laurent Bonnans
Laurent Dufresne
Laurent Rabret
@@ -1579,6 +1618,7 @@ Lawrence Gripper
Lawrence Matthews
Lawrence Wagerfield
Leah Neukirchen
+Lealem Amedie
Leandro Coutinho
Legoff Vincent
Lehel Bernadt
@@ -1602,6 +1642,7 @@ LigH-de on github
lijian996 on github
Lijo Antony
lilongyan-huawei on github
+Lin Sun
Linas Vepstas
Lindley French
Ling Thio
@@ -1615,15 +1656,18 @@ Litter White
Liviu Chircu
Liza Alenchery
lizhuang0630 on github
+lkordos on github
lllaffer on github
Lloyd Fournier
Lluís Batlle i Rossell
locpyl-tidnyd on github
Loganaden Velvindron
Loic Dachary
+LoRd_MuldeR
Loren Kirkby
Lorenzo Miniero
Loïc Yhuel
+lRoccoon on github
Luan Cestari
Luca Altea
Luca Boccassi
@@ -1667,6 +1711,7 @@ Maksim Arhipov
Maksim Kuzevanov
Maksim Sciepanienka
Maksim Stsepanenka
+Maksymilian Arciemowicz
Malik Idrees Hasan Khan
Mamoru Tasaka
Mamta Upadhyay
@@ -1693,6 +1738,7 @@ Marcelo Juchem
Marcin Adamski
Marcin Gryszkalis
Marcin Konicki
+Marcin Rataj
Marco Deckel
Marco G. Salvagno
Marco Kamner
@@ -1713,6 +1759,7 @@ Mark Davies
Mark Dodgson
Mark Gaiser
Mark Hamilton
+Mark Huang
Mark Incley
Mark Itzcovitz
Mark Karpeles
@@ -1721,6 +1768,7 @@ Mark Nottingham
Mark Roszko
Mark Salisbury
Mark Seuffert
+Mark Sinkovics
Mark Snelling
Mark Swaanenburg
Mark Tully
@@ -1756,6 +1804,7 @@ Martin Jansen
Martin Kammerhofer
Martin Kepplinger
Martin Lemke
+Martin Schmatz
Martin Skinner
Martin Staael
Martin Storsjö
@@ -1808,6 +1857,7 @@ Matthias Naegler
Mattias Fornander
Matus Uzak
Maurice Barnum
+Mauricio Scheffer
Mauro Iorio
Mauro Rappa
Maurício Meneghini Fauth
@@ -1931,6 +1981,7 @@ Mohamed Lrhazi
Mohamed Osama
Mohammad AlSaleh
Mohammad Hasbini
+Mohammadreza Hendiani
Mohammed Naser
Mohun Biswas
momala454 on github
@@ -1995,6 +2046,7 @@ Nick Zitzmann
nick-telia on github
Nicklas Avén
Nico Baggus
+Nico Rieck
nico-abram on github
Nicolas Berloquin
Nicolas Croiset
@@ -2018,6 +2070,7 @@ nimaje on github
niner on github
Ning Dong
Nir Soffer
+Niracler Li
Niranjan Hasabnis
Nis Jorgensen
nk
@@ -2037,6 +2090,7 @@ Nuru on github
Octavio Schroeder
odek86 on github
Ofer
+ohyeaah on github
Okhin Vasilij
Ola Mork
Olaf Flebbe
@@ -2063,6 +2117,7 @@ omau on github
Ondřej Koláček
opensignature on github
opensslonzos-github on github
+Ophir Lojkine
Orange Tsai
Oren Souroujon
Oren Tirosh
@@ -2078,6 +2133,7 @@ Oskar Liljeblad
Oskar Sigvardsson
Oumph on github
ovidiu-benea on github
+Ozan Cansel
P R Schaffner
Pablo Busse
Palo Markovic
@@ -2230,6 +2286,7 @@ Prithvi MK
privetryan on github
Priyanka Shah
ProceduralMan on github
+promptfuzz_ on hackerone
Pronyushkin Petr
Przemysław Tomaszewski
pszemus on github
@@ -2299,6 +2356,7 @@ Renaud Lehoux
Rene Bernhardt
Rene Rebe
Reuven Wachtfogel
+RevaliQaQ on github
Reza Arbab
Rianov Viacheslav
Ricardo Cadime
@@ -2324,6 +2382,7 @@ Richard Gorton
Richard Gray
Richard Hosking
Richard Hsu
+Richard Levitte
Richard Marion
Richard Michael
Richard Moore
@@ -2346,6 +2405,7 @@ Ricky-Tigg on github
Rider Linden
RiderALT on github
Rikard Falkeborn
+rilysh
rl1987 on github
Rob Boeckermann
Rob Cotrone
@@ -2373,6 +2433,7 @@ Robert Prag
Robert Ronto
Robert Schumann
Robert Simpson
+Robert Southee
Robert Weaver
Robert Wruck
Robin A. Meade
@@ -2448,6 +2509,7 @@ Salvador Dávila
Salvatore Sorrentino
Sam Deane
Sam Hurst
+Sam James
Sam Roth
Sam Schanken
Samanta Navarro
@@ -2477,11 +2539,13 @@ Saul good
Saurav Babu
sayrer on github
SBKarr on github
+Scarlett McAllister
Scott Bailey
Scott Barrett
Scott Cantor
Scott Davis
Scott McCreary
+sd0 on hackerone
Sean Boudreau
Sean Burford
Sean MacLennan
@@ -2521,6 +2585,7 @@ SerusDev on github
Seshubabu Pasam
Seth Mos
Sevan Janiyan
+sfan5 on github
Sgharat on github
Sh Diao
Shachaf Ben-Kiki
@@ -2559,10 +2624,12 @@ Simon Warta
simplerobot on github
Siva Sivaraman
SLDiggie on github
+Smackd0wn
Smackd0wn on github
smuellerDD on github
sn on hackerone
sofaboss on github
+Sohom Datta
Somnath Kundu
Song Ma
Sonia Subramanian
@@ -2629,6 +2696,7 @@ Steve Marx
Steve Oliphant
Steve Roskowski
Steve Walch
+Steven Allen
Steven Bazyl
Steven G. Johnson
Steven Gu
@@ -2667,6 +2735,7 @@ Taneli Vähäkangas
Tanguy Fautre
Taras Kushnir
tarek112 on github
+Tatsuhiko Miyagawa
Tatsuhiro Tsujikawa
tawmoto on github
tbugfinder on github
@@ -2679,6 +2748,7 @@ thanhchungbtc on github
The Infinnovation team
TheAssassin on github
TheKnarf on github
+Theo
Theodore Dubois
therealhirudo on github
Thiago Suchorski
@@ -2686,6 +2756,7 @@ tholin on github
Thomas Bouzerar
Thomas Braun
Thomas Danielsson
+Thomas Ferguson
Thomas Gamper
Thomas Glanzmann
Thomas Guillem
@@ -2714,6 +2785,7 @@ Tim Chen
Tim Costello
Tim Harder
Tim Heckman
+Tim Hill
Tim Mcdonough
Tim Newsome
Tim Rühsen
@@ -2793,6 +2865,7 @@ tonystz on Github
Toon Verwaest
Tor Arntsen
Torben Dannhauer
+Torben Dury
Torsten Foertsch
Toshio Kuratomi
Toshiyuki Maezawa
@@ -2809,6 +2882,7 @@ Tseng Jun
Tuomas Siipola
Tuomo Rinne
Tupone Alfredo
+Turiiya
Tyler Hall
Török Edwin
u20221022 on github
@@ -2920,6 +2994,7 @@ x2018 on github
Xavier Bouchoux
XhmikosR on github
XhstormR on github
+Xi Ruoyao
Xiang Xiao
Xiangbin Li
xianghongai on github
@@ -2931,6 +3006,7 @@ xtonik on github
xwxbug on github
Xì Gà
Yaakov Selkowitz
+Yadhu Krishna M
Yair Lenga
Yang Tse
Yaobin Wen
@@ -2938,10 +3014,12 @@ Yarram Sunil
Yasuharu Yamada
Yasuhiro Matsumoto
Yechiel Kalmenson
+Yedaya Katsman
Yehezkel Horowitz
Yehoshua Hershberg
ygthien on github
Yi Huang
+Yifei Kong
Yiming Jing
Yingwei Liu
yiyuaner on github
@@ -2969,6 +3047,8 @@ Zachary Seguin
Zdenek Pavlas
Zekun Ni
zelinchen on github
+zengwei
+zengwei2000
Zenju on github
Zero King
Zespre Schmidt
@@ -2976,6 +3056,7 @@ Zhang Xiuhua
zhanghu on xiaomi
Zhao Yisha
Zhaoyang Wu
+zhengqwe on github
Zhibiao Wu
zhihaoy on github
Zhouyihai Ding
diff --git a/docs/TODO b/docs/TODO
index f487f88aa..162944360 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -122,6 +122,7 @@
13.8 Support DANE
13.9 TLS record padding
13.10 Support Authority Information Access certificate extension (AIA)
+ 13.11 Some TLS options are not offered for HTTPS proxies
13.12 Reduce CA certificate bundle reparsing
13.13 Make sure we forbid TLS 1.3 post-handshake authentication
13.14 Support the clienthello extension
@@ -195,6 +196,9 @@
21. MQTT
21.1 Support rate-limiting
+ 22. TFTP
+ 22.1 TFTP doesn't convert LF to CRLF for mode=netascii
+
==============================================================================
1. libcurl
@@ -884,6 +888,14 @@
See https://github.com/curl/curl/issues/2793
+13.11 Some TLS options are not offered for HTTPS proxies
+
+ Some TLS related options to the command line tool and libcurl are only
+ provided for the server and not for HTTPS proxies. --proxy-tls-max,
+ --proxy-tlsv1.3, --proxy-curves and a few more.a
+
+ https://github.com/curl/curl/issues/12286
+
13.12 Reduce CA certificate bundle reparsing
When using the OpenSSL backend, curl will load and reparse the CA bundle at
@@ -1104,7 +1116,7 @@
slow, potentially with a (random) wait between transfers. There is also a
proposed 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
+ https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/
See https://github.com/curl/curl/issues/5406
@@ -1383,3 +1395,14 @@
The rate-limiting logic is done in the PERFORMING state in multi.c but MQTT
is not (yet) implemented to use that.
+
+22. TFTP
+
+22.1 TFTP doesn't convert LF to CRLF for mode=netascii
+
+ RFC 3617 defines that an TFTP transfer can be done using "netascii"
+ mode. curl does not support extracting that mode from the URL nor does it treat
+ such transfers specifically. It should probably do LF to CRLF translations
+ for them.
+
+ See https://github.com/curl/curl/issues/12655
diff --git a/docs/TheArtOfHttpScripting.md b/docs/TheArtOfHttpScripting.md
index 43f13e2af..8607642f7 100644
--- a/docs/TheArtOfHttpScripting.md
+++ b/docs/TheArtOfHttpScripting.md
@@ -87,16 +87,16 @@
The Uniform Resource Locator format is how you specify the address of a
particular resource on the Internet. You know these, you have seen URLs like
https://curl.se or https://example.com a million times. RFC 3986 is the
- canonical spec. And yeah, the formal name is not URL, it is URI.
+ canonical spec. The formal name is not URL, it is **URI**.
## Host
- The host name is usually resolved using DNS or your /etc/hosts file to an IP
+ The hostname is usually resolved using DNS or your /etc/hosts file to an IP
address and that is what curl will communicate with. Alternatively you specify
the IP address directly in the URL instead of a name.
For development and other trying out situations, you can point to a different
- IP address for a host name than what would otherwise be used, by using curl's
+ IP address for a hostname than what would otherwise be used, by using curl's
[`--resolve`](https://curl.se/docs/manpage.html#--resolve) option:
curl --resolve www.example.org:80:127.0.0.1 http://www.example.org/
@@ -107,7 +107,7 @@
or in some cases UDP. Normally you do not have to take that into
consideration, but at times you run test servers on other ports or
similar. Then you can specify the port number in the URL with a colon and a
- number immediately following the host name. Like when doing HTTP to port
+ number immediately following the hostname. Like when doing HTTP to port
1234:
curl http://www.example.org:1234/
@@ -142,20 +142,20 @@
The path part is just sent off to the server to request that it sends back
the associated response. The path is what is to the right side of the slash
- that follows the host name and possibly port number.
+ that follows the hostname and possibly port number.
# Fetch a page
## GET
The simplest and most common request/operation made using HTTP is to GET a
- URL. The URL could itself refer to a web page, an image or a file. The client
+ URL. The URL could itself refer to a webpage, an image or a file. The client
issues a GET request to the server and receives the document it asked for.
If you issue the command line
curl https://curl.se
- you get a web page returned in your terminal window. The entire HTML document
+ you get a webpage returned in your terminal window. The entire HTML document
that that URL holds.
All HTTP replies contain a set of response headers that are normally hidden,
@@ -309,12 +309,10 @@
This method is mainly designed to better support file uploads. A form that
allows a user to upload a file could be written like this in HTML:
-```html
-<form method="POST" enctype='multipart/form-data' action="upload.cgi">
- <input type=file name=upload>
- <input type=submit name=press value="OK">
-</form>
-```
+ <form method="POST" enctype='multipart/form-data' action="upload.cgi">
+ <input name=upload type=file>
+ <input type=submit name=press value="OK">
+ </form>
This clearly shows that the Content-Type about to be sent is
`multipart/form-data`.
@@ -500,7 +498,7 @@
The way the web browsers do "client side state control" is by using
cookies. Cookies are just names with associated contents. The cookies are
sent to the client by the server. The server tells the client for what path
- and host name it wants the cookie sent back, and it also sends an expiration
+ and hostname it wants the cookie sent back, and it also sends an expiration
date and a few more properties.
When a client communicates with a server with a name and path as previously
@@ -630,18 +628,17 @@
It should be noted that curl selects which methods to use on its own
depending on what action to ask for. `-d` will do POST, `-I` will do HEAD and
- so on. If you use the
- [`--request`](https://curl.se/docs/manpage.html#-X) / `-X` option you
- can change the method keyword curl selects, but you will not modify curl's
- behavior. This means that if you for example use -d "data" to do a POST, you
- can modify the method to a `PROPFIND` with `-X` and curl will still think it
- sends a POST . You can change the normal GET to a POST method by simply
- adding `-X POST` in a command line like:
+ so on. If you use the [`--request`](https://curl.se/docs/manpage.html#-X) /
+ `-X` option you can change the method keyword curl selects, but you will not
+ modify curl's behavior. This means that if you for example use -d "data" to
+ do a POST, you can modify the method to a `PROPFIND` with `-X` and curl will
+ still think it sends a POST. You can change the normal GET to a POST method
+ by simply adding `-X POST` in a command line like:
curl -X POST http://example.org/
- ... but curl will still think and act as if it sent a GET so it will not send
- any request body etc.
+ curl will however still act as if it sent a GET so it will not send any
+ request body etc.
# Web Login
diff --git a/docs/URL-SYNTAX.md b/docs/URL-SYNTAX.md
index ddd99454f..011a32c38 100644
--- a/docs/URL-SYNTAX.md
+++ b/docs/URL-SYNTAX.md
@@ -28,7 +28,7 @@ Due to the inherent differences between URL parser implementations, it is
considered a security risk to mix different implementations and assume the
same behavior!
-For example, if you use one parser to check if a URL uses a good host name or
+For example, if you use one parser to check if a URL uses a good hostname or
the correct auth field, and then pass on that same URL to a *second* parser,
there will always be a risk it treats the same URL differently. There is no
right and wrong in URL land, only differences of opinions.
@@ -92,7 +92,7 @@ curl supports "URLs" that do not start with a scheme. This is not supported by
any of the specifications. This is a shortcut to entering URLs that was
supported by browsers early on and has been mimicked by curl.
-Based on what the host name starts with, curl will "guess" what protocol to
+Based on what the hostname starts with, curl will "guess" what protocol to
use:
- `ftp.` means FTP
@@ -367,9 +367,9 @@ curl supports SMB version 1 (only)
## SMTP
-The path part of a SMTP request specifies the host name to present during
+The path part of a SMTP request specifies the hostname to present during
communication with the mail server. If the path is omitted, then libcurl will
-attempt to resolve the local computer's host name. However, this may not
+attempt to resolve the local computer's hostname. However, this may not
return the fully qualified domain name that is required by some mail servers
and specifying this path allows you to set an alternative name, such as your
machine's fully qualified domain name, which you might have obtained from an
diff --git a/docs/VULN-DISCLOSURE-POLICY.md b/docs/VULN-DISCLOSURE-POLICY.md
index 3ce220329..a0086634a 100644
--- a/docs/VULN-DISCLOSURE-POLICY.md
+++ b/docs/VULN-DISCLOSURE-POLICY.md
@@ -59,8 +59,7 @@ announcement.
[SECURITY-ADVISORY](https://curl.se/dev/advisory.html) for help on creating
the advisory.
-- Request a CVE number from
- [HackerOne](https://docs.hackerone.com/programs/cve-requests.html)
+- Request a CVE number from HackerOne
- Update the "security advisory" with the CVE number.
@@ -93,7 +92,7 @@ announcement.
the same manner we always announce releases. It gets sent to the
curl-announce, curl-library and curl-users mailing lists.
-- The security web page on the website should get the new vulnerability
+- The security webpage on the website should get the new vulnerability
mentioned.
## security (at curl dot se)
@@ -283,3 +282,12 @@ and if an attacker can trick the user to run a specifically crafted curl
command line, all bets are off. Such an attacker can just as well have the
user run a much worse command that can do something fatal (like
`sudo rm -rf /`).
+
+## Terminal output and escape sequences
+
+Content that is transferred from a server and gets displayed in a terminal by
+curl may contain escape sequences or use other tricks to fool the user. This
+is curl working as designed and is not a curl security problem. Escape
+sequences, moving cursor, changing color etc, is also frequently used for
+good. To reduce the risk of getting fooled, save files and browse them after
+download using a display method that minimizes risks.
diff --git a/docs/WEBSOCKET.md b/docs/WEBSOCKET.md
index ba84c2284..c3967b8ea 100644
--- a/docs/WEBSOCKET.md
+++ b/docs/WEBSOCKET.md
@@ -109,10 +109,9 @@ Ideas:
## Why not libWebSocket
-[libWebSocket](https://libWebSockets.org/) is said to be a solid, fast and
-efficient WebSocket library with a vast amount of users. My plan was
-originally to build upon it to skip having to implement the low level parts of
-WebSocket myself.
+libWebSocket is said to be a solid, fast and efficient WebSocket library with
+a vast amount of users. My plan was originally to build upon it to skip having
+to implement the low level parts of WebSocket myself.
Here are the reasons why I have decided to move forward with WebSocket in
curl **without using libWebSocket**:
diff --git a/docs/cmdline-opts/CMakeLists.txt b/docs/cmdline-opts/CMakeLists.txt
index 3dd8be49b..ee158df99 100644
--- a/docs/cmdline-opts/CMakeLists.txt
+++ b/docs/cmdline-opts/CMakeLists.txt
@@ -28,8 +28,10 @@ transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
add_custom_command(OUTPUT "${MANPAGE}"
- COMMAND "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/gen.pl" mainpage "${CMAKE_CURRENT_SOURCE_DIR}" > "${MANPAGE}"
- DEPENDS ${DPAGES} ${OTHERPAGES}
+ COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && "${PERL_EXECUTABLE}" "./gen.pl" mainpage ${DPAGES} > "${MANPAGE}"
VERBATIM
)
-add_custom_target(generate-curl.1 DEPENDS "${MANPAGE}")
+add_custom_target(generate-curl.1 ALL DEPENDS "${MANPAGE}")
+if(NOT CURL_DISABLE_INSTALL)
+ install(FILES "${MANPAGE}" DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+endif()
diff --git a/docs/cmdline-opts/MANPAGE.md b/docs/cmdline-opts/MANPAGE.md
index 6de32dab9..951cbe859 100644
--- a/docs/cmdline-opts/MANPAGE.md
+++ b/docs/cmdline-opts/MANPAGE.md
@@ -9,24 +9,38 @@
This is the curl man page generator. It generates a single nroff man page
output from the set of sources files in this directory.
-There is one source file for each supported command line option. The output
-gets `page-header` prepended and `page-footer` appended. The format is
-described below.
+The `mainpage.idx` file lists all files that are rendered in that order to
+produce the output. The magic `%options` keyword inserts all command line
+options documented.
+
+The `%options` documentation is created with one source file for each
+supported command line option.
+
+The documentation file format is described below. It is meant to look similar
+to markdown which is why it uses `.md` file extensions.
## Option files
Each command line option is described in a file named `<long name>.d`, where
option name is written without any prefixing dashes. Like the file name for
-the -v, --verbose option is named `verbose.d`.
+the `-v, --verbose` option is named `verbose.d`.
+
+Each file has a set of meta-data in the top of the file, followed by a body of
+text.
-Each file has a set of meta-data and a body of text.
+The documentation files that do not document options have no meta-data part.
+
+A line that starts with `<!--` is a comment. It should also end with `-->`.
### Meta-data
+ --- (start of meta-data)
Added: (version number in which this was added)
Arg: (the argument the option takes)
c: (copyright line)
- Example: (example command line, without "curl" and can use `$URL`)
+ Example:
+ - (an example command line, without "curl" and can use `$URL`)
+ - (another example)
Experimental: yes (if so)
Help: (short text for the --help output for this option)
Long: (long form name, without dashes)
@@ -36,7 +50,9 @@ Each file has a set of meta-data and a body of text.
Protocols: (space separated list for which protocols this option works)
Requires: (space separated list of features this requires, no dashes)
Scope: global (if the option is global)
- See-also: (space separated list of related options, no dashes)
+ See-also:
+ - (a related option, no dashes)
+ - (another related option, no dashes)
Short: (single letter, without dash)
SPDX-License-Identifier: curl
Tags: (space separated list)
@@ -54,12 +70,33 @@ Text written within `*asterisks*` is shown using italics. Text within two
Text that is prefixed with a space is treated like an "example" and gets
output in monospace.
-## Header and footer
+Within the body, describe a list of items like this:
+
+ ## item 1
+ description
+
+ ## item 2
+ second description
+
+The list is automatically terminated at end of file, or you can do it
+explicitly with an empty "header":
+
+ ##
+
+### Headers
+
+The `#` header can be used by non-option files and it produces produces a
+`.SH` output.
+
+If the `#` header is used for a command line option file, that header is
+simply ignored in the generated output. It can still serve a purpose in the
+source file as it helps the user identify what option the file is for.
-`page-header` is the file that is output before the generated options output
-for the master man page.
+### Variables
-`page-footer` is appended after all the individual options.
+There are three different "variables" that can be used when creating the
+output. They need to be written within backticks in the source file (to escape
+getting spellchecked by CI jobs): `%DATE`, `%VERSION` and `%GLOBALS`.
## Generate
diff --git a/docs/cmdline-opts/Makefile.am b/docs/cmdline-opts/Makefile.am
index 5a8996bc2..e9b35ac05 100644
--- a/docs/cmdline-opts/Makefile.am
+++ b/docs/cmdline-opts/Makefile.am
@@ -28,7 +28,7 @@ MANPAGE = $(top_builddir)/docs/curl.1
include Makefile.inc
-EXTRA_DIST = $(DPAGES) MANPAGE.md gen.pl $(OTHERPAGES) CMakeLists.txt
+EXTRA_DIST = $(DPAGES) MANPAGE.md gen.pl $(SUPPORT) CMakeLists.txt mainpage.idx
GEN = $(GN_$(V))
GN_0 = @echo " GENERATE" $@;
@@ -37,5 +37,8 @@ GN_ = $(GN_0)
all: $(MANPAGE)
-$(MANPAGE): $(DPAGES) $(OTHERPAGES) Makefile.inc gen.pl
+$(MANPAGE): $(DPAGES) $(SUPPORT) mainpage.idx Makefile.inc gen.pl
$(GEN)(rm -f $(MANPAGE) && cd $(srcdir) && @PERL@ ./gen.pl mainpage $(DPAGES) > $(builddir)/manpage.tmp && mv $(builddir)/manpage.tmp $(MANPAGE))
+
+listhelp:
+ ./gen.pl listhelp $(DPAGES) > $(top_builddir)/src/tool_listhelp.c
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index a7c92f264..428cc3bab 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -23,264 +23,283 @@
###########################################################################
# Shared between Makefile.am and CMakeLists.txt
-DPAGES = \
- abstract-unix-socket.d \
- alt-svc.d \
- anyauth.d \
- append.d \
- aws-sigv4.d \
- basic.d \
- ca-native.d \
- cacert.d \
- capath.d \
- cert-status.d \
- cert-type.d \
- cert.d \
- ciphers.d \
- compressed-ssh.d \
- compressed.d \
- config.d \
- connect-timeout.d \
- connect-to.d \
- continue-at.d \
- cookie-jar.d \
- cookie.d \
- create-dirs.d \
- create-file-mode.d \
- crlf.d \
- crlfile.d \
- curves.d \
- data-ascii.d \
- data-binary.d \
- data-raw.d \
- data-urlencode.d \
- data.d \
- delegation.d \
- digest.d \
- disable-eprt.d \
- disable-epsv.d \
- disable.d \
- disallow-username-in-url.d \
- dns-interface.d \
- dns-ipv4-addr.d \
- dns-ipv6-addr.d \
- dns-servers.d \
- doh-cert-status.d \
- doh-insecure.d \
- doh-url.d \
- dump-header.d \
- egd-file.d \
- engine.d \
- etag-compare.d \
- etag-save.d \
- expect100-timeout.d \
- fail-early.d \
- fail-with-body.d \
- fail.d \
- false-start.d \
- form-escape.d \
- form-string.d \
- form.d \
- ftp-account.d \
- ftp-alternative-to-user.d \
- ftp-create-dirs.d \
- ftp-method.d \
- ftp-pasv.d \
- ftp-port.d \
- ftp-pret.d \
- ftp-skip-pasv-ip.d \
- ftp-ssl-ccc-mode.d \
- ftp-ssl-ccc.d \
- ftp-ssl-control.d \
- get.d \
- globoff.d \
- happy-eyeballs-timeout-ms.d \
- haproxy-protocol.d \
- haproxy-clientip.d \
- head.d \
- header.d \
- help.d \
- hostpubmd5.d \
- hostpubsha256.d \
- hsts.d \
- http0.9.d \
- http1.0.d \
- http1.1.d \
- http2-prior-knowledge.d \
- http2.d \
- http3.d \
- http3-only.d \
- ignore-content-length.d \
- include.d \
- insecure.d \
- interface.d \
- ipfs-gateway.d \
- ipv4.d \
- ipv6.d \
- json.d \
- junk-session-cookies.d \
- keepalive-time.d \
- key-type.d \
- key.d \
- krb.d \
- libcurl.d \
- limit-rate.d \
- list-only.d \
- local-port.d \
- location-trusted.d \
- location.d \
- login-options.d \
- mail-auth.d \
- mail-from.d \
- mail-rcpt-allowfails.d \
- mail-rcpt.d \
- manual.d \
- max-filesize.d \
- max-redirs.d \
- max-time.d \
- metalink.d \
- negotiate.d \
- netrc-file.d \
- netrc-optional.d \
- netrc.d \
- next.d \
- no-alpn.d \
- no-buffer.d \
- no-clobber.d \
- no-keepalive.d \
- no-npn.d \
- no-progress-meter.d \
- no-sessionid.d \
- noproxy.d \
- ntlm-wb.d \
- ntlm.d \
- oauth2-bearer.d \
- output-dir.d \
- output.d \
- parallel-immediate.d \
- parallel-max.d \
- parallel.d \
- pass.d \
- path-as-is.d \
- pinnedpubkey.d \
- post301.d \
- post302.d \
- post303.d \
- preproxy.d \
- progress-bar.d \
- proto-default.d \
- proto-redir.d \
- proto.d \
- proxy-anyauth.d \
- proxy-basic.d \
- proxy-ca-native.d \
- proxy-cacert.d \
- proxy-capath.d \
- proxy-cert-type.d \
- proxy-cert.d \
- proxy-ciphers.d \
- proxy-crlfile.d \
- proxy-digest.d \
- proxy-header.d \
- proxy-http2.d \
- proxy-insecure.d \
- proxy-key-type.d \
- proxy-key.d \
- proxy-negotiate.d \
- proxy-ntlm.d \
- proxy-pass.d \
- proxy-pinnedpubkey.d \
- proxy-service-name.d \
- proxy-ssl-allow-beast.d \
- proxy-ssl-auto-client-cert.d \
- proxy-tls13-ciphers.d \
- proxy-tlsauthtype.d \
- proxy-tlspassword.d \
- proxy-tlsuser.d \
- proxy-tlsv1.d \
- proxy-user.d \
- proxy.d \
- proxy1.0.d \
- proxytunnel.d \
- pubkey.d \
- quote.d \
- random-file.d \
- range.d \
- rate.d \
- raw.d \
- referer.d \
- remote-header-name.d \
- remote-name-all.d \
- remote-name.d \
- remote-time.d \
- remove-on-error.d \
- request-target.d \
- request.d \
- resolve.d \
- retry-all-errors.d \
- retry-connrefused.d \
- retry-delay.d \
- retry-max-time.d \
- retry.d \
- sasl-authzid.d \
- sasl-ir.d \
- service-name.d \
- show-error.d \
- silent.d \
- socks4.d \
- socks4a.d \
- socks5-basic.d \
- socks5-gssapi-nec.d \
- socks5-gssapi-service.d \
- socks5-gssapi.d \
- socks5-hostname.d \
- socks5.d \
- speed-limit.d \
- speed-time.d \
- ssl-allow-beast.d \
- ssl-auto-client-cert.d \
- ssl-no-revoke.d \
- ssl-reqd.d \
- ssl-revoke-best-effort.d \
- ssl.d \
- sslv2.d \
- sslv3.d \
- stderr.d \
- styled-output.d \
- suppress-connect-headers.d \
- tcp-fastopen.d \
- tcp-nodelay.d \
- telnet-option.d \
- tftp-blksize.d \
- tftp-no-options.d \
- time-cond.d \
- tls-max.d \
- tls13-ciphers.d \
- tlsauthtype.d \
- tlspassword.d \
- tlsuser.d \
- tlsv1.0.d \
- tlsv1.1.d \
- tlsv1.2.d \
- tlsv1.3.d \
- tlsv1.d \
- tr-encoding.d \
- trace-ascii.d \
- trace-config.d \
- trace-ids.d \
- trace-time.d \
- trace.d \
- unix-socket.d \
- upload-file.d \
- url.d \
- url-query.d \
- use-ascii.d \
- user-agent.d \
- user.d \
- variable.d \
- verbose.d \
- version.d \
- write-out.d \
- xattr.d
+SUPPORT = \
+ _AUTHORS.md \
+ _BUGS.md \
+ _DESCRIPTION.md \
+ _ENVIRONMENT.md \
+ _EXITCODES.md \
+ _FILES.md \
+ _GLOBBING.md \
+ _NAME.md \
+ _OPTIONS.md \
+ _OUTPUT.md \
+ _PROGRESS.md \
+ _PROTOCOLS.md \
+ _PROXYPREFIX.md \
+ _SEEALSO.md \
+ _SYNOPSIS.md \
+ _URL.md \
+ _VARIABLES.md \
+ _VERSION.md \
+ _WWW.md
-OTHERPAGES = page-footer page-header
+DPAGES = \
+ abstract-unix-socket.md \
+ alt-svc.md \
+ anyauth.md \
+ append.md \
+ aws-sigv4.md \
+ basic.md \
+ ca-native.md \
+ cacert.md \
+ capath.md \
+ cert-status.md \
+ cert-type.md \
+ cert.md \
+ ciphers.md \
+ compressed-ssh.md \
+ compressed.md \
+ config.md \
+ connect-timeout.md \
+ connect-to.md \
+ continue-at.md \
+ cookie-jar.md \
+ cookie.md \
+ create-dirs.md \
+ create-file-mode.md \
+ crlf.md \
+ crlfile.md \
+ curves.md \
+ data-ascii.md \
+ data-binary.md \
+ data-raw.md \
+ data-urlencode.md \
+ data.md \
+ delegation.md \
+ digest.md \
+ disable-eprt.md \
+ disable-epsv.md \
+ disable.md \
+ disallow-username-in-url.md \
+ dns-interface.md \
+ dns-ipv4-addr.md \
+ dns-ipv6-addr.md \
+ dns-servers.md \
+ doh-cert-status.md \
+ doh-insecure.md \
+ doh-url.md \
+ dump-header.md \
+ egd-file.md \
+ engine.md \
+ etag-compare.md \
+ etag-save.md \
+ expect100-timeout.md \
+ fail-early.md \
+ fail-with-body.md \
+ fail.md \
+ false-start.md \
+ form-escape.md \
+ form-string.md \
+ form.md \
+ ftp-account.md \
+ ftp-alternative-to-user.md \
+ ftp-create-dirs.md \
+ ftp-method.md \
+ ftp-pasv.md \
+ ftp-port.md \
+ ftp-pret.md \
+ ftp-skip-pasv-ip.md \
+ ftp-ssl-ccc-mode.md \
+ ftp-ssl-ccc.md \
+ ftp-ssl-control.md \
+ get.md \
+ globoff.md \
+ happy-eyeballs-timeout-ms.md \
+ haproxy-protocol.md \
+ haproxy-clientip.md \
+ head.md \
+ header.md \
+ help.md \
+ hostpubmd5.md \
+ hostpubsha256.md \
+ hsts.md \
+ http0.9.md \
+ http1.0.md \
+ http1.1.md \
+ http2-prior-knowledge.md \
+ http2.md \
+ http3.md \
+ http3-only.md \
+ ignore-content-length.md \
+ include.md \
+ insecure.md \
+ interface.md \
+ ipfs-gateway.md \
+ ipv4.md \
+ ipv6.md \
+ json.md \
+ junk-session-cookies.md \
+ keepalive-time.md \
+ key-type.md \
+ key.md \
+ krb.md \
+ libcurl.md \
+ limit-rate.md \
+ list-only.md \
+ local-port.md \
+ location-trusted.md \
+ location.md \
+ login-options.md \
+ mail-auth.md \
+ mail-from.md \
+ mail-rcpt-allowfails.md \
+ mail-rcpt.md \
+ manual.md \
+ max-filesize.md \
+ max-redirs.md \
+ max-time.md \
+ metalink.md \
+ negotiate.md \
+ netrc-file.md \
+ netrc-optional.md \
+ netrc.md \
+ next.md \
+ no-alpn.md \
+ no-buffer.md \
+ no-clobber.md \
+ no-keepalive.md \
+ no-npn.md \
+ no-progress-meter.md \
+ no-sessionid.md \
+ noproxy.md \
+ ntlm-wb.md \
+ ntlm.md \
+ oauth2-bearer.md \
+ output-dir.md \
+ output.md \
+ parallel-immediate.md \
+ parallel-max.md \
+ parallel.md \
+ pass.md \
+ path-as-is.md \
+ pinnedpubkey.md \
+ post301.md \
+ post302.md \
+ post303.md \
+ preproxy.md \
+ progress-bar.md \
+ proto-default.md \
+ proto-redir.md \
+ proto.md \
+ proxy-anyauth.md \
+ proxy-basic.md \
+ proxy-ca-native.md \
+ proxy-cacert.md \
+ proxy-capath.md \
+ proxy-cert-type.md \
+ proxy-cert.md \
+ proxy-ciphers.md \
+ proxy-crlfile.md \
+ proxy-digest.md \
+ proxy-header.md \
+ proxy-http2.md \
+ proxy-insecure.md \
+ proxy-key-type.md \
+ proxy-key.md \
+ proxy-negotiate.md \
+ proxy-ntlm.md \
+ proxy-pass.md \
+ proxy-pinnedpubkey.md \
+ proxy-service-name.md \
+ proxy-ssl-allow-beast.md \
+ proxy-ssl-auto-client-cert.md \
+ proxy-tls13-ciphers.md \
+ proxy-tlsauthtype.md \
+ proxy-tlspassword.md \
+ proxy-tlsuser.md \
+ proxy-tlsv1.md \
+ proxy-user.md \
+ proxy.md \
+ proxy1.0.md \
+ proxytunnel.md \
+ pubkey.md \
+ quote.md \
+ random-file.md \
+ range.md \
+ rate.md \
+ raw.md \
+ referer.md \
+ remote-header-name.md \
+ remote-name-all.md \
+ remote-name.md \
+ remote-time.md \
+ remove-on-error.md \
+ request-target.md \
+ request.md \
+ resolve.md \
+ retry-all-errors.md \
+ retry-connrefused.md \
+ retry-delay.md \
+ retry-max-time.md \
+ retry.md \
+ sasl-authzid.md \
+ sasl-ir.md \
+ service-name.md \
+ show-error.md \
+ silent.md \
+ socks4.md \
+ socks4a.md \
+ socks5-basic.md \
+ socks5-gssapi-nec.md \
+ socks5-gssapi-service.md \
+ socks5-gssapi.md \
+ socks5-hostname.md \
+ socks5.md \
+ speed-limit.md \
+ speed-time.md \
+ ssl-allow-beast.md \
+ ssl-auto-client-cert.md \
+ ssl-no-revoke.md \
+ ssl-reqd.md \
+ ssl-revoke-best-effort.md \
+ ssl.md \
+ sslv2.md \
+ sslv3.md \
+ stderr.md \
+ styled-output.md \
+ suppress-connect-headers.md \
+ tcp-fastopen.md \
+ tcp-nodelay.md \
+ telnet-option.md \
+ tftp-blksize.md \
+ tftp-no-options.md \
+ time-cond.md \
+ tls-max.md \
+ tls13-ciphers.md \
+ tlsauthtype.md \
+ tlspassword.md \
+ tlsuser.md \
+ tlsv1.0.md \
+ tlsv1.1.md \
+ tlsv1.2.md \
+ tlsv1.3.md \
+ tlsv1.md \
+ tr-encoding.md \
+ trace-ascii.md \
+ trace-config.md \
+ trace-ids.md \
+ trace-time.md \
+ trace.md \
+ unix-socket.md \
+ upload-file.md \
+ url.md \
+ url-query.md \
+ use-ascii.md \
+ user-agent.md \
+ user.md \
+ variable.md \
+ verbose.md \
+ version.md \
+ write-out.md \
+ xattr.md
diff --git a/docs/cmdline-opts/_AUTHORS.md b/docs/cmdline-opts/_AUTHORS.md
new file mode 100644
index 000000000..0c9bfb953
--- /dev/null
+++ b/docs/cmdline-opts/_AUTHORS.md
@@ -0,0 +1,5 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# AUTHORS
+Daniel Stenberg is the main author, but the whole list of contributors is
+found in the separate THANKS file.
diff --git a/docs/cmdline-opts/_BUGS.md b/docs/cmdline-opts/_BUGS.md
new file mode 100644
index 000000000..45630d435
--- /dev/null
+++ b/docs/cmdline-opts/_BUGS.md
@@ -0,0 +1,5 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# BUGS
+If you experience any problems with curl, submit an issue in the project's bug
+tracker on GitHub: https://github.com/curl/curl/issues
diff --git a/docs/cmdline-opts/_DESCRIPTION.md b/docs/cmdline-opts/_DESCRIPTION.md
new file mode 100644
index 000000000..3e06c1b38
--- /dev/null
+++ b/docs/cmdline-opts/_DESCRIPTION.md
@@ -0,0 +1,11 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# DESCRIPTION
+
+**curl** is a tool for transferring data from or to a server using URLs. It
+supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS,
+IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP,
+SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.
+
+curl is powered by libcurl for all transfer-related features. See
+*libcurl(3)* for details.
diff --git a/docs/cmdline-opts/_ENVIRONMENT.md b/docs/cmdline-opts/_ENVIRONMENT.md
new file mode 100644
index 000000000..cf30d4740
--- /dev/null
+++ b/docs/cmdline-opts/_ENVIRONMENT.md
@@ -0,0 +1,114 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# ENVIRONMENT
+The environment variables can be specified in lower case or upper case. The
+lower case version has precedence. `http_proxy` is an exception as it is only
+available in lower case.
+
+Using an environment variable to set the proxy has the same effect as using
+the --proxy option.
+
+## `http_proxy` [protocol://]<host>[:port]
+Sets the proxy server to use for HTTP.
+
+## `HTTPS_PROXY` [protocol://]<host>[:port]
+Sets the proxy server to use for HTTPS.
+
+## `[url-protocol]_PROXY` [protocol://]<host>[:port]
+Sets the proxy server to use for [url-protocol], where the protocol is a
+protocol that curl supports and as specified in a URL. FTP, FTPS, POP3, IMAP,
+SMTP, LDAP, etc.
+
+## `ALL_PROXY` [protocol://]<host>[:port]
+Sets the proxy server to use if no protocol-specific proxy is set.
+
+## `NO_PROXY` <comma-separated list of hosts/domains>
+list of host names that should not go through any proxy. If set to an asterisk
+'*' only, it matches all hosts. Each name in this list is matched as either
+a domain name which contains the hostname, or the hostname itself.
+
+This environment variable disables use of the proxy even when specified with
+the --proxy option. That is
+
+ NO_PROXY=direct.example.com curl -x http://proxy.example.com
+ http://direct.example.com
+
+accesses the target URL directly, and
+
+ NO_PROXY=direct.example.com curl -x http://proxy.example.com
+ http://somewhere.example.com
+
+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 addresses can be specified using CIDR notation: an appended slash and
+number specifies the number of "network bits" out of the address to use in the
+comparison (added in 7.86.0). For example "192.168.0.0/16" would match all
+addresses starting with "192.168".
+
+## `APPDATA` <dir>
+On Windows, this variable is used when trying to find the home directory. If
+the primary home variable are all unset.
+
+## `COLUMNS` <terminal width>
+If set, the specified number of characters is used as the terminal width when
+the alternative progress-bar is shown. If not set, curl tries to figure it out
+using other ways.
+
+## `CURL_CA_BUNDLE` <file>
+If set, it is used as the --cacert value. This environment variable is ignored
+if Schannel is used as the TLS backend.
+
+## `CURL_HOME` <dir>
+If set, is the first variable curl checks when trying to find its home
+directory. If not set, it continues to check *XDG_CONFIG_HOME*
+
+## `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
+invoked. Setting a name that is not a built-in alternative makes curl stay
+with the default.
+
+SSL backend names (case-insensitive): **bearssl**, **gnutls**, **mbedtls**,
+**openssl**, **rustls**, **schannel**, **secure-transport**, **wolfssl**
+
+## `HOME` <dir>
+If set, this is used to find the home directory when that is needed. Like when
+looking for the default .curlrc. *CURL_HOME* and *XDG_CONFIG_HOME*
+have preference.
+
+## `QLOGDIR` <directory name>
+If curl was built with HTTP/3 support, setting this environment variable to a
+local directory makes 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 the ngtcp2 and quiche QUIC backends.
+
+## `SHELL`
+Used on VMS when trying to detect if using a **DCL** or a **unix** shell.
+
+## `SSL_CERT_DIR` <dir>
+If set, it is used as the --capath value. This environment variable is ignored
+if Schannel is used as the TLS backend.
+
+## `SSL_CERT_FILE` <path>
+If set, it is used as the --cacert value. This environment variable is ignored
+if Schannel is used as the TLS backend.
+
+## `SSLKEYLOGFILE` <file name>
+If you set this environment variable to a file name, curl stores 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
+and wolfSSL.
+
+## `USERPROFILE` <dir>
+On Windows, this variable is used when trying to find the home directory. If
+the other, primary, variable are all unset. If set, curl uses the path
+**"$USERPROFILE\Application Data"**.
+
+## `XDG_CONFIG_HOME` <dir>
+If *CURL_HOME* is not set, this variable is checked when looking for a
+default .curlrc file.
diff --git a/docs/cmdline-opts/_EXITCODES.md b/docs/cmdline-opts/_EXITCODES.md
new file mode 100644
index 000000000..ac7ab5ca1
--- /dev/null
+++ b/docs/cmdline-opts/_EXITCODES.md
@@ -0,0 +1,201 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# EXIT CODES
+There are a bunch of different error codes and their corresponding error
+messages that may appear under error conditions. At the time of this writing,
+the exit codes are:
+## 0
+Success. The operation completed successfully according to the instructions.
+## 1
+Unsupported protocol. This build of curl has no support for this protocol.
+## 2
+Failed to initialize.
+## 3
+URL malformed. The syntax was not correct.
+## 4
+A feature or option that was needed to perform the desired request was not
+enabled or was explicitly disabled at build-time. To make curl able to do
+this, you probably need another build of libcurl.
+## 5
+Could not resolve proxy. The given proxy host could not be resolved.
+## 6
+Could not resolve host. The given remote host could not be resolved.
+## 7
+Failed to connect to host.
+## 8
+Weird server reply. The server sent data curl could not parse.
+## 9
+FTP access denied. The server denied login or denied access to the particular
+resource or directory you wanted to reach. Most often you tried to change to a
+directory that does not exist on the server.
+## 10
+FTP accept failed. While waiting for the server to connect back when an active
+FTP session is used, an error code was sent over the control connection or
+similar.
+## 11
+FTP weird PASS reply. Curl could not parse the reply sent to the PASS request.
+## 12
+During an active FTP session while waiting for the server to connect back to
+curl, the timeout expired.
+## 13
+FTP weird PASV reply, Curl could not parse the reply sent to the PASV request.
+## 14
+FTP weird 227 format. Curl could not parse the 227-line the server sent.
+## 15
+FTP cannot use host. Could not resolve the host IP we got in the 227-line.
+## 16
+HTTP/2 error. A problem was detected in the HTTP2 framing layer. This is
+somewhat generic and can be one out of several problems, see the error message
+for details.
+## 17
+FTP could not set binary. Could not change transfer method to binary.
+## 18
+Partial file. Only a part of the file was transferred.
+## 19
+FTP could not download/access the given file, the RETR (or similar) command
+failed.
+## 21
+FTP quote error. A quote command returned error from the server.
+## 22
+HTTP page not retrieved. The requested URL was not found or returned another
+error with the HTTP error code being 400 or above. This return code only
+appears if --fail is used.
+## 23
+Write error. Curl could not write data to a local filesystem or similar.
+## 25
+Failed starting the upload. For FTP, the server typically denied the STOR
+command.
+## 26
+Read error. Various reading problems.
+## 27
+Out of memory. A memory allocation request failed.
+## 28
+Operation timeout. The specified time-out period was reached according to the
+conditions.
+## 30
+FTP PORT failed. The PORT command failed. Not all FTP servers support the PORT
+command, try doing a transfer using PASV instead.
+## 31
+FTP could not use REST. The REST command failed. This command is used for
+resumed FTP transfers.
+## 33
+HTTP range error. The range "command" did not work.
+## 34
+HTTP post error. Internal post-request generation error.
+## 35
+SSL connect error. The SSL handshaking failed.
+## 36
+Bad download resume. Could not continue an earlier aborted download.
+## 37
+FILE could not read file. Failed to open the file. Permissions?
+## 38
+LDAP cannot bind. LDAP bind operation failed.
+## 39
+LDAP search failed.
+## 41
+Function not found. A required LDAP function was not found.
+## 42
+Aborted by callback. An application told curl to abort the operation.
+## 43
+Internal error. A function was called with a bad parameter.
+## 45
+Interface error. A specified outgoing interface could not be used.
+## 47
+Too many redirects. When following redirects, curl hit the maximum amount.
+## 48
+Unknown option specified to libcurl. This indicates that you passed a weird
+option to curl that was passed on to libcurl and rejected. Read up in the
+manual!
+## 49
+Malformed telnet option.
+## 52
+The server did not reply anything, which here is considered an error.
+## 53
+SSL crypto engine not found.
+## 54
+Cannot set SSL crypto engine as default.
+## 55
+Failed sending network data.
+## 56
+Failure in receiving network data.
+## 58
+Problem with the local certificate.
+## 59
+Could not use specified SSL cipher.
+## 60
+Peer certificate cannot be authenticated with known CA certificates.
+## 61
+Unrecognized transfer encoding.
+## 63
+Maximum file size exceeded.
+## 64
+Requested FTP SSL level failed.
+## 65
+Sending the data requires a rewind that failed.
+## 66
+Failed to initialize SSL Engine.
+## 67
+The user name, password, or similar was not accepted and curl failed to log in.
+## 68
+File not found on TFTP server.
+## 69
+Permission problem on TFTP server.
+## 70
+Out of disk space on TFTP server.
+## 71
+Illegal TFTP operation.
+## 72
+Unknown TFTP transfer ID.
+## 73
+File already exists (TFTP).
+## 74
+No such user (TFTP).
+## 77
+Problem reading the SSL CA cert (path? access rights?).
+## 78
+The resource referenced in the URL does not exist.
+## 79
+An unspecified error occurred during the SSH session.
+## 80
+Failed to shut down the SSL connection.
+## 82
+Could not load CRL file, missing or wrong format (added in 7.19.0).
+## 83
+Issuer check failed (added in 7.19.0).
+## 84
+The FTP PRET command failed.
+## 85
+Mismatch of RTSP CSeq numbers.
+## 86
+Mismatch of RTSP Session Identifiers.
+## 87
+Unable to parse FTP file list.
+## 88
+FTP chunk callback reported error.
+## 89
+No connection available, the session is queued.
+## 90
+SSL public key does not matched pinned public key.
+## 91
+Invalid SSL certificate status.
+## 92
+Stream error in HTTP/2 framing layer.
+## 93
+An API function was called from inside a callback.
+## 94
+An authentication function returned an error.
+## 95
+A problem was detected in the HTTP/3 layer. This is somewhat generic and can
+be one out of several problems, see the error message for details.
+## 96
+QUIC connection error. This error may be caused by an SSL library error. QUIC
+is the protocol used for HTTP/3 transfers.
+## 97
+Proxy handshake error.
+## 98
+A client-side certificate is required to complete the TLS handshake.
+## 99
+Poll or select returned fatal error.
+## XX
+More error codes might appear here in future releases. The existing ones are
+meant to never change.
diff --git a/docs/cmdline-opts/_FILES.md b/docs/cmdline-opts/_FILES.md
new file mode 100644
index 000000000..8c5d3faa7
--- /dev/null
+++ b/docs/cmdline-opts/_FILES.md
@@ -0,0 +1,6 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# FILES
+*~/.curlrc*
+
+Default config file, see --config for details.
diff --git a/docs/cmdline-opts/_GLOBBING.md b/docs/cmdline-opts/_GLOBBING.md
new file mode 100644
index 000000000..282356c3e
--- /dev/null
+++ b/docs/cmdline-opts/_GLOBBING.md
@@ -0,0 +1,40 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# GLOBBING
+You can specify multiple URLs or parts of URLs by writing lists within braces
+or ranges within brackets. We call this "globbing".
+
+Provide a list with three different names like this:
+
+ "http://site.{one,two,three}.com"
+
+Do sequences of alphanumeric series by using [] as in:
+
+ "ftp://ftp.example.com/file[1-100].txt"
+
+With leading zeroes:
+
+ "ftp://ftp.example.com/file[001-100].txt"
+
+With letters through the alphabet:
+
+ "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"
+
+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[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
+interfering with it. This also goes for other characters treated special, like
+for example '&', '?' and '*'.
+
+Switch off globbing with --globoff.
diff --git a/docs/cmdline-opts/_NAME.md b/docs/cmdline-opts/_NAME.md
new file mode 100644
index 000000000..b0d891614
--- /dev/null
+++ b/docs/cmdline-opts/_NAME.md
@@ -0,0 +1,4 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# NAME
+curl - transfer a URL
diff --git a/docs/cmdline-opts/_OPTIONS.md b/docs/cmdline-opts/_OPTIONS.md
new file mode 100644
index 000000000..1b2556659
--- /dev/null
+++ b/docs/cmdline-opts/_OPTIONS.md
@@ -0,0 +1,26 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# OPTIONS
+Options start with one or two dashes. Many of the options require an
+additional value next to them. If provided text does not start with a dash, it
+is presumed to be and treated as a URL.
+
+The short "single-dash" form of the options, -d for example, may be used with
+or without a space between it and its value, although a space is a recommended
+separator. The long "double-dash" form, --data for example, requires a space
+between it and its value.
+
+Short version options that do not need any additional values can be used
+immediately next to each other, like for example you can specify all the
+options *-O*, *-L* and *-v* at once as *-OLv*.
+
+In general, all boolean options are enabled with --**option** and yet again
+disabled with --**no-**option. That is, you use the same option name but
+prefix it with "no-". However, in this list we mostly only list and show the
+*--option* version of them.
+
+When --next is used, it resets the parser state and you start again with a
+clean option state, except for the options that are "global". Global options
+retain their values and meaning even after --next.
+
+The following options are global: `%GLOBALS`.
diff --git a/docs/cmdline-opts/_OUTPUT.md b/docs/cmdline-opts/_OUTPUT.md
new file mode 100644
index 000000000..32a5457af
--- /dev/null
+++ b/docs/cmdline-opts/_OUTPUT.md
@@ -0,0 +1,11 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# OUTPUT
+If not told otherwise, curl writes the received data to stdout. It can be
+instructed to instead save that data into a local file, using the --output or
+--remote-name options. If curl is given multiple URLs to transfer on the
+command line, it similarly needs multiple options for where to save them.
+
+curl does not parse or otherwise "understand" the content it gets or writes as
+output. It does no encoding or decoding, unless explicitly asked to with
+dedicated command line options.
diff --git a/docs/cmdline-opts/_PROGRESS.md b/docs/cmdline-opts/_PROGRESS.md
new file mode 100644
index 000000000..80e36f102
--- /dev/null
+++ b/docs/cmdline-opts/_PROGRESS.md
@@ -0,0 +1,25 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# "PROGRESS METER"
+
+curl normally displays a progress meter during operations, indicating the
+amount of transferred data, transfer speeds and estimated time left, etc. The
+progress meter displays the transfer rate in bytes per second. The suffixes
+(k, M, G, T, P) are 1024 based. For example 1k is 1024 bytes. 1M is 1048576
+bytes.
+
+curl displays this data to the terminal by default, so if you invoke curl to
+do an operation and it is about to write data to the terminal, it *disables*
+the progress meter as otherwise it would mess up the output mixing progress
+meter and response data.
+
+If you want a progress meter for HTTP POST or PUT requests, you need to
+redirect the response output to a file, using shell redirect (>), --output or
+similar.
+
+This does not apply to FTP upload as that operation does not spit out any
+response data to the terminal.
+
+If you prefer a progress "bar" instead of the regular meter, --progress-bar is
+your friend. You can also disable the progress meter completely with the
+--silent option.
diff --git a/docs/cmdline-opts/_PROTOCOLS.md b/docs/cmdline-opts/_PROTOCOLS.md
new file mode 100644
index 000000000..b834f9ae3
--- /dev/null
+++ b/docs/cmdline-opts/_PROTOCOLS.md
@@ -0,0 +1,51 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# PROTOCOLS
+curl supports numerous protocols, or put in URL terms: schemes. Your
+particular build may not support them all.
+## DICT
+Lets you lookup words using online dictionaries.
+## FILE
+Read or write local files. curl does not support accessing file:// URL
+remotely, but when running on Microsoft Windows using the native UNC approach
+works.
+## FTP(S)
+curl supports the File Transfer Protocol with a lot of tweaks and levers. With
+or without using TLS.
+## GOPHER(S)
+Retrieve files.
+## HTTP(S)
+curl supports HTTP with numerous options and variations. It can speak HTTP
+version 0.9, 1.0, 1.1, 2 and 3 depending on build options and the correct
+command line options.
+## IMAP(S)
+Using the mail reading protocol, curl can "download" emails for you. With or
+without using TLS.
+## LDAP(S)
+curl can do directory lookups for you, with or without TLS.
+## MQTT
+curl supports MQTT version 3. Downloading over MQTT equals "subscribe" to a
+topic while uploading/posting equals "publish" on a topic. MQTT over TLS is
+not supported (yet).
+## POP3(S)
+Downloading from a pop3 server means getting a mail. With or without using
+TLS.
+## RTMP(S)
+The **Realtime Messaging Protocol** is primarily used to serve streaming media
+and curl can download it.
+## RTSP
+curl supports RTSP 1.0 downloads.
+## SCP
+curl supports SSH version 2 scp transfers.
+## SFTP
+curl supports SFTP (draft 5) done over SSH version 2.
+## SMB(S)
+curl supports SMB version 1 for upload and download.
+## SMTP(S)
+Uploading contents to an SMTP server means sending an email. With or without
+TLS.
+## TELNET
+Telling curl to fetch a telnet URL starts an interactive session where it
+sends what it reads on stdin and outputs what the server sends it.
+## TFTP
+curl can do TFTP downloads and uploads.
diff --git a/docs/cmdline-opts/_PROXYPREFIX.md b/docs/cmdline-opts/_PROXYPREFIX.md
new file mode 100644
index 000000000..297b56c4b
--- /dev/null
+++ b/docs/cmdline-opts/_PROXYPREFIX.md
@@ -0,0 +1,22 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# PROXY PROTOCOL PREFIXES
+The proxy string may be specified with a protocol:// prefix to specify
+alternative proxy protocols. (Added in 7.21.7)
+
+If no protocol is specified in the proxy string or if the string does not
+match a supported one, the proxy is treated as an HTTP proxy.
+
+The supported proxy protocol prefixes are as follows:
+## http://
+Makes it use it as an HTTP proxy. The default if no scheme prefix is used.
+## https://
+Makes it treated as an **HTTPS** proxy.
+## socks4://
+Makes it the equivalent of --socks4
+## socks4a://
+Makes it the equivalent of --socks4a
+## socks5://
+Makes it the equivalent of --socks5
+## socks5h://
+Makes it the equivalent of --socks5-hostname
diff --git a/docs/cmdline-opts/_SEEALSO.md b/docs/cmdline-opts/_SEEALSO.md
new file mode 100644
index 000000000..f4d0b55cf
--- /dev/null
+++ b/docs/cmdline-opts/_SEEALSO.md
@@ -0,0 +1,5 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# SEE ALSO
+
+**ftp (1)**, **wget (1)**
diff --git a/docs/cmdline-opts/_SYNOPSIS.md b/docs/cmdline-opts/_SYNOPSIS.md
new file mode 100644
index 000000000..381587744
--- /dev/null
+++ b/docs/cmdline-opts/_SYNOPSIS.md
@@ -0,0 +1,5 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# SYNOPSIS
+
+**curl [options / URLs]**
diff --git a/docs/cmdline-opts/_URL.md b/docs/cmdline-opts/_URL.md
new file mode 100644
index 000000000..0084ec612
--- /dev/null
+++ b/docs/cmdline-opts/_URL.md
@@ -0,0 +1,28 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# URL
+The URL syntax is protocol-dependent. You find a detailed description in
+RFC 3986.
+
+If you provide a URL without a leading **protocol://** scheme, curl guesses
+what protocol you want. It then defaults to HTTP but assumes others based on
+often-used host name prefixes. For example, for host names starting with
+"ftp." curl assumes you want FTP.
+
+You can specify any amount of URLs on the command line. They are fetched in a
+sequential manner in the specified order unless you use --parallel. You can
+specify command line options and URLs mixed and in any order on the command
+line.
+
+curl attempts to reuse connections when doing multiple transfers, so that
+getting many files from the same server do not use multiple connects and setup
+handshakes. This improves speed. Connection reuse can only be done for URLs
+specified for a single command line invocation and cannot be performed between
+separate curl runs.
+
+Provide an IPv6 zone id in the URL with an escaped percentage sign. Like in
+
+ "http://[fe80::3%25eth0]/"
+
+Everything provided on the command line that is not a command line option or
+its argument, curl assumes is a URL and treats it as such.
diff --git a/docs/cmdline-opts/_VARIABLES.md b/docs/cmdline-opts/_VARIABLES.md
new file mode 100644
index 000000000..3e17bfdae
--- /dev/null
+++ b/docs/cmdline-opts/_VARIABLES.md
@@ -0,0 +1,44 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# VARIABLES
+curl supports command line variables (added in 8.3.0). Set variables with
+--variable name=content or --variable name@file (where "file" can be stdin if
+set to a single dash (-)).
+
+Variable contents can be expanded in option parameters using "{{name}}" (without
+the quotes) if the option name is prefixed with "--expand-". This gets the
+contents of the variable "name" inserted, or a blank if the name does not
+exist as a variable. Insert "{{" verbatim in the string by prefixing it with a
+backslash, like "\{{".
+
+You an access and expand environment variables by first importing them. You
+can select to either require the environment variable to be set or you can
+provide a default value in case it is not already set. Plain --variable %name
+imports the variable called 'name' but exits with an error if that environment
+variable is not already set. To provide a default value if it is not set, use
+--variable %name=content or --variable %name@content.
+
+Example. Get the USER environment variable into the URL, fail if USER is not
+set:
+
+ --variable '%USER'
+ --expand-url = "https://example.com/api/{{USER}}/method"
+
+When expanding variables, curl supports a set of functions that can make the
+variable contents more convenient to use. It can trim leading and trailing
+white space with *trim*, it can output the contents as a JSON quoted string
+with *json*, URL encode the string with *url* or base64 encode it with
+*b64*. You apply function to a variable expansion, add them colon separated to
+the right side of the variable. Variable content holding null bytes that are
+not encoded when expanded cause error.
+
+Example: get the contents of a file called $HOME/.secret into a variable
+called "fix". Make sure that the content is trimmed and percent-encoded sent
+as POST data:
+
+ --variable %HOME
+ --expand-variable fix@{{HOME}}/.secret
+ --expand-data "{{fix:trim:url}}"
+ https://example.com/
+
+Command line variables and expansions were added in in 8.3.0.
diff --git a/docs/cmdline-opts/_VERSION.md b/docs/cmdline-opts/_VERSION.md
new file mode 100644
index 000000000..4c759f147
--- /dev/null
+++ b/docs/cmdline-opts/_VERSION.md
@@ -0,0 +1,15 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# VERSION
+
+This man page describes curl %VERSION. If you use a later version, chances are
+this man page does not fully document it. If you use an earlier version, this
+document tries to include version information about which specific version
+that introduced changes.
+
+You can always learn which the latest curl version is by running
+
+ curl https://curl.se/info
+
+The online version of this man page is always showing the latest incarnation:
+https://curl.se/docs/manpage.html
diff --git a/docs/cmdline-opts/_WWW.md b/docs/cmdline-opts/_WWW.md
new file mode 100644
index 000000000..35d946697
--- /dev/null
+++ b/docs/cmdline-opts/_WWW.md
@@ -0,0 +1,4 @@
+<!-- Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. -->
+<!-- SPDX-License-Identifier: curl -->
+# WWW
+https://curl.se
diff --git a/docs/cmdline-opts/abstract-unix-socket.d b/docs/cmdline-opts/abstract-unix-socket.d
deleted file mode 100644
index 5c2fd4a47..000000000
--- a/docs/cmdline-opts/abstract-unix-socket.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: abstract-unix-socket
-Arg: <path>
-Help: Connect via abstract Unix domain socket
-Added: 7.53.0
-Protocols: HTTP
-Category: connection
-See-also: unix-socket
-Example: --abstract-unix-socket socketpath $URL
-Multi: single
----
-Connect through an abstract Unix domain socket, instead of using the network.
-Note: netstat shows the path of an abstract socket prefixed with '@', however
-the <path> argument should not have this leading character.
diff --git a/docs/cmdline-opts/abstract-unix-socket.md b/docs/cmdline-opts/abstract-unix-socket.md
new file mode 100644
index 000000000..27bc8cad6
--- /dev/null
+++ b/docs/cmdline-opts/abstract-unix-socket.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: abstract-unix-socket
+Arg: <path>
+Help: Connect via abstract Unix domain socket
+Added: 7.53.0
+Protocols: HTTP
+Category: connection
+Multi: single
+See-also:
+ - unix-socket
+Example:
+ - --abstract-unix-socket socketpath $URL
+---
+
+# `--abstract-unix-socket`
+
+Connect through an abstract Unix domain socket, instead of using the network.
+Note: netstat shows the path of an abstract socket prefixed with '@', however
+the <path> argument should not have this leading character.
diff --git a/docs/cmdline-opts/alt-svc.d b/docs/cmdline-opts/alt-svc.d
deleted file mode 100644
index 276ac1b66..000000000
--- a/docs/cmdline-opts/alt-svc.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: alt-svc
-Arg: <file name>
-Protocols: HTTPS
-Help: Enable alt-svc with this cache file
-Added: 7.64.1
-Category: http
-See-also: resolve connect-to
-Example: --alt-svc svc.txt $URL
-Multi: append
----
-This option enables the alt-svc parser in curl. If the file name points to an
-existing alt-svc cache file, that gets used. After a completed transfer, the
-cache is saved to the file name again if it has been modified.
-
-Specify a "" file name (zero length) to avoid loading/saving and make curl
-just handle the cache in memory.
-
-If this option is used several times, curl loads contents from all the
-files but the last one is used for saving.
diff --git a/docs/cmdline-opts/alt-svc.md b/docs/cmdline-opts/alt-svc.md
new file mode 100644
index 000000000..0a0f17df5
--- /dev/null
+++ b/docs/cmdline-opts/alt-svc.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: alt-svc
+Arg: <file name>
+Protocols: HTTPS
+Help: Enable alt-svc with this cache file
+Added: 7.64.1
+Category: http
+Multi: append
+See-also:
+ - resolve
+ - connect-to
+Example:
+ - --alt-svc svc.txt $URL
+---
+
+# `--alt-svc`
+
+This option enables the alt-svc parser in curl. If the file name points to an
+existing alt-svc cache file, that gets used. After a completed transfer, the
+cache is saved to the file name again if it has been modified.
+
+Specify a "" file name (zero length) to avoid loading/saving and make curl
+just handle the cache in memory.
+
+If this option is used several times, curl loads contents from all the
+files but the last one is used for saving.
diff --git a/docs/cmdline-opts/anyauth.d b/docs/cmdline-opts/anyauth.d
deleted file mode 100644
index 2498bdcd8..000000000
--- a/docs/cmdline-opts/anyauth.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: anyauth
-Help: Pick any authentication method
-Protocols: HTTP
-See-also: proxy-anyauth basic digest
-Category: http proxy auth
-Example: --anyauth --user me:pwd $URL
-Added: 7.10.6
-Multi: mutex
----
-Tells curl to figure out authentication method by itself, and use the most
-secure one the remote site claims to support. This is done by first doing a
-request and checking the response-headers, thus possibly inducing an extra
-network round-trip. This is used instead of setting a specific authentication
-method, which you can do with --basic, --digest, --ntlm, and --negotiate.
-
-Using --anyauth is not recommended if you do uploads from stdin, since it may
-require data to be sent twice and then the client must be able to rewind. If
-the need should arise when uploading from stdin, the upload operation fails.
-
-Used together with --user.
diff --git a/docs/cmdline-opts/anyauth.md b/docs/cmdline-opts/anyauth.md
new file mode 100644
index 000000000..150e069e8
--- /dev/null
+++ b/docs/cmdline-opts/anyauth.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: anyauth
+Help: Pick any authentication method
+Protocols: HTTP
+Category: http proxy auth
+Added: 7.10.6
+Multi: mutex
+See-also:
+ - proxy-anyauth
+ - basic
+ - digest
+Example:
+ - --anyauth --user me:pwd $URL
+---
+
+# `--anyauth`
+
+Tells curl to figure out authentication method by itself, and use the most
+secure one the remote site claims to support. This is done by first doing a
+request and checking the response-headers, thus possibly inducing an extra
+network round-trip. This is used instead of setting a specific authentication
+method, which you can do with --basic, --digest, --ntlm, and --negotiate.
+
+Using --anyauth is not recommended if you do uploads from stdin, since it may
+require data to be sent twice and then the client must be able to rewind. If
+the need should arise when uploading from stdin, the upload operation fails.
+
+Used together with --user.
diff --git a/docs/cmdline-opts/append.d b/docs/cmdline-opts/append.d
deleted file mode 100644
index 7561c951c..000000000
--- a/docs/cmdline-opts/append.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: a
-Long: append
-Help: Append to target file when uploading
-Protocols: FTP SFTP
-Category: ftp sftp
-See-also: range continue-at
-Example: --upload-file local --append ftp://example.com/
-Added: 4.8
-Multi: boolean
----
-When used in an upload, this option makes curl append to the target file
-instead of overwriting it. If the remote file does not exist, it is
-created. Note that this flag is ignored by some SFTP servers (including
-OpenSSH).
diff --git a/docs/cmdline-opts/append.md b/docs/cmdline-opts/append.md
new file mode 100644
index 000000000..3d0030d6a
--- /dev/null
+++ b/docs/cmdline-opts/append.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: a
+Long: append
+Help: Append to target file when uploading
+Protocols: FTP SFTP
+Category: ftp sftp
+Added: 4.8
+Multi: boolean
+See-also:
+ - range
+ - continue-at
+Example:
+ - --upload-file local --append ftp://example.com/
+---
+
+# `--append`
+
+When used in an upload, this option makes curl append to the target file
+instead of overwriting it. If the remote file does not exist, it is
+created. Note that this flag is ignored by some SFTP servers (including
+OpenSSH).
diff --git a/docs/cmdline-opts/aws-sigv4.d b/docs/cmdline-opts/aws-sigv4.d
deleted file mode 100644
index b771eee6a..000000000
--- a/docs/cmdline-opts/aws-sigv4.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: aws-sigv4
-Arg: <provider1[:provider2[:region[:service]]]>
-Help: Use AWS V4 signature authentication
-Category: auth http
-Added: 7.75.0
-See-also: basic user
-Example: --aws-sigv4 "aws:amz:us-east-2:es" --user "key:secret" $URL
-Multi: single
----
-Use AWS V4 signature authentication in the transfer.
-
-The provider argument is a string that is used by the algorithm when creating
-outgoing authentication headers.
-
-The region argument is a string that points to a geographic area of
-a resources collection (region-code) when the region name is omitted from
-the endpoint.
-
-The service argument is a string that points to a function provided by a cloud
-(service-code) when the service name is omitted from the endpoint.
diff --git a/docs/cmdline-opts/aws-sigv4.md b/docs/cmdline-opts/aws-sigv4.md
new file mode 100644
index 000000000..1b3909244
--- /dev/null
+++ b/docs/cmdline-opts/aws-sigv4.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: aws-sigv4
+Protocols: HTTP
+Arg: <provider1[:provider2[:region[:service]]]>
+Help: Use AWS V4 signature authentication
+Category: auth http
+Added: 7.75.0
+Multi: single
+See-also:
+ - basic
+ - user
+Example:
+ - --aws-sigv4 "aws:amz:us-east-2:es" --user "key:secret" $URL
+---
+
+# `--aws-sigv4`
+
+Use AWS V4 signature authentication in the transfer.
+
+The provider argument is a string that is used by the algorithm when creating
+outgoing authentication headers.
+
+The region argument is a string that points to a geographic area of
+a resources collection (region-code) when the region name is omitted from
+the endpoint.
+
+The service argument is a string that points to a function provided by a cloud
+(service-code) when the service name is omitted from the endpoint.
diff --git a/docs/cmdline-opts/basic.d b/docs/cmdline-opts/basic.d
deleted file mode 100644
index cb0642620..000000000
--- a/docs/cmdline-opts/basic.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: basic
-Help: Use HTTP Basic Authentication
-See-also: proxy-basic
-Protocols: HTTP
-Category: auth
-Example: -u name:password --basic $URL
-Added: 7.10.6
-Multi: mutex
----
-Tells curl to use HTTP Basic authentication with the remote host. This is the
-default and this option is usually pointless, unless you use it to override a
-previously set option that sets a different authentication method (such as
---ntlm, --digest, or --negotiate).
-
-Used together with --user.
diff --git a/docs/cmdline-opts/basic.md b/docs/cmdline-opts/basic.md
new file mode 100644
index 000000000..34b019175
--- /dev/null
+++ b/docs/cmdline-opts/basic.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: basic
+Help: Use HTTP Basic Authentication
+Protocols: HTTP
+Category: auth
+Added: 7.10.6
+Multi: mutex
+See-also:
+ - proxy-basic
+Example:
+ - -u name:password --basic $URL
+---
+
+# `--basic`
+
+Tells curl to use HTTP Basic authentication with the remote host. This is the
+default and this option is usually pointless, unless you use it to override a
+previously set option that sets a different authentication method (such as
+--ntlm, --digest, or --negotiate).
+
+Used together with --user.
diff --git a/docs/cmdline-opts/ca-native.d b/docs/cmdline-opts/ca-native.d
deleted file mode 100644
index 51e36918a..000000000
--- a/docs/cmdline-opts/ca-native.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ca-native
-Help: Use CA certificates from the native OS
-Protocols: TLS
-Category: tls
-See-also: cacert capath insecure
-Example: --ca-native $URL
-Added: 8.2.0
-Multi: boolean
----
-Tells curl to use the CA store from the native operating system to verify the
-peer. By default, curl otherwise uses a CA store provided in a single file or
-directory, but when using this option it interfaces the operating system's
-own vault.
-
-This option only works for curl on Windows when built to use OpenSSL. When
-curl on Windows is built to use Schannel, this feature is implied and curl
-then only uses the native CA store.
-
-curl built with wolfSSL also supports this option (added in 8.3.0).
diff --git a/docs/cmdline-opts/ca-native.md b/docs/cmdline-opts/ca-native.md
new file mode 100644
index 000000000..d0b4bfa5a
--- /dev/null
+++ b/docs/cmdline-opts/ca-native.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ca-native
+Help: Use CA certificates from the native OS
+Protocols: TLS
+Category: tls
+Added: 8.2.0
+Multi: boolean
+See-also:
+ - cacert
+ - capath
+ - insecure
+Example:
+ - --ca-native $URL
+---
+
+# `--ca-native`
+
+Tells curl to use the CA store from the native operating system to verify the
+peer. By default, curl otherwise uses a CA store provided in a single file or
+directory, but when using this option it interfaces the operating system's
+own vault.
+
+This option works for curl on Windows when built to use OpenSSL, wolfSSL
+(added in 8.3.0) or GnuTLS (added in 8.5.0). When curl on Windows is built to
+use Schannel, this feature is implied and curl then only uses the native CA
+store.
diff --git a/docs/cmdline-opts/cacert.d b/docs/cmdline-opts/cacert.d
deleted file mode 100644
index 5e4e74901..000000000
--- a/docs/cmdline-opts/cacert.d
+++ /dev/null
@@ -1,35 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: cacert
-Arg: <file>
-Help: CA certificate to verify peer against
-Protocols: TLS
-Category: tls
-See-also: capath insecure
-Example: --cacert CA-file.txt $URL
-Added: 7.5
-Multi: single
----
-Tells curl to use the specified certificate file to verify the peer. The file
-may contain multiple CA certificates. The certificate(s) must be in PEM
-format. Normally curl is built to use a default file for this, so this option
-is typically used to alter that default file.
-
-curl recognizes the environment variable named 'CURL_CA_BUNDLE' if it is
-set, and uses the given path as a path to a CA cert bundle. This option
-overrides that variable.
-
-The windows version of curl automatically looks for a CA certs file named
-'curl-ca-bundle.crt', either in the same directory as curl.exe, or in the
-Current Working Directory, or in any folder along your PATH.
-
-(iOS and macOS only) If curl is built against Secure Transport, then this
-option is supported for backward compatibility with other SSL engines, but it
-should not be set. If the option is not set, then curl uses the certificates
-in the system and user Keychain to verify the peer, which is the preferred
-method of verifying the peer's certificate chain.
-
-(Schannel only) This option is supported for Schannel in Windows 7 or later
-(added in 7.60.0). This option is supported for backward compatibility with
-other SSL engines; instead it is recommended to use Windows' store of root
-certificates (the default for Schannel).
diff --git a/docs/cmdline-opts/cacert.md b/docs/cmdline-opts/cacert.md
new file mode 100644
index 000000000..7b1b2174b
--- /dev/null
+++ b/docs/cmdline-opts/cacert.md
@@ -0,0 +1,42 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: cacert
+Arg: <file>
+Help: CA certificate to verify peer against
+Protocols: TLS
+Category: tls
+Added: 7.5
+Multi: single
+See-also:
+ - capath
+ - insecure
+Example:
+ - --cacert CA-file.txt $URL
+---
+
+# `--cacert`
+
+Tells curl to use the specified certificate file to verify the peer. The file
+may contain multiple CA certificates. The certificate(s) must be in PEM
+format. Normally curl is built to use a default file for this, so this option
+is typically used to alter that default file.
+
+curl recognizes the environment variable named 'CURL_CA_BUNDLE' if it is set
+and the TLS backend is not Schannel, and uses the given path as a path to a CA
+cert bundle. This option overrides that variable.
+
+The windows version of curl automatically looks for a CA certs file named
+'curl-ca-bundle.crt', either in the same directory as curl.exe, or in the
+Current Working Directory, or in any folder along your PATH.
+
+(iOS and macOS only) If curl is built against Secure Transport, then this
+option is supported for backward compatibility with other SSL engines, but it
+should not be set. If the option is not set, then curl uses the certificates
+in the system and user Keychain to verify the peer, which is the preferred
+method of verifying the peer's certificate chain.
+
+(Schannel only) This option is supported for Schannel in Windows 7 or later
+(added in 7.60.0). This option is supported for backward compatibility with
+other SSL engines; instead it is recommended to use Windows' store of root
+certificates (the default for Schannel).
diff --git a/docs/cmdline-opts/capath.d b/docs/cmdline-opts/capath.d
deleted file mode 100644
index 75e9f2e40..000000000
--- a/docs/cmdline-opts/capath.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: capath
-Arg: <dir>
-Help: CA directory to verify peer against
-Protocols: TLS
-Category: tls
-See-also: cacert insecure
-Example: --capath /local/directory $URL
-Added: 7.9.8
-Multi: single
----
-Tells curl to use the specified certificate directory to verify the
-peer. Multiple paths can be provided by separating them with ":" (e.g.
-"path1:path2:path3"). The certificates must be in PEM format, and if curl is
-built against OpenSSL, the directory must have been processed using the
-c_rehash utility supplied with OpenSSL. Using --capath can allow
-OpenSSL-powered curl to make SSL-connections much more efficiently than using
---cacert if the --cacert file contains many CA certificates.
-
-If this option is set, the default capath value is ignored.
diff --git a/docs/cmdline-opts/capath.md b/docs/cmdline-opts/capath.md
new file mode 100644
index 000000000..ecd28df24
--- /dev/null
+++ b/docs/cmdline-opts/capath.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: capath
+Arg: <dir>
+Help: CA directory to verify peer against
+Protocols: TLS
+Category: tls
+Added: 7.9.8
+Multi: single
+See-also:
+ - cacert
+ - insecure
+Example:
+ - --capath /local/directory $URL
+---
+
+# `--capath`
+
+Tells curl to use the specified certificate directory to verify the
+peer. Multiple paths can be provided by separating them with ":" (e.g.
+"path1:path2:path3"). The certificates must be in PEM format, and if curl is
+built against OpenSSL, the directory must have been processed using the
+c_rehash utility supplied with OpenSSL. Using --capath can allow
+OpenSSL-powered curl to make SSL-connections much more efficiently than using
+--cacert if the --cacert file contains many CA certificates.
+
+If this option is set, the default capath value is ignored.
diff --git a/docs/cmdline-opts/cert-status.d b/docs/cmdline-opts/cert-status.d
deleted file mode 100644
index e2d1d7aa2..000000000
--- a/docs/cmdline-opts/cert-status.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: cert-status
-Protocols: TLS
-Added: 7.41.0
-Help: Verify the status of the server cert via OCSP-staple
-Category: tls
-See-also: pinnedpubkey
-Example: --cert-status $URL
-Multi: boolean
----
-Tells curl to verify the status of the server certificate by using the
-Certificate Status Request (aka. OCSP stapling) TLS extension.
-
-If this option is enabled and the server sends an invalid (e.g. expired)
-response, if the response suggests that the server certificate has been
-revoked, or no response at all is received, the verification fails.
-
-This is currently only implemented in the OpenSSL and GnuTLS backends.
diff --git a/docs/cmdline-opts/cert-status.md b/docs/cmdline-opts/cert-status.md
new file mode 100644
index 000000000..bfbd3af83
--- /dev/null
+++ b/docs/cmdline-opts/cert-status.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: cert-status
+Protocols: TLS
+Added: 7.41.0
+Help: Verify the status of the server cert via OCSP-staple
+Category: tls
+Multi: boolean
+See-also:
+ - pinnedpubkey
+Example:
+ - --cert-status $URL
+---
+
+# `--cert-status`
+
+Tells curl to verify the status of the server certificate by using the
+Certificate Status Request (aka. OCSP stapling) TLS extension.
+
+If this option is enabled and the server sends an invalid (e.g. expired)
+response, if the response suggests that the server certificate has been
+revoked, or no response at all is received, the verification fails.
+
+This is currently only implemented in the OpenSSL and GnuTLS backends.
diff --git a/docs/cmdline-opts/cert-type.d b/docs/cmdline-opts/cert-type.d
deleted file mode 100644
index cf9f17b7d..000000000
--- a/docs/cmdline-opts/cert-type.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: cert-type
-Protocols: TLS
-Arg: <type>
-Help: Certificate type (DER/PEM/ENG/P12)
-See-also: cert key key-type
-Category: tls
-Example: --cert-type PEM --cert file $URL
-Added: 7.9.3
-Multi: single
----
-Tells curl what type the provided client certificate is using. PEM, DER, ENG
-and P12 are recognized types.
-
-The default type depends on the TLS backend and is usually PEM, however for
-Secure Transport and Schannel it is P12. If --cert is a pkcs11: URI then ENG is
-the default type.
diff --git a/docs/cmdline-opts/cert-type.md b/docs/cmdline-opts/cert-type.md
new file mode 100644
index 000000000..a0030a59d
--- /dev/null
+++ b/docs/cmdline-opts/cert-type.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: cert-type
+Protocols: TLS
+Arg: <type>
+Help: Certificate type (DER/PEM/ENG/P12)
+Category: tls
+Added: 7.9.3
+Multi: single
+See-also:
+ - cert
+ - key
+ - key-type
+Example:
+ - --cert-type PEM --cert file $URL
+---
+
+# `--cert-type`
+
+Tells curl what type the provided client certificate is using. PEM, DER, ENG
+and P12 are recognized types.
+
+The default type depends on the TLS backend and is usually PEM, however for
+Secure Transport and Schannel it is P12. If --cert is a pkcs11: URI then ENG is
+the default type.
diff --git a/docs/cmdline-opts/cert.d b/docs/cmdline-opts/cert.d
deleted file mode 100644
index 56d0df7fd..000000000
--- a/docs/cmdline-opts/cert.d
+++ /dev/null
@@ -1,49 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: E
-Long: cert
-Arg: <certificate[:password]>
-Help: Client certificate file and password
-Protocols: TLS
-See-also: cert-type key key-type
-Category: tls
-Example: --cert certfile --key keyfile $URL
-Added: 5.0
-Multi: single
----
-Tells curl to use the specified client certificate file when getting a file
-with HTTPS, FTPS or another SSL-based protocol. The certificate must be in
-PKCS#12 format if using Secure Transport, or PEM format if using any other
-engine. If the optional password is not specified, it is queried for on
-the terminal. Note that this option assumes a certificate file that is the
-private key and the client certificate concatenated. See --cert and --key to
-specify them independently.
-
-In the <certificate> portion of the argument, you must escape the character ":"
-as "\\:" so that it is not recognized as the password delimiter. Similarly, you
-must escape the character "\\" as "\\\\" so that it is not recognized as an
-escape character.
-
-If curl is built against OpenSSL library, and the engine pkcs11 is available,
-then a PKCS#11 URI (RFC 7512) can be used to specify a certificate located in
-a PKCS#11 device. A string beginning with "pkcs11:" is interpreted as a
-PKCS#11 URI. If a PKCS#11 URI is provided, then the --engine option is set as
-"pkcs11" if none was provided and the --cert-type option is set as "ENG" if
-none was provided.
-
-(iOS and macOS only) If curl is built against Secure Transport, then the
-certificate string can either be the name of a certificate/private key in the
-system or user keychain, or the path to a PKCS#12-encoded certificate and
-private key. 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,
-*"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* and
-*LocalMachineEnterprise*.
diff --git a/docs/cmdline-opts/cert.md b/docs/cmdline-opts/cert.md
new file mode 100644
index 000000000..6df5d0ebf
--- /dev/null
+++ b/docs/cmdline-opts/cert.md
@@ -0,0 +1,56 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: E
+Long: cert
+Arg: <certificate[:password]>
+Help: Client certificate file and password
+Protocols: TLS
+Category: tls
+Added: 5.0
+Multi: single
+See-also:
+ - cert-type
+ - key
+ - key-type
+Example:
+ - --cert certfile --key keyfile $URL
+---
+
+# `--cert`
+
+Tells curl to use the specified client certificate file when getting a file
+with HTTPS, FTPS or another SSL-based protocol. The certificate must be in
+PKCS#12 format if using Secure Transport, or PEM format if using any other
+engine. If the optional password is not specified, it is queried for on
+the terminal. Note that this option assumes a certificate file that is the
+private key and the client certificate concatenated. See --cert and --key to
+specify them independently.
+
+In the <certificate> portion of the argument, you must escape the character
+":" as "\:" so that it is not recognized as the password delimiter. Similarly,
+you must escape the double quote character as \" so that it is not recognized
+as an escape character.
+
+If curl is built against OpenSSL library, and the engine pkcs11 is available,
+then a PKCS#11 URI (RFC 7512) can be used to specify a certificate located in
+a PKCS#11 device. A string beginning with "pkcs11:" is interpreted as a
+PKCS#11 URI. If a PKCS#11 URI is provided, then the --engine option is set as
+"pkcs11" if none was provided and the --cert-type option is set as "ENG" if
+none was provided.
+
+(iOS and macOS only) If curl is built against Secure Transport, then the
+certificate string can either be the name of a certificate/private key in the
+system or user keychain, or the path to a PKCS#12-encoded certificate and
+private key. 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,
+*"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* and *LocalMachineEnterprise*.
diff --git a/docs/cmdline-opts/ciphers.d b/docs/cmdline-opts/ciphers.d
deleted file mode 100644
index a30902bdb..000000000
--- a/docs/cmdline-opts/ciphers.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ciphers
-Arg: <list of ciphers>
-Help: SSL ciphers to use
-Protocols: TLS
-Category: tls
-See-also: tlsv1.3 tls13-ciphers proxy-ciphers
-Example: --ciphers ECDHE-ECDSA-AES256-CCM8 $URL
-Added: 7.9
-Multi: single
----
-Specifies which ciphers to use in the connection. The list of ciphers must
-specify valid ciphers. Read up on SSL cipher list details on this URL:
-
-https://curl.se/docs/ssl-ciphers.html
diff --git a/docs/cmdline-opts/ciphers.md b/docs/cmdline-opts/ciphers.md
new file mode 100644
index 000000000..9d7e0c6fe
--- /dev/null
+++ b/docs/cmdline-opts/ciphers.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ciphers
+Arg: <list of ciphers>
+Help: SSL ciphers to use
+Protocols: TLS
+Category: tls
+Added: 7.9
+Multi: single
+See-also:
+ - tlsv1.3
+ - tls13-ciphers
+ - proxy-ciphers
+Example:
+ - --ciphers ECDHE-ECDSA-AES256-CCM8 $URL
+---
+
+# `--ciphers`
+
+Specifies which ciphers to use in the connection. The list of ciphers must
+specify valid ciphers. Read up on SSL cipher list details on this URL:
+
+https://curl.se/docs/ssl-ciphers.html
diff --git a/docs/cmdline-opts/compressed-ssh.d b/docs/cmdline-opts/compressed-ssh.d
deleted file mode 100644
index 897395677..000000000
--- a/docs/cmdline-opts/compressed-ssh.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: compressed-ssh
-Help: Enable SSH compression
-Protocols: SCP SFTP
-Added: 7.56.0
-Category: scp ssh
-See-also: compressed
-Example: --compressed-ssh sftp://example.com/
-Multi: boolean
----
-Enables built-in SSH compression.
-This is a request, not an order; the server may or may not do it.
diff --git a/docs/cmdline-opts/compressed-ssh.md b/docs/cmdline-opts/compressed-ssh.md
new file mode 100644
index 000000000..c52e5a7a3
--- /dev/null
+++ b/docs/cmdline-opts/compressed-ssh.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: compressed-ssh
+Help: Enable SSH compression
+Protocols: SCP SFTP
+Added: 7.56.0
+Category: scp ssh
+Multi: boolean
+See-also:
+ - compressed
+Example:
+ - --compressed-ssh sftp://example.com/
+---
+
+# `--compressed-ssh`
+
+Enables built-in SSH compression.
+This is a request, not an order; the server may or may not do it.
diff --git a/docs/cmdline-opts/compressed.d b/docs/cmdline-opts/compressed.d
deleted file mode 100644
index bb1d3baa7..000000000
--- a/docs/cmdline-opts/compressed.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: compressed
-Help: Request compressed response
-Protocols: HTTP
-Category: http
-Example: --compressed $URL
-See-also: compressed-ssh
-Added: 7.10
-Multi: boolean
----
-Request a compressed response using one of the algorithms curl supports, and
-automatically decompress the content.
-
-Response headers are not modified when saved, so if they are "interpreted"
-separately again at a later point they might appear to be saying that the
-content is (still) compressed; while in fact it has already been decompressed.
-
-If this option is used and the server sends an unsupported encoding, curl
-reports an error. This is a request, not an order; the server may or may not
-deliver data compressed.
diff --git a/docs/cmdline-opts/compressed.md b/docs/cmdline-opts/compressed.md
new file mode 100644
index 000000000..35bbab813
--- /dev/null
+++ b/docs/cmdline-opts/compressed.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: compressed
+Help: Request compressed response
+Protocols: HTTP
+Category: http
+Added: 7.10
+Multi: boolean
+See-also:
+ - compressed-ssh
+Example:
+ - --compressed $URL
+---
+
+# `--compressed`
+
+Request a compressed response using one of the algorithms curl supports, and
+automatically decompress the content.
+
+Response headers are not modified when saved, so if they are "interpreted"
+separately again at a later point they might appear to be saying that the
+content is (still) compressed; while in fact it has already been decompressed.
+
+If this option is used and the server sends an unsupported encoding, curl
+reports an error. This is a request, not an order; the server may or may not
+deliver data compressed.
diff --git a/docs/cmdline-opts/config.d b/docs/cmdline-opts/config.d
deleted file mode 100644
index c22a827f6..000000000
--- a/docs/cmdline-opts/config.d
+++ /dev/null
@@ -1,77 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: config
-Arg: <file>
-Help: Read config from a file
-Short: K
-Category: curl
-Example: --config file.txt $URL
-Added: 4.10
-See-also: disable
-Multi: append
----
-Specify a text file to read curl arguments from. The command line arguments
-found in the text file are used as if they were provided on the command
-line.
-
-Options and their parameters must be specified on the same line in the file,
-separated by whitespace, colon, or the equals sign. Long option names can
-optionally be given in the config file without the initial double dashes and
-if so, the colon or equals characters can be used as separators. If the option
-is specified with one or two dashes, there can be no colon or equals character
-between the option and its parameter.
-
-If the parameter contains whitespace or starts with a colon (:) or equals sign
-(=), it must be specified enclosed within double quotes (\&"). Within double
-quotes the following escape sequences are available: \\\\, \\", \\t, \\n, \\r
-and \\v. A backslash preceding any other letter is ignored.
-
-If the first non-blank column of a config line is a '#' character, that line
-is treated as a comment.
-
-Only write one option per physical line in the config file. A single line is
-required to be no more than 10 megabytes (since 8.2.0).
-
-Specify the filename to --config as '-' to make curl read the file from stdin.
-
-Note that to be able to specify a URL in the config file, you need to specify
-it using the --url option, and not by simply writing the URL on its own
-line. So, it could look similar to this:
-
-url = "https://curl.se/docs/"
-
- # --- Example file ---
- # this is a comment
- url = "example.com"
- output = "curlhere.html"
- user-agent = "superagent/1.0"
-
- # and fetch another URL too
- url = "example.com/docs/manpage.html"
- -O
- referer = "http://nowhereatall.example.com/"
- # --- End of example file ---
-
-When curl is invoked, it (unless --disable is used) checks for a default
-config file and uses it if found, even when --config is used. The default
-config file is checked for in the following places in this order:
-
-1) **"$CURL_HOME/.curlrc"**
-
-2) **"$XDG_CONFIG_HOME/curlrc"** (Added in 7.73.0)
-
-3) **"$HOME/.curlrc"**
-
-4) Windows: **"%USERPROFILE%\\.curlrc"**
-
-5) Windows: **"%APPDATA%\\.curlrc"**
-
-6) Windows: **"%USERPROFILE%\\Application Data\\.curlrc"**
-
-7) Non-Windows: use getpwuid to find the home directory
-
-8) On Windows, if it finds no *.curlrc* file in the sequence described above, it
-checks for one in the same dir the curl executable is placed.
-
-On Windows two filenames are checked per location: *.curlrc* and *_curlrc*,
-preferring the former. Older versions on Windows checked for *_curlrc* only.
diff --git a/docs/cmdline-opts/config.md b/docs/cmdline-opts/config.md
new file mode 100644
index 000000000..2f393e27e
--- /dev/null
+++ b/docs/cmdline-opts/config.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: config
+Arg: <file>
+Help: Read config from a file
+Short: K
+Category: curl
+Added: 4.10
+Multi: append
+See-also:
+ - disable
+Example:
+ - --config file.txt $URL
+---
+
+# `--config`
+
+Specify a text file to read curl arguments from. The command line arguments
+found in the text file are used as if they were provided on the command
+line.
+
+Options and their parameters must be specified on the same line in the file,
+separated by whitespace, colon, or the equals sign. Long option names can
+optionally be given in the config file without the initial double dashes and
+if so, the colon or equals characters can be used as separators. If the option
+is specified with one or two dashes, there can be no colon or equals character
+between the option and its parameter.
+
+If the parameter contains whitespace or starts with a colon (:) or equals sign
+(=), it must be specified enclosed within double quotes ("). Within double
+quotes the following escape sequences are available: \\, \", \t, \n, \r and
+\v. A backslash preceding any other letter is ignored.
+
+If the first non-blank column of a config line is a '#' character, that line
+is treated as a comment.
+
+Only write one option per physical line in the config file. A single line is
+required to be no more than 10 megabytes (since 8.2.0).
+
+Specify the filename to --config as '-' to make curl read the file from stdin.
+
+Note that to be able to specify a URL in the config file, you need to specify
+it using the --url option, and not by simply writing the URL on its own
+line. So, it could look similar to this:
+
+ url = "https://curl.se/docs/"
+
+ # --- Example file ---
+ # this is a comment
+ url = "example.com"
+ output = "curlhere.html"
+ user-agent = "superagent/1.0"
+
+ # and fetch another URL too
+ url = "example.com/docs/manpage.html"
+ -O
+ referer = "http://nowhereatall.example.com/"
+ # --- End of example file ---
+
+When curl is invoked, it (unless --disable is used) checks for a default
+config file and uses it if found, even when --config is used. The default
+config file is checked for in the following places in this order:
+
+1) **"$CURL_HOME/.curlrc"**
+
+2) **"$XDG_CONFIG_HOME/curlrc"** (Added in 7.73.0)
+
+3) **"$HOME/.curlrc"**
+
+4) Windows: **"%USERPROFILE%\.curlrc"**
+
+5) Windows: **"%APPDATA%\.curlrc"**
+
+6) Windows: **"%USERPROFILE%\Application Data\.curlrc"**
+
+7) Non-Windows: use getpwuid to find the home directory
+
+8) On Windows, if it finds no *.curlrc* file in the sequence described above, it
+checks for one in the same dir the curl executable is placed.
+
+On Windows two filenames are checked per location: *.curlrc* and *_curlrc*,
+preferring the former. Older versions on Windows checked for *_curlrc* only.
diff --git a/docs/cmdline-opts/connect-timeout.d b/docs/cmdline-opts/connect-timeout.d
deleted file mode 100644
index b3d19b3c3..000000000
--- a/docs/cmdline-opts/connect-timeout.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: connect-timeout
-Arg: <fractional seconds>
-Help: Maximum time allowed for connection
-See-also: max-time
-Category: connection
-Example: --connect-timeout 20 $URL
-Example: --connect-timeout 3.14 $URL
-Added: 7.7
-Multi: single
----
-Maximum time in seconds that you allow curl's connection to take. This only
-limits the connection phase, so if curl connects within the given period it
-continues - if not it exits.
-
-This option accepts decimal values (added in 7.32.0). The decimal value needs
-to be provided using a dot (.) as decimal separator - not the local version
-even if it might be using another separator.
-
-The connection phase is considered complete when the DNS lookup and requested
-TCP, TLS or QUIC handshakes are done.
diff --git a/docs/cmdline-opts/connect-timeout.md b/docs/cmdline-opts/connect-timeout.md
new file mode 100644
index 000000000..f7281b09a
--- /dev/null
+++ b/docs/cmdline-opts/connect-timeout.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: connect-timeout
+Arg: <fractional seconds>
+Help: Maximum time allowed for connection
+Category: connection
+Added: 7.7
+Multi: single
+See-also:
+ - max-time
+Example:
+ - --connect-timeout 20 $URL
+ - --connect-timeout 3.14 $URL
+---
+
+# `--connect-timeout`
+
+Maximum time in seconds that you allow curl's connection to take. This only
+limits the connection phase, so if curl connects within the given period it
+continues - if not it exits.
+
+This option accepts decimal values (added in 7.32.0). The decimal value needs
+to be provided using a dot (.) as decimal separator - not the local version
+even if it might be using another separator.
+
+The connection phase is considered complete when the DNS lookup and requested
+TCP, TLS or QUIC handshakes are done.
diff --git a/docs/cmdline-opts/connect-to.d b/docs/cmdline-opts/connect-to.d
deleted file mode 100644
index 95fab9112..000000000
--- a/docs/cmdline-opts/connect-to.d
+++ /dev/null
@@ -1,24 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: connect-to
-Arg: <HOST1:PORT1:HOST2:PORT2>
-Help: Connect to host
-Added: 7.49.0
-See-also: resolve header
-Category: connection
-Example: --connect-to example.com:443:example.net:8443 $URL
-Multi: append
----
-
-For a request to the given HOST1:PORT1 pair, connect to HOST2:PORT2 instead.
-This option is suitable to direct requests at a specific server, e.g. at a
-specific cluster node in a cluster of servers. This option is only used to
-establish the network connection. It does NOT affect the hostname/port that is
-used for TLS/SSL (e.g. SNI, certificate verification) or for the application
-protocols. "HOST1" and "PORT1" may be the empty string, meaning "any
-host/port". "HOST2" and "PORT2" may also be the empty string, meaning "use the
-request's original host/port".
-
-A "host" specified to this option is compared as a string, so it needs to
-match the name used in request URL. It can be either numerical such as
-"127.0.0.1" or the full host name such as "example.org".
diff --git a/docs/cmdline-opts/connect-to.md b/docs/cmdline-opts/connect-to.md
new file mode 100644
index 000000000..7cd0aa857
--- /dev/null
+++ b/docs/cmdline-opts/connect-to.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: connect-to
+Arg: <HOST1:PORT1:HOST2:PORT2>
+Help: Connect to host
+Added: 7.49.0
+Category: connection
+Multi: append
+See-also:
+ - resolve
+ - header
+Example:
+ - --connect-to example.com:443:example.net:8443 $URL
+---
+
+# `--connect-to`
+
+For a request to the given `HOST1:PORT1` pair, connect to `HOST2:PORT2`
+instead. This option is suitable to direct requests at a specific server,
+e.g. at a specific cluster node in a cluster of servers. This option is only
+used to establish the network connection. It does NOT affect the hostname/port
+that is used for TLS/SSL (e.g. SNI, certificate verification) or for the
+application protocols. `HOST1` and `PORT1` may be the empty string, meaning
+"any host/port". `HOST2` and `PORT2` may also be the empty string, meaning
+"use the request's original host/port".
+
+A hostname specified to this option is compared as a string, so it needs to
+match the name used in request URL. It can be either numerical such as
+`127.0.0.1` or the full host name such as `example.org`.
diff --git a/docs/cmdline-opts/continue-at.d b/docs/cmdline-opts/continue-at.d
deleted file mode 100644
index a4fc1a969..000000000
--- a/docs/cmdline-opts/continue-at.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: C
-Long: continue-at
-Arg: <offset>
-Help: Resumed transfer offset
-See-also: range
-Category: connection
-Example: -C - $URL
-Example: -C 400 $URL
-Added: 4.8
-Multi: single
----
-Continue/Resume a previous file transfer at the given offset. The given offset
-is the exact number of bytes that are skipped, counting from the beginning
-of the source file before it is transferred to the destination. If used with
-uploads, the FTP server command SIZE is not used by curl.
-
-Use "-C -" to tell curl to automatically find out where/how to resume the
-transfer. It then uses the given output/input files to figure that out.
diff --git a/docs/cmdline-opts/continue-at.md b/docs/cmdline-opts/continue-at.md
new file mode 100644
index 000000000..67a79fd70
--- /dev/null
+++ b/docs/cmdline-opts/continue-at.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: C
+Long: continue-at
+Arg: <offset>
+Help: Resumed transfer offset
+Category: connection
+Added: 4.8
+Multi: single
+See-also:
+ - range
+Example:
+ - -C - $URL
+ - -C 400 $URL
+---
+
+# `--continue-at`
+
+Continue/Resume a previous file transfer at the given offset. The given offset
+is the exact number of bytes that are skipped, counting from the beginning
+of the source file before it is transferred to the destination. If used with
+uploads, the FTP server command SIZE is not used by curl.
+
+Use "-C -" to tell curl to automatically find out where/how to resume the
+transfer. It then uses the given output/input files to figure that out.
diff --git a/docs/cmdline-opts/cookie-jar.d b/docs/cmdline-opts/cookie-jar.d
deleted file mode 100644
index 28738cac9..000000000
--- a/docs/cmdline-opts/cookie-jar.d
+++ /dev/null
@@ -1,31 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: c
-Long: cookie-jar
-Arg: <filename>
-Protocols: HTTP
-Help: Write cookies to <filename> after operation
-Category: http
-Example: -c store-here.txt $URL
-Example: -c store-here.txt -b read-these $URL
-Added: 7.9
-See-also: cookie
-Multi: single
----
-Specify to which file you want curl to write all cookies after a completed
-operation. Curl writes all cookies from its in-memory cookie storage to the
-given file at the end of operations. If no cookies are known, no data is
-written. The file is created using the Netscape cookie file format. If you set
-the file name to a single dash, "-", the cookies are written to stdout.
-
-The file specified with --cookie-jar is only used for output. No cookies are
-read from the file. To read cookies, use the --cookie option. Both options
-can specify the same file.
-
-This command line option activates the cookie engine that makes curl record
-and use cookies. The --cookie option also activates it.
-
-If the cookie jar cannot be created or written to, the whole curl operation
-does not fail or even report an error clearly. Using --verbose gets a warning
-displayed, but that is the only visible feedback you get about this possibly
-lethal situation.
diff --git a/docs/cmdline-opts/cookie-jar.md b/docs/cmdline-opts/cookie-jar.md
new file mode 100644
index 000000000..5453152e4
--- /dev/null
+++ b/docs/cmdline-opts/cookie-jar.md
@@ -0,0 +1,37 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: c
+Long: cookie-jar
+Arg: <filename>
+Protocols: HTTP
+Help: Write cookies to <filename> after operation
+Category: http
+Added: 7.9
+Multi: single
+See-also:
+ - cookie
+Example:
+ - -c store-here.txt $URL
+ - -c store-here.txt -b read-these $URL
+---
+
+# `--cookie-jar`
+
+Specify to which file you want curl to write all cookies after a completed
+operation. Curl writes all cookies from its in-memory cookie storage to the
+given file at the end of operations. If no cookies are known, no data is
+written. The file is created using the Netscape cookie file format. If you set
+the file name to a single dash, "-", the cookies are written to stdout.
+
+The file specified with --cookie-jar is only used for output. No cookies are
+read from the file. To read cookies, use the --cookie option. Both options
+can specify the same file.
+
+This command line option activates the cookie engine that makes curl record
+and use cookies. The --cookie option also activates it.
+
+If the cookie jar cannot be created or written to, the whole curl operation
+does not fail or even report an error clearly. Using --verbose gets a warning
+displayed, but that is the only visible feedback you get about this possibly
+lethal situation.
diff --git a/docs/cmdline-opts/cookie.d b/docs/cmdline-opts/cookie.d
deleted file mode 100644
index 0f858d661..000000000
--- a/docs/cmdline-opts/cookie.d
+++ /dev/null
@@ -1,42 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: b
-Long: cookie
-Arg: <data|filename>
-Protocols: HTTP
-Help: Send cookies from string/file
-Category: http
-Example: -b cookiefile $URL
-Example: -b cookiefile -c cookiefile $URL
-See-also: cookie-jar junk-session-cookies
-Added: 4.9
-Multi: append
----
-Pass the data to the HTTP server in the Cookie header. It is supposedly the
-data previously received from the server in a "Set-Cookie:" line. The data
-should be in the format "NAME1=VALUE1; NAME2=VALUE2". This makes curl use the
-cookie header with this content explicitly in all outgoing request(s). If
-multiple requests are done due to authentication, followed redirects or
-similar, they all get this cookie passed on.
-
-If no '=' symbol is used in the argument, it is instead treated as a filename
-to read previously stored cookie from. This option also activates the cookie
-engine which makes curl record incoming cookies, which may be handy if you are
-using this in combination with the --location option or do multiple URL
-transfers on the same invoke. If the file name is exactly a minus ("-"), curl
-instead reads the contents from stdin.
-
-The file format of the file to read cookies from should be plain HTTP headers
-(Set-Cookie style) or the Netscape/Mozilla cookie file format.
-
-The file specified with --cookie is only used as input. No cookies are written
-to the file. To store cookies, use the --cookie-jar option.
-
-If you use the Set-Cookie file format and do not specify a domain then the
-cookie is not sent since the domain never matches. To address this, set a
-domain in Set-Cookie line (doing that includes subdomains) or preferably: use
-the Netscape format.
-
-Users often want to both read cookies from a file and write updated cookies
-back to a file, so using both --cookie and --cookie-jar in the same command
-line is common.
diff --git a/docs/cmdline-opts/cookie.md b/docs/cmdline-opts/cookie.md
new file mode 100644
index 000000000..d0a6d3539
--- /dev/null
+++ b/docs/cmdline-opts/cookie.md
@@ -0,0 +1,58 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: b
+Long: cookie
+Arg: <data|filename>
+Protocols: HTTP
+Help: Send cookies from string/file
+Category: http
+Added: 4.9
+Multi: append
+See-also:
+ - cookie-jar
+ - junk-session-cookies
+Example:
+ - -b "" $URL
+ - -b cookiefile $URL
+ - -b cookiefile -c cookiefile $URL
+---
+
+# `--cookie`
+
+Pass the data to the HTTP server in the Cookie header. It is supposedly the
+data previously received from the server in a "Set-Cookie:" line. The data
+should be in the format "NAME1=VALUE1; NAME2=VALUE2". This makes curl use the
+cookie header with this content explicitly in all outgoing request(s). If
+multiple requests are done due to authentication, followed redirects or
+similar, they all get this cookie passed on.
+
+If no '=' symbol is used in the argument, it is instead treated as a filename
+to read previously stored cookie from. This option also activates the cookie
+engine which makes curl record incoming cookies, which may be handy if you are
+using this in combination with the --location option or do multiple URL
+transfers on the same invoke.
+
+If the file name is exactly a minus ("-"), curl instead reads the contents from
+stdin. If the file name is an empty string ("") and is the only cookie input,
+curl will activate the cookie engine without any cookies.
+
+The file format of the file to read cookies from should be plain HTTP headers
+(Set-Cookie style) or the Netscape/Mozilla cookie file format.
+
+The file specified with --cookie is only used as input. No cookies are written
+to the file. To store cookies, use the --cookie-jar option.
+
+If you use the Set-Cookie file format and do not specify a domain then the
+cookie is not sent since the domain never matches. To address this, set a
+domain in Set-Cookie line (doing that includes subdomains) or preferably: use
+the Netscape format.
+
+Users often want to both read cookies from a file and write updated cookies
+back to a file, so using both --cookie and --cookie-jar in the same command
+line is common.
+
+If curl is built with PSL (**Public Suffix List**) support, it detects and
+discards cookies that are specified for such suffix domains that should not be
+allowed to have cookies. If curl is *not* built with PSL support, it has no
+ability to stop super cookies.
diff --git a/docs/cmdline-opts/create-dirs.d b/docs/cmdline-opts/create-dirs.d
deleted file mode 100644
index 966b70384..000000000
--- a/docs/cmdline-opts/create-dirs.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: create-dirs
-Help: Create necessary local directory hierarchy
-Category: curl
-Example: --create-dirs --output local/dir/file $URL
-Added: 7.10.3
-See-also: ftp-create-dirs output-dir
-Multi: boolean
----
-When used in conjunction with the --output option, curl creates the necessary
-local directory hierarchy as needed. This option creates the directories
-mentioned with the --output option combined with the path possibly set with
---output-dir. If the combined output file name uses no directory, or if the
-directories it mentions already exist, no directories are created.
-
-Created directories are made with mode 0750 on unix style file systems.
-
-To create remote directories when using FTP or SFTP, try --ftp-create-dirs.
diff --git a/docs/cmdline-opts/create-dirs.md b/docs/cmdline-opts/create-dirs.md
new file mode 100644
index 000000000..de48807d4
--- /dev/null
+++ b/docs/cmdline-opts/create-dirs.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: create-dirs
+Help: Create necessary local directory hierarchy
+Category: curl
+Added: 7.10.3
+Multi: boolean
+See-also:
+ - ftp-create-dirs
+ - output-dir
+Example:
+ - --create-dirs --output local/dir/file $URL
+---
+
+# `--create-dirs`
+
+When used in conjunction with the --output option, curl creates the necessary
+local directory hierarchy as needed. This option creates the directories
+mentioned with the --output option combined with the path possibly set with
+--output-dir. If the combined output file name uses no directory, or if the
+directories it mentions already exist, no directories are created.
+
+Created directories are made with mode 0750 on unix style file systems.
+
+To create remote directories when using FTP or SFTP, try --ftp-create-dirs.
diff --git a/docs/cmdline-opts/create-file-mode.d b/docs/cmdline-opts/create-file-mode.d
deleted file mode 100644
index c0ebc08d4..000000000
--- a/docs/cmdline-opts/create-file-mode.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: create-file-mode
-Arg: <mode>
-Help: File mode for created files
-Protocols: SFTP SCP FILE
-Category: sftp scp file upload
-See-also: ftp-create-dirs
-Added: 7.75.0
-Example: --create-file-mode 0777 -T localfile sftp://example.com/new
-Multi: single
----
-When curl is used to create files remotely using one of the supported
-protocols, this option allows the user to set which 'mode' to set on the file
-at creation time, instead of the default 0644.
-
-This option takes an octal number as argument.
diff --git a/docs/cmdline-opts/create-file-mode.md b/docs/cmdline-opts/create-file-mode.md
new file mode 100644
index 000000000..c6467d15a
--- /dev/null
+++ b/docs/cmdline-opts/create-file-mode.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: create-file-mode
+Arg: <mode>
+Help: File mode for created files
+Protocols: SFTP SCP FILE
+Category: sftp scp file upload
+Added: 7.75.0
+Multi: single
+See-also:
+ - ftp-create-dirs
+Example:
+ - --create-file-mode 0777 -T localfile sftp://example.com/new
+---
+
+# `--create-file-mode`
+
+When curl is used to create files remotely using one of the supported
+protocols, this option allows the user to set which 'mode' to set on the file
+at creation time, instead of the default 0644.
+
+This option takes an octal number as argument.
diff --git a/docs/cmdline-opts/crlf.d b/docs/cmdline-opts/crlf.d
deleted file mode 100644
index ea7fb1526..000000000
--- a/docs/cmdline-opts/crlf.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: crlf
-Help: Convert LF to CRLF in upload
-Protocols: FTP SMTP
-Category: ftp smtp
-Example: --crlf -T file ftp://example.com/
-Added: 5.7
-See-also: use-ascii
-Multi: boolean
----
-Convert line feeds to carriage return plus line feeds in upload. Useful for
-**MVS (OS/390)**.
-
-(SMTP added in 7.40.0)
diff --git a/docs/cmdline-opts/crlf.md b/docs/cmdline-opts/crlf.md
new file mode 100644
index 000000000..81a14ef6f
--- /dev/null
+++ b/docs/cmdline-opts/crlf.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: crlf
+Help: Convert LF to CRLF in upload
+Protocols: FTP SMTP
+Category: ftp smtp
+Added: 5.7
+Multi: boolean
+See-also:
+ - use-ascii
+Example:
+ - --crlf -T file ftp://example.com/
+---
+
+# `--crlf`
+
+Convert line feeds to carriage return plus line feeds in upload. Useful for
+**MVS (OS/390)**.
+
+(SMTP added in 7.40.0)
diff --git a/docs/cmdline-opts/crlfile.d b/docs/cmdline-opts/crlfile.d
deleted file mode 100644
index da0d239ba..000000000
--- a/docs/cmdline-opts/crlfile.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: crlfile
-Arg: <file>
-Protocols: TLS
-Help: Use this CRL list
-Added: 7.19.7
-Category: tls
-Example: --crlfile rejects.txt $URL
-See-also: cacert capath
-Multi: single
----
-Provide a file using PEM format with a Certificate Revocation List that may
-specify peer certificates that are to be considered revoked.
diff --git a/docs/cmdline-opts/crlfile.md b/docs/cmdline-opts/crlfile.md
new file mode 100644
index 000000000..16bd7b35b
--- /dev/null
+++ b/docs/cmdline-opts/crlfile.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: crlfile
+Arg: <file>
+Protocols: TLS
+Help: Use this CRL list
+Added: 7.19.7
+Category: tls
+Multi: single
+See-also:
+ - cacert
+ - capath
+Example:
+ - --crlfile rejects.txt $URL
+---
+
+# `--crlfile`
+
+Provide a file using PEM format with a Certificate Revocation List that may
+specify peer certificates that are to be considered revoked.
diff --git a/docs/cmdline-opts/curves.d b/docs/cmdline-opts/curves.d
deleted file mode 100644
index 58d472d20..000000000
--- a/docs/cmdline-opts/curves.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: curves
-Arg: <algorithm list>
-Help: (EC) TLS key exchange algorithm(s) to request
-Protocols: TLS
-Added: 7.73.0
-Category: tls
-Example: --curves X25519 $URL
-See-also: ciphers
-Multi: single
----
-Tells curl to request specific curves to use during SSL session establishment
-according to RFC 8422, 5.1. Multiple algorithms can be provided by separating
-them with ":" (e.g. "X25519:P-521"). The parameter is available identically
-in the "openssl s_client/s_server" utilities.
-
---curves allows a OpenSSL powered curl to make SSL-connections with exactly
-the (EC) curve requested by the client, avoiding nontransparent client/server
-negotiations.
-
-If this option is set, the default curves list built into OpenSSL are ignored.
diff --git a/docs/cmdline-opts/curves.md b/docs/cmdline-opts/curves.md
new file mode 100644
index 000000000..99f1ad48a
--- /dev/null
+++ b/docs/cmdline-opts/curves.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: curves
+Arg: <algorithm list>
+Help: (EC) TLS key exchange algorithm(s) to request
+Protocols: TLS
+Added: 7.73.0
+Category: tls
+Multi: single
+See-also:
+ - ciphers
+Example:
+ - --curves X25519 $URL
+---
+
+# `--curves`
+
+Tells curl to request specific curves to use during SSL session establishment
+according to RFC 8422, 5.1. Multiple algorithms can be provided by separating
+them with `:` (e.g. `X25519:P-521`). The parameter is available identically in
+the OpenSSL `s_client` and `s_server` utilities.
+
+--curves allows a OpenSSL powered curl to make SSL-connections with exactly
+the (EC) curve requested by the client, avoiding nontransparent client/server
+negotiations.
+
+If this option is set, the default curves list built into OpenSSL are ignored.
diff --git a/docs/cmdline-opts/data-ascii.d b/docs/cmdline-opts/data-ascii.d
deleted file mode 100644
index 5c7840bbc..000000000
--- a/docs/cmdline-opts/data-ascii.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: data-ascii
-Arg: <data>
-Help: HTTP POST ASCII data
-Protocols: HTTP
-Category: http post upload
-Example: --data-ascii @file $URL
-Added: 7.2
-See-also: data-binary data-raw data-urlencode
-Multi: append
----
-This is just an alias for --data.
diff --git a/docs/cmdline-opts/data-ascii.md b/docs/cmdline-opts/data-ascii.md
new file mode 100644
index 000000000..124dee13c
--- /dev/null
+++ b/docs/cmdline-opts/data-ascii.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: data-ascii
+Arg: <data>
+Help: HTTP POST ASCII data
+Protocols: HTTP
+Category: http post upload
+Added: 7.2
+Multi: append
+See-also:
+ - data-binary
+ - data-raw
+ - data-urlencode
+Example:
+ - --data-ascii @file $URL
+---
+
+# `--data-ascii`
+
+This is just an alias for --data.
diff --git a/docs/cmdline-opts/data-binary.d b/docs/cmdline-opts/data-binary.d
deleted file mode 100644
index 2cedda97b..000000000
--- a/docs/cmdline-opts/data-binary.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: data-binary
-Arg: <data>
-Help: HTTP POST binary data
-Protocols: HTTP
-Category: http post upload
-Example: --data-binary @filename $URL
-Added: 7.2
-See-also: data-ascii
-Multi: append
----
-This posts data exactly as specified with no extra processing whatsoever.
-
-If you start the data with the letter @, the rest should be a filename. Data
-is posted in a similar manner as --data does, except that newlines and
-carriage returns are preserved and conversions are never done.
-
-Like --data the default content-type sent to the server is
-application/x-www-form-urlencoded. If you want the data to be treated as
-arbitrary binary data by the server then set the content-type to octet-stream:
--H "Content-Type: application/octet-stream".
-
-If this option is used several times, the ones following the first append
-data as described in --data.
diff --git a/docs/cmdline-opts/data-binary.md b/docs/cmdline-opts/data-binary.md
new file mode 100644
index 000000000..3d563fbdd
--- /dev/null
+++ b/docs/cmdline-opts/data-binary.md
@@ -0,0 +1,31 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: data-binary
+Arg: <data>
+Help: HTTP POST binary data
+Protocols: HTTP
+Category: http post upload
+Added: 7.2
+Multi: append
+See-also:
+ - data-ascii
+Example:
+ - --data-binary @filename $URL
+---
+
+# `--data-binary`
+
+This posts data exactly as specified with no extra processing whatsoever.
+
+If you start the data with the letter @, the rest should be a filename. Data
+is posted in a similar manner as --data does, except that newlines and
+carriage returns are preserved and conversions are never done.
+
+Like --data the default content-type sent to the server is
+application/x-www-form-urlencoded. If you want the data to be treated as
+arbitrary binary data by the server then set the content-type to octet-stream:
+-H "Content-Type: application/octet-stream".
+
+If this option is used several times, the ones following the first append
+data as described in --data.
diff --git a/docs/cmdline-opts/data-raw.d b/docs/cmdline-opts/data-raw.d
deleted file mode 100644
index e6a5a5b2b..000000000
--- a/docs/cmdline-opts/data-raw.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: data-raw
-Arg: <data>
-Protocols: HTTP
-Help: HTTP POST data, '@' allowed
-Added: 7.43.0
-See-also: data
-Category: http post upload
-Example: --data-raw "hello" $URL
-Example: --data-raw "@at@at@" $URL
-Multi: append
----
-This posts data similarly to --data but without the special
-interpretation of the @ character.
diff --git a/docs/cmdline-opts/data-raw.md b/docs/cmdline-opts/data-raw.md
new file mode 100644
index 000000000..2cb46938b
--- /dev/null
+++ b/docs/cmdline-opts/data-raw.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: data-raw
+Arg: <data>
+Protocols: HTTP
+Help: HTTP POST data, '@' allowed
+Added: 7.43.0
+Category: http post upload
+Multi: append
+See-also:
+ - data
+Example:
+ - --data-raw "hello" $URL
+ - --data-raw "@at@at@" $URL
+---
+
+# `--data-raw`
+
+This posts data similarly to --data but without the special
+interpretation of the @ character.
diff --git a/docs/cmdline-opts/data-urlencode.d b/docs/cmdline-opts/data-urlencode.d
deleted file mode 100644
index 3c436b26b..000000000
--- a/docs/cmdline-opts/data-urlencode.d
+++ /dev/null
@@ -1,42 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: data-urlencode
-Arg: <data>
-Help: HTTP POST data URL encoded
-Protocols: HTTP
-See-also: data data-raw
-Added: 7.18.0
-Category: http post upload
-Example: --data-urlencode name=val $URL
-Example: --data-urlencode =encodethis $URL
-Example: --data-urlencode name@file $URL
-Example: --data-urlencode @fileonly $URL
-Multi: append
----
-This posts data, similar to the other --data options with the exception
-that this performs URL-encoding.
-
-To be CGI-compliant, the <data> part should begin with a *name* followed
-by a separator and a content specification. The <data> part can be passed to
-curl using one of the following syntaxes:
-.RS
-.IP "content"
-This makes curl URL-encode the content and pass that on. Just be careful
-so that the content does not contain any = or @ symbols, as that makes
-the syntax match one of the other cases below!
-.IP "=content"
-This makes curl URL-encode the content and pass that on. The preceding =
-symbol is not included in the data.
-.IP "name=content"
-This makes curl URL-encode the content part and pass that on. Note that
-the name part is expected to be URL-encoded already.
-.IP "@filename"
-This makes curl load data from the given file (including any newlines),
-URL-encode that data and pass it on in the POST.
-.IP "name@filename"
-This makes curl load data from the given file (including any newlines),
-URL-encode that data and pass it on in the POST. The name part gets an equal
-sign appended, resulting in *name=urlencoded-file-content*. Note that the
-name is expected to be URL-encoded already.
-.RE
-.IP
diff --git a/docs/cmdline-opts/data-urlencode.md b/docs/cmdline-opts/data-urlencode.md
new file mode 100644
index 000000000..4d3f29813
--- /dev/null
+++ b/docs/cmdline-opts/data-urlencode.md
@@ -0,0 +1,51 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: data-urlencode
+Arg: <data>
+Help: HTTP POST data URL encoded
+Protocols: HTTP
+Added: 7.18.0
+Category: http post upload
+Multi: append
+See-also:
+ - data
+ - data-raw
+Example:
+ - --data-urlencode name=val $URL
+ - --data-urlencode =encodethis $URL
+ - --data-urlencode name@file $URL
+ - --data-urlencode @fileonly $URL
+---
+
+# `--data-urlencode`
+
+This posts data, similar to the other --data options with the exception
+that this performs URL-encoding.
+
+To be CGI-compliant, the <data> part should begin with a *name* followed
+by a separator and a content specification. The <data> part can be passed to
+curl using one of the following syntaxes:
+
+## content
+This makes curl URL-encode the content and pass that on. Just be careful
+so that the content does not contain any = or @ symbols, as that makes
+the syntax match one of the other cases below!
+
+## =content
+This makes curl URL-encode the content and pass that on. The preceding =
+symbol is not included in the data.
+
+## name=content
+This makes curl URL-encode the content part and pass that on. Note that
+the name part is expected to be URL-encoded already.
+
+## @filename
+This makes curl load data from the given file (including any newlines),
+URL-encode that data and pass it on in the POST.
+
+## name@filename
+This makes curl load data from the given file (including any newlines),
+URL-encode that data and pass it on in the POST. The name part gets an equal
+sign appended, resulting in *name=urlencoded-file-content*. Note that the
+name is expected to be URL-encoded already.
diff --git a/docs/cmdline-opts/data.d b/docs/cmdline-opts/data.d
deleted file mode 100644
index f1d67b950..000000000
--- a/docs/cmdline-opts/data.d
+++ /dev/null
@@ -1,41 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: data
-Short: d
-Arg: <data>
-Help: HTTP POST data
-Protocols: HTTP MQTT
-See-also: data-binary data-urlencode data-raw
-Mutexed: form head upload-file
-Category: important http post upload
-Example: -d "name=curl" $URL
-Example: -d "name=curl" -d "tool=cmdline" $URL
-Example: -d @filename $URL
-Added: 4.0
-Multi: append
----
-Sends the specified data in a POST request to the HTTP server, in the same way
-that a browser does when a user has filled in an HTML form and presses the
-submit button. This makes curl pass the data to the server using the
-content-type application/x-www-form-urlencoded. Compare to --form.
-
---data-raw is almost the same but does not have a special interpretation of
-the @ character. To post data purely binary, you should instead use the
---data-binary option. To URL-encode the value of a form field you may use
---data-urlencode.
-
-If any of these options is used more than once on the same command line, the
-data pieces specified are merged with a separating &-symbol. Thus, using
-'-d name=daniel -d skill=lousy' would generate a post chunk that looks like
-'name=daniel&skill=lousy'.
-
-If you start the data with the letter @, the rest should be a file name to
-read the data from, or - if you want curl to read the data from stdin. Posting
-data from a file named 'foobar' would thus be done with --data @foobar. When
---data is told to read from a file like that, carriage returns and newlines
-are stripped out. If you do not want the @ character to have a special
-interpretation use --data-raw instead.
-
-The data for this option is passed on to the server exactly as provided on the
-command line. curl does not convert, change or improve it. It is up to the
-user to provide the data in the correct form.
diff --git a/docs/cmdline-opts/data.md b/docs/cmdline-opts/data.md
new file mode 100644
index 000000000..fb3b84872
--- /dev/null
+++ b/docs/cmdline-opts/data.md
@@ -0,0 +1,49 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: data
+Short: d
+Arg: <data>
+Help: HTTP POST data
+Protocols: HTTP MQTT
+Mutexed: form head upload-file
+Category: important http post upload
+Added: 4.0
+Multi: append
+See-also:
+ - data-binary
+ - data-urlencode
+ - data-raw
+Example:
+ - -d "name=curl" $URL
+ - -d "name=curl" -d "tool=cmdline" $URL
+ - -d @filename $URL
+---
+
+# `--data`
+
+Sends the specified data in a POST request to the HTTP server, in the same way
+that a browser does when a user has filled in an HTML form and presses the
+submit button. This makes curl pass the data to the server using the
+content-type application/x-www-form-urlencoded. Compare to --form.
+
+--data-raw is almost the same but does not have a special interpretation of
+the @ character. To post data purely binary, you should instead use the
+--data-binary option. To URL-encode the value of a form field you may use
+--data-urlencode.
+
+If any of these options is used more than once on the same command line, the
+data pieces specified are merged with a separating &-symbol. Thus, using
+'-d name=daniel -d skill=lousy' would generate a post chunk that looks like
+'name=daniel&skill=lousy'.
+
+If you start the data with the letter @, the rest should be a file name to
+read the data from, or - if you want curl to read the data from stdin. Posting
+data from a file named 'foobar' would thus be done with --data @foobar. When
+--data is told to read from a file like that, carriage returns and newlines
+are stripped out. If you do not want the @ character to have a special
+interpretation use --data-raw instead.
+
+The data for this option is passed on to the server exactly as provided on the
+command line. curl does not convert, change or improve it. It is up to the
+user to provide the data in the correct form.
diff --git a/docs/cmdline-opts/delegation.d b/docs/cmdline-opts/delegation.d
deleted file mode 100644
index 794184934..000000000
--- a/docs/cmdline-opts/delegation.d
+++ /dev/null
@@ -1,24 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: delegation
-Arg: <LEVEL>
-Help: GSS-API delegation permission
-Protocols: GSS/kerberos
-Category: auth
-Example: --delegation "none" $URL
-Added: 7.22.0
-See-also: insecure ssl
-Multi: single
----
-Set LEVEL to tell the server what it is allowed to delegate when it
-comes to user credentials.
-.RS
-.IP "none"
-Do not allow any delegation.
-.IP "policy"
-Delegates if and only if the OK-AS-DELEGATE flag is set in the Kerberos
-service ticket, which is a matter of realm policy.
-.IP "always"
-Unconditionally allow the server to delegate.
-.RE
-.IP
diff --git a/docs/cmdline-opts/delegation.md b/docs/cmdline-opts/delegation.md
new file mode 100644
index 000000000..3d6cff899
--- /dev/null
+++ b/docs/cmdline-opts/delegation.md
@@ -0,0 +1,31 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: delegation
+Arg: <LEVEL>
+Help: GSS-API delegation permission
+Protocols: GSS/kerberos
+Category: auth
+Added: 7.22.0
+Multi: single
+See-also:
+ - insecure
+ - ssl
+Example:
+ - --delegation "none" $URL
+---
+
+# `--delegation`
+
+Set LEVEL to tell the server what it is allowed to delegate when it
+comes to user credentials.
+
+## none
+Do not allow any delegation.
+
+## policy
+Delegates if and only if the OK-AS-DELEGATE flag is set in the Kerberos
+service ticket, which is a matter of realm policy.
+
+## always
+Unconditionally allow the server to delegate.
diff --git a/docs/cmdline-opts/digest.d b/docs/cmdline-opts/digest.d
deleted file mode 100644
index f2ee551c5..000000000
--- a/docs/cmdline-opts/digest.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: digest
-Help: Use HTTP Digest Authentication
-Protocols: HTTP
-Mutexed: basic ntlm negotiate
-See-also: user proxy-digest anyauth
-Category: proxy auth http
-Example: -u name:password --digest $URL
-Added: 7.10.6
-Multi: boolean
----
-Enables HTTP Digest authentication. This is an authentication scheme that
-prevents the password from being sent over the wire in clear text. Use this in
-combination with the normal --user option to set user name and password.
diff --git a/docs/cmdline-opts/digest.md b/docs/cmdline-opts/digest.md
new file mode 100644
index 000000000..f05c01fed
--- /dev/null
+++ b/docs/cmdline-opts/digest.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: digest
+Help: Use HTTP Digest Authentication
+Protocols: HTTP
+Mutexed: basic ntlm negotiate
+Category: proxy auth http
+Added: 7.10.6
+Multi: boolean
+See-also:
+ - user
+ - proxy-digest
+ - anyauth
+Example:
+ - -u name:password --digest $URL
+---
+
+# `--digest`
+
+Enables HTTP Digest authentication. This is an authentication scheme that
+prevents the password from being sent over the wire in clear text. Use this in
+combination with the normal --user option to set user name and password.
diff --git a/docs/cmdline-opts/disable-eprt.d b/docs/cmdline-opts/disable-eprt.d
deleted file mode 100644
index b6d382baf..000000000
--- a/docs/cmdline-opts/disable-eprt.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: disable-eprt
-Help: Inhibit using EPRT or LPRT
-Protocols: FTP
-Category: ftp
-Example: --disable-eprt ftp://example.com/
-Added: 7.10.5
-See-also: disable-epsv ftp-port
-Multi: boolean
----
-Tell curl to disable the use of the EPRT and LPRT commands when doing active
-FTP transfers. Curl normally first attempts to use EPRT before using PORT, but
-with this option, it uses PORT right away. EPRT is an extension to the
-original FTP protocol, and does not work on all servers, but enables more
-functionality in a better way than the traditional PORT command.
-
---eprt can be used to explicitly enable EPRT again and --no-eprt is an alias
-for --disable-eprt.
-
-If the server is accessed using IPv6, this option has no effect as EPRT is
-necessary then.
-
-Disabling EPRT only changes the active behavior. If you want to switch to
-passive mode you need to not use --ftp-port or force it with --ftp-pasv.
diff --git a/docs/cmdline-opts/disable-eprt.md b/docs/cmdline-opts/disable-eprt.md
new file mode 100644
index 000000000..80ae05691
--- /dev/null
+++ b/docs/cmdline-opts/disable-eprt.md
@@ -0,0 +1,32 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: disable-eprt
+Help: Inhibit using EPRT or LPRT
+Protocols: FTP
+Category: ftp
+Added: 7.10.5
+Multi: boolean
+See-also:
+ - disable-epsv
+ - ftp-port
+Example:
+ - --disable-eprt ftp://example.com/
+---
+
+# `--disable-eprt`
+
+Tell curl to disable the use of the EPRT and LPRT commands when doing active
+FTP transfers. Curl normally first attempts to use EPRT before using PORT, but
+with this option, it uses PORT right away. EPRT is an extension to the
+original FTP protocol, and does not work on all servers, but enables more
+functionality in a better way than the traditional PORT command.
+
+--eprt can be used to explicitly enable EPRT again and --no-eprt is an alias
+for --disable-eprt.
+
+If the server is accessed using IPv6, this option has no effect as EPRT is
+necessary then.
+
+Disabling EPRT only changes the active behavior. If you want to switch to
+passive mode you need to not use --ftp-port or force it with --ftp-pasv.
diff --git a/docs/cmdline-opts/disable-epsv.d b/docs/cmdline-opts/disable-epsv.d
deleted file mode 100644
index f02df763d..000000000
--- a/docs/cmdline-opts/disable-epsv.d
+++ /dev/null
@@ -1,23 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: disable-epsv
-Help: Inhibit using EPSV
-Protocols: FTP
-Category: ftp
-Example: --disable-epsv ftp://example.com/
-Added: 7.9.2
-See-also: disable-eprt ftp-port
-Multi: boolean
----
-Tell curl to disable the use of the EPSV command when doing passive FTP
-transfers. Curl normally first attempts to use EPSV before PASV, but with this
-option, it does not try EPSV.
-
---epsv can be used to explicitly enable EPSV again and --no-epsv is an alias
-for --disable-epsv.
-
-If the server is an IPv6 host, this option has no effect as EPSV is necessary
-then.
-
-Disabling EPSV only changes the passive behavior. If you want to switch to
-active mode you need to use --ftp-port.
diff --git a/docs/cmdline-opts/disable-epsv.md b/docs/cmdline-opts/disable-epsv.md
new file mode 100644
index 000000000..f4a8de8c0
--- /dev/null
+++ b/docs/cmdline-opts/disable-epsv.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: disable-epsv
+Help: Inhibit using EPSV
+Protocols: FTP
+Category: ftp
+Added: 7.9.2
+Multi: boolean
+See-also:
+ - disable-eprt
+ - ftp-port
+Example:
+ - --disable-epsv ftp://example.com/
+---
+
+# `--disable-epsv`
+
+Tell curl to disable the use of the EPSV command when doing passive FTP
+transfers. Curl normally first attempts to use EPSV before PASV, but with this
+option, it does not try EPSV.
+
+--epsv can be used to explicitly enable EPSV again and --no-epsv is an alias
+for --disable-epsv.
+
+If the server is an IPv6 host, this option has no effect as EPSV is necessary
+then.
+
+Disabling EPSV only changes the passive behavior. If you want to switch to
+active mode you need to use --ftp-port.
diff --git a/docs/cmdline-opts/disable.d b/docs/cmdline-opts/disable.d
deleted file mode 100644
index 979c03991..000000000
--- a/docs/cmdline-opts/disable.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: disable
-Short: q
-Help: Disable .curlrc
-Category: curl
-Example: -q $URL
-Added: 5.0
-See-also: config
-Multi: boolean
----
-If used as the **first** parameter on the command line, the *curlrc* config
-file is not read or used. See the --config for details on the default config
-file search path.
-
-Prior to 7.50.0 curl supported the short option name *q* but not the long
-option name *disable*.
diff --git a/docs/cmdline-opts/disable.md b/docs/cmdline-opts/disable.md
new file mode 100644
index 000000000..e22a2bb4a
--- /dev/null
+++ b/docs/cmdline-opts/disable.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: disable
+Short: q
+Help: Disable .curlrc
+Category: curl
+Added: 5.0
+Multi: boolean
+See-also:
+ - config
+Example:
+ - -q $URL
+---
+
+# `--disable`
+
+If used as the **first** parameter on the command line, the *curlrc* config
+file is not read or used. See the --config for details on the default config
+file search path.
+
+Prior to 7.50.0 curl supported the short option name *q* but not the long
+option name *disable*.
diff --git a/docs/cmdline-opts/disallow-username-in-url.d b/docs/cmdline-opts/disallow-username-in-url.d
deleted file mode 100644
index d0537db97..000000000
--- a/docs/cmdline-opts/disallow-username-in-url.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: disallow-username-in-url
-Help: Disallow username in URL
-Protocols: HTTP
-Added: 7.61.0
-See-also: proto
-Category: curl http
-Example: --disallow-username-in-url $URL
-Multi: boolean
----
-This tells curl to exit if passed a URL containing a username. This is probably
-most useful when the URL is being provided at runtime or similar.
diff --git a/docs/cmdline-opts/disallow-username-in-url.md b/docs/cmdline-opts/disallow-username-in-url.md
new file mode 100644
index 000000000..faa4d8834
--- /dev/null
+++ b/docs/cmdline-opts/disallow-username-in-url.md
@@ -0,0 +1,18 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: disallow-username-in-url
+Help: Disallow username in URL
+Added: 7.61.0
+Category: curl
+Multi: boolean
+See-also:
+ - proto
+Example:
+ - --disallow-username-in-url $URL
+---
+
+# `--disallow-username-in-url`
+
+This tells curl to exit if passed a URL containing a username. This is probably
+most useful when the URL is being provided at runtime or similar.
diff --git a/docs/cmdline-opts/dns-interface.d b/docs/cmdline-opts/dns-interface.d
deleted file mode 100644
index fd924b897..000000000
--- a/docs/cmdline-opts/dns-interface.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: dns-interface
-Arg: <interface>
-Help: Interface to use for DNS requests
-Protocols: DNS
-See-also: dns-ipv4-addr dns-ipv6-addr
-Added: 7.33.0
-Requires: c-ares
-Category: dns
-Example: --dns-interface eth0 $URL
-Multi: single
----
-Tell curl to send outgoing DNS requests through <interface>. This option is a
-counterpart to --interface (which does not affect DNS). The supplied string
-must be an interface name (not an address).
diff --git a/docs/cmdline-opts/dns-interface.md b/docs/cmdline-opts/dns-interface.md
new file mode 100644
index 000000000..afc5573e5
--- /dev/null
+++ b/docs/cmdline-opts/dns-interface.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: dns-interface
+Arg: <interface>
+Help: Interface to use for DNS requests
+Protocols: DNS
+Added: 7.33.0
+Requires: c-ares
+Category: dns
+Multi: single
+See-also:
+ - dns-ipv4-addr
+ - dns-ipv6-addr
+Example:
+ - --dns-interface eth0 $URL
+---
+
+# `--dns-interface`
+
+Tell curl to send outgoing DNS requests through <interface>. This option is a
+counterpart to --interface (which does not affect DNS). The supplied string
+must be an interface name (not an address).
diff --git a/docs/cmdline-opts/dns-ipv4-addr.d b/docs/cmdline-opts/dns-ipv4-addr.d
deleted file mode 100644
index 593055739..000000000
--- a/docs/cmdline-opts/dns-ipv4-addr.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: dns-ipv4-addr
-Arg: <address>
-Help: IPv4 address to use for DNS requests
-Protocols: DNS
-See-also: dns-interface dns-ipv6-addr
-Added: 7.33.0
-Requires: c-ares
-Category: dns
-Example: --dns-ipv4-addr 10.1.2.3 $URL
-Multi: single
----
-Tell curl to bind to a specific IP address when making IPv4 DNS requests, so
-that the DNS requests originate from this address. The argument should be a
-single IPv4 address.
diff --git a/docs/cmdline-opts/dns-ipv4-addr.md b/docs/cmdline-opts/dns-ipv4-addr.md
new file mode 100644
index 000000000..ff4163bc1
--- /dev/null
+++ b/docs/cmdline-opts/dns-ipv4-addr.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: dns-ipv4-addr
+Arg: <address>
+Help: IPv4 address to use for DNS requests
+Protocols: DNS
+Added: 7.33.0
+Requires: c-ares
+Category: dns
+Multi: single
+See-also:
+ - dns-interface
+ - dns-ipv6-addr
+Example:
+ - --dns-ipv4-addr 10.1.2.3 $URL
+---
+
+# `--dns-ipv4-addr`
+
+Tell curl to bind to a specific IP address when making IPv4 DNS requests, so
+that the DNS requests originate from this address. The argument should be a
+single IPv4 address.
diff --git a/docs/cmdline-opts/dns-ipv6-addr.d b/docs/cmdline-opts/dns-ipv6-addr.d
deleted file mode 100644
index a76120cdc..000000000
--- a/docs/cmdline-opts/dns-ipv6-addr.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: dns-ipv6-addr
-Arg: <address>
-Help: IPv6 address to use for DNS requests
-Protocols: DNS
-See-also: dns-interface dns-ipv4-addr
-Added: 7.33.0
-Requires: c-ares
-Category: dns
-Example: --dns-ipv6-addr 2a04:4e42::561 $URL
-Multi: single
----
-Tell curl to bind to a specific IP address when making IPv6 DNS requests, so
-that the DNS requests originate from this address. The argument should be a
-single IPv6 address.
diff --git a/docs/cmdline-opts/dns-ipv6-addr.md b/docs/cmdline-opts/dns-ipv6-addr.md
new file mode 100644
index 000000000..7d4d1c1f5
--- /dev/null
+++ b/docs/cmdline-opts/dns-ipv6-addr.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: dns-ipv6-addr
+Arg: <address>
+Help: IPv6 address to use for DNS requests
+Protocols: DNS
+Added: 7.33.0
+Requires: c-ares
+Category: dns
+Multi: single
+See-also:
+ - dns-interface
+ - dns-ipv4-addr
+Example:
+ - --dns-ipv6-addr 2a04:4e42::561 $URL
+---
+
+# `--dns-ipv6-addr`
+
+Tell curl to bind to a specific IP address when making IPv6 DNS requests, so
+that the DNS requests originate from this address. The argument should be a
+single IPv6 address.
diff --git a/docs/cmdline-opts/dns-servers.d b/docs/cmdline-opts/dns-servers.d
deleted file mode 100644
index bec23a3c3..000000000
--- a/docs/cmdline-opts/dns-servers.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: dns-servers
-Arg: <addresses>
-Help: DNS server addrs to use
-Requires: c-ares
-Added: 7.33.0
-Category: dns
-Example: --dns-servers 192.168.0.1,192.168.0.2 $URL
-See-also: dns-interface dns-ipv4-addr
-Multi: single
----
-Set the list of DNS servers to be used instead of the system default.
-The list of IP addresses should be separated with commas. Port numbers
-may also optionally be given as *:<port-number>* after each IP
-address.
diff --git a/docs/cmdline-opts/dns-servers.md b/docs/cmdline-opts/dns-servers.md
new file mode 100644
index 000000000..3eab6668d
--- /dev/null
+++ b/docs/cmdline-opts/dns-servers.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: dns-servers
+Arg: <addresses>
+Help: DNS server addrs to use
+Protocols: DNS
+Requires: c-ares
+Added: 7.33.0
+Category: dns
+Multi: single
+See-also:
+ - dns-interface
+ - dns-ipv4-addr
+Example:
+ - --dns-servers 192.168.0.1,192.168.0.2 $URL
+---
+
+# `--dns-servers`
+
+Set the list of DNS servers to be used instead of the system default.
+The list of IP addresses should be separated with commas. Port numbers
+may also optionally be given as *:<port-number>* after each IP
+address.
diff --git a/docs/cmdline-opts/doh-cert-status.d b/docs/cmdline-opts/doh-cert-status.d
deleted file mode 100644
index 37ae0f827..000000000
--- a/docs/cmdline-opts/doh-cert-status.d
+++ /dev/null
@@ -1,11 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: doh-cert-status
-Help: Verify the status of the DoH server cert via OCSP-staple
-Added: 7.76.0
-Category: dns tls
-Example: --doh-cert-status --doh-url https://doh.example $URL
-See-also: doh-insecure
-Multi: boolean
----
-Same as --cert-status but used for DoH (DNS-over-HTTPS).
diff --git a/docs/cmdline-opts/doh-cert-status.md b/docs/cmdline-opts/doh-cert-status.md
new file mode 100644
index 000000000..efa9da75c
--- /dev/null
+++ b/docs/cmdline-opts/doh-cert-status.md
@@ -0,0 +1,17 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: doh-cert-status
+Help: Verify the status of the DoH server cert via OCSP-staple
+Added: 7.76.0
+Category: dns tls
+Multi: boolean
+See-also:
+ - doh-insecure
+Example:
+ - --doh-cert-status --doh-url https://doh.example $URL
+---
+
+# `--doh-cert-status`
+
+Same as --cert-status but used for DoH (DNS-over-HTTPS).
diff --git a/docs/cmdline-opts/doh-insecure.d b/docs/cmdline-opts/doh-insecure.d
deleted file mode 100644
index dcc65fb6c..000000000
--- a/docs/cmdline-opts/doh-insecure.d
+++ /dev/null
@@ -1,11 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: doh-insecure
-Help: Allow insecure DoH server connections
-Added: 7.76.0
-Category: dns tls
-Example: --doh-insecure --doh-url https://doh.example $URL
-See-also: doh-url
-Multi: boolean
----
-Same as --insecure but used for DoH (DNS-over-HTTPS).
diff --git a/docs/cmdline-opts/doh-insecure.md b/docs/cmdline-opts/doh-insecure.md
new file mode 100644
index 000000000..684428ddf
--- /dev/null
+++ b/docs/cmdline-opts/doh-insecure.md
@@ -0,0 +1,17 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: doh-insecure
+Help: Allow insecure DoH server connections
+Added: 7.76.0
+Category: dns tls
+Multi: boolean
+See-also:
+ - doh-url
+Example:
+ - --doh-insecure --doh-url https://doh.example $URL
+---
+
+# `--doh-insecure`
+
+Same as --insecure but used for DoH (DNS-over-HTTPS).
diff --git a/docs/cmdline-opts/doh-url.d b/docs/cmdline-opts/doh-url.d
deleted file mode 100644
index 6d0dd1605..000000000
--- a/docs/cmdline-opts/doh-url.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: doh-url
-Arg: <URL>
-Help: Resolve host names over DoH
-Added: 7.62.0
-Category: dns
-Example: --doh-url https://doh.example $URL
-See-also: doh-insecure
-Multi: single
----
-Specifies which DNS-over-HTTPS (DoH) server to use to resolve hostnames,
-instead of using the default name resolver mechanism. The URL must be HTTPS.
-
-Some SSL options that you set for your transfer also applies to DoH since the
-name lookups take place over SSL. However, the certificate verification
-settings are not inherited but are controlled separately via --doh-insecure
-and --doh-cert-status.
-
-This option is unset if an empty string "" is used as the URL.
-(Added in 7.85.0)
diff --git a/docs/cmdline-opts/doh-url.md b/docs/cmdline-opts/doh-url.md
new file mode 100644
index 000000000..d12bf5194
--- /dev/null
+++ b/docs/cmdline-opts/doh-url.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: doh-url
+Arg: <URL>
+Help: Resolve host names over DoH
+Added: 7.62.0
+Category: dns
+Multi: single
+See-also:
+ - doh-insecure
+Example:
+ - --doh-url https://doh.example $URL
+---
+
+# `--doh-url`
+
+Specifies which DNS-over-HTTPS (DoH) server to use to resolve hostnames,
+instead of using the default name resolver mechanism. The URL must be HTTPS.
+
+Some SSL options that you set for your transfer also applies to DoH since the
+name lookups take place over SSL. However, the certificate verification
+settings are not inherited but are controlled separately via --doh-insecure
+and --doh-cert-status.
+
+This option is unset if an empty string "" is used as the URL.
+(Added in 7.85.0)
diff --git a/docs/cmdline-opts/dump-header.d b/docs/cmdline-opts/dump-header.d
deleted file mode 100644
index 42a79e7dd..000000000
--- a/docs/cmdline-opts/dump-header.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: dump-header
-Short: D
-Arg: <filename>
-Help: Write the received headers to <filename>
-Protocols: HTTP FTP
-See-also: output
-Category: http ftp
-Example: --dump-header store.txt $URL
-Added: 5.7
-Multi: single
----
-Write the received protocol headers to the specified file. If no headers are
-received, the use of this option creates an empty file.
-
-When used in FTP, the FTP server response lines are considered being "headers"
-and thus are saved there.
-
-Having multiple transfers in one set of operations (i.e. the URLs in one
---next clause), appends them to the same file, separated by a blank line.
diff --git a/docs/cmdline-opts/dump-header.md b/docs/cmdline-opts/dump-header.md
new file mode 100644
index 000000000..42d3e85ed
--- /dev/null
+++ b/docs/cmdline-opts/dump-header.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: dump-header
+Short: D
+Arg: <filename>
+Help: Write the received headers to <filename>
+Protocols: HTTP FTP
+Category: http ftp
+Added: 5.7
+Multi: single
+See-also:
+ - output
+Example:
+ - --dump-header store.txt $URL
+---
+
+# `--dump-header`
+
+Write the received protocol headers to the specified file. If no headers are
+received, the use of this option creates an empty file.
+
+When used in FTP, the FTP server response lines are considered being "headers"
+and thus are saved there.
+
+Having multiple transfers in one set of operations (i.e. the URLs in one
+--next clause), appends them to the same file, separated by a blank line.
diff --git a/docs/cmdline-opts/egd-file.d b/docs/cmdline-opts/egd-file.d
deleted file mode 100644
index 4543ecf15..000000000
--- a/docs/cmdline-opts/egd-file.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: egd-file
-Arg: <file>
-Help: EGD socket path for random data
-Protocols: TLS
-See-also: random-file
-Category: tls
-Example: --egd-file /random/here $URL
-Added: 7.7
-Multi: single
----
-Deprecated option (added in 7.84.0). Prior to that it only had an effect on
-curl if built to use old versions of OpenSSL.
-
-Specify the path name to the Entropy Gathering Daemon socket. The socket is
-used to seed the random engine for SSL connections.
diff --git a/docs/cmdline-opts/egd-file.md b/docs/cmdline-opts/egd-file.md
new file mode 100644
index 000000000..b68b7d496
--- /dev/null
+++ b/docs/cmdline-opts/egd-file.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: egd-file
+Arg: <file>
+Help: EGD socket path for random data
+Protocols: TLS
+Category: tls
+Added: 7.7
+Multi: single
+See-also:
+ - random-file
+Example:
+ - --egd-file /random/here $URL
+---
+
+# `--egd-file`
+
+Deprecated option (added in 7.84.0). Prior to that it only had an effect on
+curl if built to use old versions of OpenSSL.
+
+Specify the path name to the Entropy Gathering Daemon socket. The socket is
+used to seed the random engine for SSL connections.
diff --git a/docs/cmdline-opts/engine.d b/docs/cmdline-opts/engine.d
deleted file mode 100644
index 1ebc779c0..000000000
--- a/docs/cmdline-opts/engine.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: engine
-Arg: <name>
-Help: Crypto engine to use
-Protocols: TLS
-Category: tls
-Example: --engine flavor $URL
-Added: 7.9.3
-See-also: ciphers curves
-Multi: single
----
-Select the OpenSSL crypto engine to use for cipher operations. Use --engine
-list to print a list of build-time supported engines. Note that not all (and
-possibly none) of the engines may be available at runtime.
diff --git a/docs/cmdline-opts/engine.md b/docs/cmdline-opts/engine.md
new file mode 100644
index 000000000..511190023
--- /dev/null
+++ b/docs/cmdline-opts/engine.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: engine
+Arg: <name>
+Help: Crypto engine to use
+Protocols: TLS
+Category: tls
+Added: 7.9.3
+Multi: single
+See-also:
+ - ciphers
+ - curves
+Example:
+ - --engine flavor $URL
+---
+
+# `--engine`
+
+Select the OpenSSL crypto engine to use for cipher operations. Use --engine
+list to print a list of build-time supported engines. Note that not all (and
+possibly none) of the engines may be available at runtime.
diff --git a/docs/cmdline-opts/etag-compare.d b/docs/cmdline-opts/etag-compare.d
deleted file mode 100644
index d3c48d17a..000000000
--- a/docs/cmdline-opts/etag-compare.d
+++ /dev/null
@@ -1,23 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: etag-compare
-Arg: <file>
-Help: Pass an ETag from a file as a custom header
-Protocols: HTTP
-Added: 7.68.0
-Category: http
-Example: --etag-compare etag.txt $URL
-See-also: etag-save time-cond
-Multi: single
----
-This option makes a conditional HTTP request for the specific ETag read
-from the given file by sending a custom If-None-Match header using the
-stored ETag.
-
-For correct results, make sure that the specified file contains only a
-single line with the desired ETag. An empty file is parsed as an empty
-ETag.
-
-Use the option --etag-save to first save the ETag from a response, and
-then use this option to compare against the saved ETag in a subsequent
-request.
diff --git a/docs/cmdline-opts/etag-compare.md b/docs/cmdline-opts/etag-compare.md
new file mode 100644
index 000000000..11c1d0e87
--- /dev/null
+++ b/docs/cmdline-opts/etag-compare.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: etag-compare
+Arg: <file>
+Help: Pass an ETag from a file as a custom header
+Protocols: HTTP
+Added: 7.68.0
+Category: http
+Multi: single
+See-also:
+ - etag-save
+ - time-cond
+Example:
+ - --etag-compare etag.txt $URL
+---
+
+# `--etag-compare`
+
+This option makes a conditional HTTP request for the specific ETag read
+from the given file by sending a custom If-None-Match header using the
+stored ETag.
+
+For correct results, make sure that the specified file contains only a
+single line with the desired ETag. An empty file is parsed as an empty
+ETag.
+
+Use the option --etag-save to first save the ETag from a response, and
+then use this option to compare against the saved ETag in a subsequent
+request.
diff --git a/docs/cmdline-opts/etag-save.d b/docs/cmdline-opts/etag-save.d
deleted file mode 100644
index 6295a9e31..000000000
--- a/docs/cmdline-opts/etag-save.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: etag-save
-Arg: <file>
-Help: Parse ETag from a request and save it to a file
-Protocols: HTTP
-Added: 7.68.0
-Category: http
-Example: --etag-save storetag.txt $URL
-See-also: etag-compare
-Multi: single
----
-This option saves an HTTP ETag to the specified file. An ETag is a
-caching related header, usually returned in a response.
-
-If no ETag is sent by the server, an empty file is created.
diff --git a/docs/cmdline-opts/etag-save.md b/docs/cmdline-opts/etag-save.md
new file mode 100644
index 000000000..f6fb14a51
--- /dev/null
+++ b/docs/cmdline-opts/etag-save.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: etag-save
+Arg: <file>
+Help: Parse ETag from a request and save it to a file
+Protocols: HTTP
+Added: 7.68.0
+Category: http
+Multi: single
+See-also:
+ - etag-compare
+Example:
+ - --etag-save storetag.txt $URL
+---
+
+# `--etag-save`
+
+This option saves an HTTP ETag to the specified file. An ETag is a
+caching related header, usually returned in a response.
+
+If no ETag is sent by the server, an empty file is created.
diff --git a/docs/cmdline-opts/expect100-timeout.d b/docs/cmdline-opts/expect100-timeout.d
deleted file mode 100644
index f9a119bd9..000000000
--- a/docs/cmdline-opts/expect100-timeout.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: expect100-timeout
-Arg: <seconds>
-Help: How long to wait for 100-continue
-Protocols: HTTP
-Added: 7.47.0
-See-also: connect-timeout
-Category: http
-Example: --expect100-timeout 2.5 -T file $URL
-Multi: single
----
-Maximum time in seconds that you allow curl to wait for a 100-continue
-response when curl emits an Expects: 100-continue header in its request. By
-default curl waits one second. This option accepts decimal values! When
-curl stops waiting, it continues as if the response has been received.
-
-The decimal value needs to provided using a dot (.) as decimal separator - not
-the local version even if it might be using another separator.
diff --git a/docs/cmdline-opts/expect100-timeout.md b/docs/cmdline-opts/expect100-timeout.md
new file mode 100644
index 000000000..9554568a7
--- /dev/null
+++ b/docs/cmdline-opts/expect100-timeout.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: expect100-timeout
+Arg: <seconds>
+Help: How long to wait for 100-continue
+Protocols: HTTP
+Added: 7.47.0
+Category: http
+Multi: single
+See-also:
+ - connect-timeout
+Example:
+ - --expect100-timeout 2.5 -T file $URL
+---
+
+# `--expect100-timeout`
+
+Maximum time in seconds that you allow curl to wait for a 100-continue
+response when curl emits an Expects: 100-continue header in its request. By
+default curl waits one second. This option accepts decimal values! When
+curl stops waiting, it continues as if the response has been received.
+
+The decimal value needs to provided using a dot (.) as decimal separator - not
+the local version even if it might be using another separator.
diff --git a/docs/cmdline-opts/fail-early.d b/docs/cmdline-opts/fail-early.d
deleted file mode 100644
index 36b330999..000000000
--- a/docs/cmdline-opts/fail-early.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: fail-early
-Help: Fail on first transfer error, do not continue
-Added: 7.52.0
-Category: curl
-Example: --fail-early $URL https://two.example
-See-also: fail fail-with-body
-Multi: boolean
-Scope: global
----
-Fail and exit on the first detected transfer error.
-
-When curl is used to do multiple transfers on the command line, it attempts to
-operate on each given URL, one by one. By default, it ignores errors if there
-are more URLs given and the last URL's success determines the error code curl
-returns. So early failures are "hidden" by subsequent successful transfers.
-
-Using this option, curl instead returns an error on the first transfer that
-fails, independent of the amount of URLs that are given on the command
-line. This way, no transfer failures go undetected by scripts and similar.
-
-This option does not imply --fail, which causes transfers to fail due to the
-server's HTTP status code. You can combine the two options, however note --fail
-is not global and is therefore contained by --next.
diff --git a/docs/cmdline-opts/fail-early.md b/docs/cmdline-opts/fail-early.md
new file mode 100644
index 000000000..b68160c20
--- /dev/null
+++ b/docs/cmdline-opts/fail-early.md
@@ -0,0 +1,32 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: fail-early
+Help: Fail on first transfer error, do not continue
+Added: 7.52.0
+Category: curl
+Multi: boolean
+Scope: global
+See-also:
+ - fail
+ - fail-with-body
+Example:
+ - --fail-early $URL https://two.example
+---
+
+# `--fail-early`
+
+Fail and exit on the first detected transfer error.
+
+When curl is used to do multiple transfers on the command line, it attempts to
+operate on each given URL, one by one. By default, it ignores errors if there
+are more URLs given and the last URL's success determines the error code curl
+returns. So early failures are "hidden" by subsequent successful transfers.
+
+Using this option, curl instead returns an error on the first transfer that
+fails, independent of the amount of URLs that are given on the command
+line. This way, no transfer failures go undetected by scripts and similar.
+
+This option does not imply --fail, which causes transfers to fail due to the
+server's HTTP status code. You can combine the two options, however note --fail
+is not global and is therefore contained by --next.
diff --git a/docs/cmdline-opts/fail-with-body.d b/docs/cmdline-opts/fail-with-body.d
deleted file mode 100644
index dddb86e22..000000000
--- a/docs/cmdline-opts/fail-with-body.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: fail-with-body
-Protocols: HTTP
-Help: Fail on HTTP errors but save the body
-Category: http output
-Added: 7.76.0
-See-also: fail fail-early
-Mutexed: fail
-Example: --fail-with-body $URL
-Multi: boolean
----
-Return an error on server errors where the HTTP response code is 400 or
-greater). In normal cases when an HTTP server fails to deliver a document, it
-returns an HTML document stating so (which often also describes why and
-more). This flag allows curl to output and save that content but also to
-return error 22.
-
-This is an alternative option to --fail which makes curl fail for the same
-circumstances but without saving the content.
diff --git a/docs/cmdline-opts/fail-with-body.md b/docs/cmdline-opts/fail-with-body.md
new file mode 100644
index 000000000..e340cb034
--- /dev/null
+++ b/docs/cmdline-opts/fail-with-body.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: fail-with-body
+Protocols: HTTP
+Help: Fail on HTTP errors but save the body
+Category: http output
+Added: 7.76.0
+Mutexed: fail
+Multi: boolean
+See-also:
+ - fail
+ - fail-early
+Example:
+ - --fail-with-body $URL
+---
+
+# `--fail-with-body`
+
+Return an error on server errors where the HTTP response code is 400 or
+greater). In normal cases when an HTTP server fails to deliver a document, it
+returns an HTML document stating so (which often also describes why and
+more). This flag allows curl to output and save that content but also to
+return error 22.
+
+This is an alternative option to --fail which makes curl fail for the same
+circumstances but without saving the content.
diff --git a/docs/cmdline-opts/fail.d b/docs/cmdline-opts/fail.d
deleted file mode 100644
index 8196a908d..000000000
--- a/docs/cmdline-opts/fail.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: fail
-Short: f
-Protocols: HTTP
-Help: Fail fast with no output on HTTP errors
-See-also: fail-with-body fail-early
-Category: important http
-Example: --fail $URL
-Mutexed: fail-with-body
-Added: 4.0
-Multi: boolean
----
-Fail fast with no output at all on server errors. This is useful to enable
-scripts and users to better deal with failed attempts. In normal cases when an
-HTTP server fails to deliver a document, it returns an HTML document stating
-so (which often also describes why and more). This flag prevents curl from
-outputting that and return error 22.
-
-This method is not fail-safe and there are occasions where non-successful
-response codes slip through, especially when authentication is involved
-(response codes 401 and 407).
diff --git a/docs/cmdline-opts/fail.md b/docs/cmdline-opts/fail.md
new file mode 100644
index 000000000..b8de4ebb2
--- /dev/null
+++ b/docs/cmdline-opts/fail.md
@@ -0,0 +1,29 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: fail
+Short: f
+Protocols: HTTP
+Help: Fail fast with no output on HTTP errors
+Category: important http
+Mutexed: fail-with-body
+Added: 4.0
+Multi: boolean
+See-also:
+ - fail-with-body
+ - fail-early
+Example:
+ - --fail $URL
+---
+
+# `--fail`
+
+Fail fast with no output at all on server errors. This is useful to enable
+scripts and users to better deal with failed attempts. In normal cases when an
+HTTP server fails to deliver a document, it returns an HTML document stating
+so (which often also describes why and more). This flag prevents curl from
+outputting that and return error 22.
+
+This method is not fail-safe and there are occasions where non-successful
+response codes slip through, especially when authentication is involved
+(response codes 401 and 407).
diff --git a/docs/cmdline-opts/false-start.d b/docs/cmdline-opts/false-start.d
deleted file mode 100644
index 73240492b..000000000
--- a/docs/cmdline-opts/false-start.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: false-start
-Help: Enable TLS False Start
-Protocols: TLS
-Added: 7.42.0
-Category: tls
-Example: --false-start $URL
-See-also: tcp-fastopen
-Multi: boolean
----
-Tells curl to use false start during the TLS handshake. False start is a mode
-where a TLS client starts sending application data before verifying the
-server's Finished message, thus saving a round trip when performing a full
-handshake.
-
-This is currently only implemented in the Secure Transport (on iOS 7.0 or
-later, or OS X 10.9 or later) backend.
diff --git a/docs/cmdline-opts/false-start.md b/docs/cmdline-opts/false-start.md
new file mode 100644
index 000000000..d2697da53
--- /dev/null
+++ b/docs/cmdline-opts/false-start.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: false-start
+Help: Enable TLS False Start
+Protocols: TLS
+Added: 7.42.0
+Category: tls
+Multi: boolean
+See-also:
+ - tcp-fastopen
+Example:
+ - --false-start $URL
+---
+
+# `--false-start`
+
+Tells curl to use false start during the TLS handshake. False start is a mode
+where a TLS client starts sending application data before verifying the
+server's Finished message, thus saving a round trip when performing a full
+handshake.
+
+This is currently only implemented in the Secure Transport (on iOS 7.0 or
+later, or OS X 10.9 or later) backend.
diff --git a/docs/cmdline-opts/form-escape.d b/docs/cmdline-opts/form-escape.d
deleted file mode 100644
index 304bfe814..000000000
--- a/docs/cmdline-opts/form-escape.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: form-escape
-Help: Escape multipart form field/file names using backslash
-Protocols: HTTP
-See-also: form
-Added: 7.81.0
-Category: http upload
-Example: --form-escape -F 'field\\name=curl' -F 'file=@load"this' $URL
-Multi: single
----
-Tells curl to pass on names of multipart form fields and files using
-backslash-escaping instead of percent-encoding.
diff --git a/docs/cmdline-opts/form-escape.md b/docs/cmdline-opts/form-escape.md
new file mode 100644
index 000000000..62973f172
--- /dev/null
+++ b/docs/cmdline-opts/form-escape.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: form-escape
+Help: Escape multipart form field/file names using backslash
+Protocols: HTTP
+Added: 7.81.0
+Category: http upload
+Multi: single
+See-also:
+ - form
+Example:
+ - --form-escape -F 'field\name=curl' -F 'file=@load"this' $URL
+---
+
+# `--form-escape`
+
+Tells curl to pass on names of multipart form fields and files using
+backslash-escaping instead of percent-encoding.
diff --git a/docs/cmdline-opts/form-string.d b/docs/cmdline-opts/form-string.d
deleted file mode 100644
index 6d7a500a4..000000000
--- a/docs/cmdline-opts/form-string.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: form-string
-Help: Specify multipart MIME data
-Protocols: HTTP SMTP IMAP
-Arg: <name=string>
-See-also: form
-Category: http upload
-Example: --form-string "data" $URL
-Added: 7.13.2
-Multi: append
----
-Similar to --form except that the value string for the named parameter is used
-literally. Leading '@' and '<' characters, and the ';type=' string in
-the value have no special meaning. Use this in preference to --form if
-there is any possibility that the string value may accidentally trigger the
-'@' or '<' features of --form.
diff --git a/docs/cmdline-opts/form-string.md b/docs/cmdline-opts/form-string.md
new file mode 100644
index 000000000..d26c47142
--- /dev/null
+++ b/docs/cmdline-opts/form-string.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: form-string
+Help: Specify multipart MIME data
+Protocols: HTTP SMTP IMAP
+Arg: <name=string>
+Category: http upload
+Added: 7.13.2
+Multi: append
+See-also:
+ - form
+Example:
+ - --form-string "data" $URL
+---
+
+# `--form-string`
+
+Similar to --form except that the value string for the named parameter is used
+literally. Leading '@' and '<' characters, and the ';type=' string in
+the value have no special meaning. Use this in preference to --form if
+there is any possibility that the string value may accidentally trigger the
+'@' or '<' features of --form.
diff --git a/docs/cmdline-opts/form.d b/docs/cmdline-opts/form.d
deleted file mode 100644
index e53e93ae0..000000000
--- a/docs/cmdline-opts/form.d
+++ /dev/null
@@ -1,134 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: form
-Short: F
-Arg: <name=content>
-Help: Specify multipart MIME data
-Protocols: HTTP SMTP IMAP
-Mutexed: data head upload-file
-Category: http upload
-Example: --form "name=curl" --form "file=@loadthis" $URL
-Added: 5.0
-See-also: data form-string form-escape
-Multi: append
----
-For HTTP protocol family, this lets curl emulate a filled-in form in which a
-user has pressed the submit button. This causes curl to POST data using the
-Content-Type multipart/form-data according to RFC 2388.
-
-For SMTP and IMAP protocols, this is the means to compose a multipart mail
-message to transmit.
-
-This enables uploading of binary files etc. To force the 'content' part to be
-a file, prefix the file name with an @ sign. To just get the content part from
-a file, prefix the file name with the symbol <. The difference between @ and <
-is then that @ makes a file get attached in the post as a file upload, while
-the < makes a text field and just get the contents for that text field from a
-file.
-
-Tell curl to read content from stdin instead of a file by using - as
-filename. This goes for both @ and < constructs. When stdin is used, the
-contents is buffered in memory first by curl to determine its size and allow a
-possible resend. Defining a part's data from a named non-regular file (such as
-a named pipe or similar) is not subject to buffering and is instead read at
-transmission time; since the full size is unknown before the transfer starts,
-such data is sent as chunks by HTTP and rejected by IMAP.
-
-Example: send an image to an HTTP server, where 'profile' is the name of the
-form-field to which the file **portrait.jpg** is the input:
-
- curl -F profile=@portrait.jpg https://example.com/upload.cgi
-
-Example: send your name and shoe size in two text fields to the server:
-
- curl -F name=John -F shoesize=11 https://example.com/
-
-Example: send your essay in a text field to the server. Send it as a plain
-text field, but get the contents for it from a local file:
-
- curl -F "story=<hugefile.txt" https://example.com/
-
-You can also tell curl what Content-Type to use by using 'type=', in a manner
-similar to:
-
- curl -F "web=@index.html;type=text/html" example.com
-
-or
-
- curl -F "name=daniel;type=text/foo" example.com
-
-You can also explicitly change the name field of a file upload part by setting
-filename=, like this:
-
- curl -F "file=@localfile;filename=nameinpost" example.com
-
-If filename/path contains ',' or ';', it must be quoted by double-quotes like:
-
- curl -F "file=@\\"local,file\\";filename=\\"name;in;post\\"" example.com
-
-or
-
- curl -F 'file=@"local,file";filename="name;in;post"' example.com
-
-Note that if a filename/path is quoted by double-quotes, any double-quote
-or backslash within the filename must be escaped by backslash.
-
-Quoting must also be applied to non-file data if it contains semicolons,
-leading/trailing spaces or leading double quotes:
-
- curl -F 'colors="red; green; blue";type=text/x-myapp' example.com
-
-You can add custom headers to the field by setting headers=, like
-
- curl -F "submit=OK;headers=\\"X-submit-type: OK\\"" example.com
-
-or
-
- curl -F "submit=OK;headers=@headerfile" example.com
-
-The headers= keyword may appear more that once and above notes about quoting
-apply. When headers are read from a file, Empty lines and lines starting
-with '#' are comments and ignored; each header can be folded by splitting
-between two words and starting the continuation line with a space; embedded
-carriage-returns and trailing spaces are stripped.
-Here is an example of a header file contents:
-
- # This file contain two headers.
- X-header-1: this is a header
-
- # The following header is folded.
- X-header-2: this is
- another header
-
-To support sending multipart mail messages, the syntax is extended as follows:
-.br
-- name can be omitted: the equal sign is the first character of the argument,
-.br
-- if data starts with '(', this signals to start a new multipart: it can be
-followed by a content type specification.
-.br
-- a multipart can be terminated with a '=)' argument.
-
-Example: the following command sends an SMTP mime email consisting in an
-inline part in two alternative formats: plain text and HTML. It attaches a
-text file:
-
- curl -F '=(;type=multipart/alternative' \\
- -F '=plain text message' \\
- -F '= <body>HTML message</body>;type=text/html' \\
- -F '=)' -F '=@textfile.txt' ... smtp://example.com
-
-Data can be encoded for transfer using encoder=. Available encodings are
-*binary* and *8bit* that do nothing else than adding the corresponding
-Content-Transfer-Encoding header, *7bit* that only rejects 8-bit characters
-with a transfer error, *quoted-printable* and *base64* that encodes data
-according to the corresponding schemes, limiting lines length to 76
-characters.
-
-Example: send multipart mail with a quoted-printable text message and a
-base64 attached file:
-
- curl -F '=text message;encoder=quoted-printable' \\
- -F '=@localfile;encoder=base64' ... smtp://example.com
-
-See further examples and details in the MANUAL.
diff --git a/docs/cmdline-opts/form.md b/docs/cmdline-opts/form.md
new file mode 100644
index 000000000..0ba552136
--- /dev/null
+++ b/docs/cmdline-opts/form.md
@@ -0,0 +1,142 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: form
+Short: F
+Arg: <name=content>
+Help: Specify multipart MIME data
+Protocols: HTTP SMTP IMAP
+Mutexed: data head upload-file
+Category: http upload
+Added: 5.0
+Multi: append
+See-also:
+ - data
+ - form-string
+ - form-escape
+Example:
+ - --form "name=curl" --form "file=@loadthis" $URL
+---
+
+# `--form`
+
+For HTTP protocol family, this lets curl emulate a filled-in form in which a
+user has pressed the submit button. This causes curl to POST data using the
+Content-Type multipart/form-data according to RFC 2388.
+
+For SMTP and IMAP protocols, this is the means to compose a multipart mail
+message to transmit.
+
+This enables uploading of binary files etc. To force the 'content' part to be
+a file, prefix the file name with an @ sign. To just get the content part from
+a file, prefix the file name with the symbol <. The difference between @ and <
+is then that @ makes a file get attached in the post as a file upload, while
+the < makes a text field and just get the contents for that text field from a
+file.
+
+Tell curl to read content from stdin instead of a file by using - as
+filename. This goes for both @ and < constructs. When stdin is used, the
+contents is buffered in memory first by curl to determine its size and allow a
+possible resend. Defining a part's data from a named non-regular file (such as
+a named pipe or similar) is not subject to buffering and is instead read at
+transmission time; since the full size is unknown before the transfer starts,
+such data is sent as chunks by HTTP and rejected by IMAP.
+
+Example: send an image to an HTTP server, where 'profile' is the name of the
+form-field to which the file **portrait.jpg** is the input:
+
+ curl -F profile=@portrait.jpg https://example.com/upload.cgi
+
+Example: send your name and shoe size in two text fields to the server:
+
+ curl -F name=John -F shoesize=11 https://example.com/
+
+Example: send your essay in a text field to the server. Send it as a plain
+text field, but get the contents for it from a local file:
+
+ curl -F "story=<hugefile.txt" https://example.com/
+
+You can also tell curl what Content-Type to use by using 'type=', in a manner
+similar to:
+
+ curl -F "web=@index.html;type=text/html" example.com
+
+or
+
+ curl -F "name=daniel;type=text/foo" example.com
+
+You can also explicitly change the name field of a file upload part by setting
+filename=, like this:
+
+ curl -F "file=@localfile;filename=nameinpost" example.com
+
+If filename/path contains ',' or ';', it must be quoted by double-quotes like:
+
+ curl -F "file=@\"local,file\";filename=\"name;in;post\"" example.com
+
+or
+
+ curl -F 'file=@"local,file";filename="name;in;post"' example.com
+
+Note that if a filename/path is quoted by double-quotes, any double-quote
+or backslash within the filename must be escaped by backslash.
+
+Quoting must also be applied to non-file data if it contains semicolons,
+leading/trailing spaces or leading double quotes:
+
+ curl -F 'colors="red; green; blue";type=text/x-myapp' example.com
+
+You can add custom headers to the field by setting headers=, like
+
+ curl -F "submit=OK;headers=\"X-submit-type: OK\"" example.com
+
+or
+
+ curl -F "submit=OK;headers=@headerfile" example.com
+
+The headers= keyword may appear more that once and above notes about quoting
+apply. When headers are read from a file, Empty lines and lines starting
+with '#' are comments and ignored; each header can be folded by splitting
+between two words and starting the continuation line with a space; embedded
+carriage-returns and trailing spaces are stripped.
+Here is an example of a header file contents:
+
+ # This file contain two headers.
+ X-header-1: this is a header
+
+ # The following header is folded.
+ X-header-2: this is
+ another header
+
+To support sending multipart mail messages, the syntax is extended as follows:
+
+- name can be omitted: the equal sign is the first character of the argument,
+
+- if data starts with '(', this signals to start a new multipart: it can be
+followed by a content type specification.
+
+- a multipart can be terminated with a '=)' argument.
+
+Example: the following command sends an SMTP mime email consisting in an
+inline part in two alternative formats: plain text and HTML. It attaches a
+text file:
+
+ curl -F '=(;type=multipart/alternative' \
+ -F '=plain text message' \
+ -F '= <body>HTML message</body>;type=text/html' \
+ -F '=)' -F '=@textfile.txt' ... smtp://example.com
+
+Data can be encoded for transfer using encoder=. Available encodings are
+*binary* and *8bit* that do nothing else than adding the corresponding
+Content-Transfer-Encoding header, *7bit* that only rejects 8-bit characters
+with a transfer error, *quoted-printable* and *base64* that encodes data
+according to the corresponding schemes, limiting lines length to 76
+characters.
+
+Example: send multipart mail with a quoted-printable text message and a
+base64 attached file:
+
+ curl -F '=text message;encoder=quoted-printable' \
+ -F '=@localfile;encoder=base64' ... smtp://example.com
+
+See further examples and details in the MANUAL.
diff --git a/docs/cmdline-opts/ftp-account.d b/docs/cmdline-opts/ftp-account.d
deleted file mode 100644
index eb669c562..000000000
--- a/docs/cmdline-opts/ftp-account.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-account
-Arg: <data>
-Help: Account data string
-Protocols: FTP
-Added: 7.13.0
-Category: ftp auth
-Example: --ftp-account "mr.robot" ftp://example.com/
-See-also: user
-Multi: single
----
-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/cmdline-opts/ftp-account.md b/docs/cmdline-opts/ftp-account.md
new file mode 100644
index 000000000..2f3363943
--- /dev/null
+++ b/docs/cmdline-opts/ftp-account.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-account
+Arg: <data>
+Help: Account data string
+Protocols: FTP
+Added: 7.13.0
+Category: ftp auth
+Multi: single
+See-also:
+ - user
+Example:
+ - --ftp-account "mr.robot" ftp://example.com/
+---
+
+# `--ftp-account`
+
+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/cmdline-opts/ftp-alternative-to-user.d b/docs/cmdline-opts/ftp-alternative-to-user.d
deleted file mode 100644
index f030bcf59..000000000
--- a/docs/cmdline-opts/ftp-alternative-to-user.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-alternative-to-user
-Arg: <command>
-Help: String to replace USER [name]
-Protocols: FTP
-Added: 7.15.5
-Category: ftp
-Example: --ftp-alternative-to-user "U53r" ftp://example.com
-See-also: ftp-account user
-Multi: single
----
-If authenticating with the USER and PASS commands fails, send this command.
-When connecting to Tumbleweed's Secure Transport server over FTPS using a
-client certificate, using "SITE AUTH" tells the server to retrieve the
-username from the certificate.
diff --git a/docs/cmdline-opts/ftp-alternative-to-user.md b/docs/cmdline-opts/ftp-alternative-to-user.md
new file mode 100644
index 000000000..9bd368600
--- /dev/null
+++ b/docs/cmdline-opts/ftp-alternative-to-user.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-alternative-to-user
+Arg: <command>
+Help: String to replace USER [name]
+Protocols: FTP
+Added: 7.15.5
+Category: ftp
+Multi: single
+See-also:
+ - ftp-account
+ - user
+Example:
+ - --ftp-alternative-to-user "U53r" ftp://example.com
+---
+
+# `--ftp-alternative-to-user`
+
+If authenticating with the USER and PASS commands fails, send this command.
+When connecting to Tumbleweed's Secure Transport server over FTPS using a
+client certificate, using "SITE AUTH" tells the server to retrieve the
+username from the certificate.
diff --git a/docs/cmdline-opts/ftp-create-dirs.d b/docs/cmdline-opts/ftp-create-dirs.d
deleted file mode 100644
index 7c64f0e21..000000000
--- a/docs/cmdline-opts/ftp-create-dirs.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-create-dirs
-Protocols: FTP SFTP
-Help: Create the remote dirs if not present
-See-also: create-dirs
-Category: ftp sftp curl
-Example: --ftp-create-dirs -T file ftp://example.com/remote/path/file
-Added: 7.10.7
-Multi: boolean
----
-When an FTP or SFTP URL/operation uses a path that does not currently exist on
-the server, the standard behavior of curl is to fail. Using this option, curl
-instead attempts to create missing directories.
diff --git a/docs/cmdline-opts/ftp-create-dirs.md b/docs/cmdline-opts/ftp-create-dirs.md
new file mode 100644
index 000000000..5151e336c
--- /dev/null
+++ b/docs/cmdline-opts/ftp-create-dirs.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-create-dirs
+Protocols: FTP SFTP
+Help: Create the remote dirs if not present
+Category: ftp sftp curl
+Added: 7.10.7
+Multi: boolean
+See-also:
+ - create-dirs
+Example:
+ - --ftp-create-dirs -T file ftp://example.com/remote/path/file
+---
+
+# `--ftp-create-dirs`
+
+When an FTP or SFTP URL/operation uses a path that does not currently exist on
+the server, the standard behavior of curl is to fail. Using this option, curl
+instead attempts to create missing directories.
diff --git a/docs/cmdline-opts/ftp-method.d b/docs/cmdline-opts/ftp-method.d
deleted file mode 100644
index 8061d2b68..000000000
--- a/docs/cmdline-opts/ftp-method.d
+++ /dev/null
@@ -1,30 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-method
-Arg: <method>
-Help: Control CWD usage
-Protocols: FTP
-Added: 7.15.1
-Category: ftp
-Example: --ftp-method multicwd ftp://example.com/dir1/dir2/file
-Example: --ftp-method nocwd ftp://example.com/dir1/dir2/file
-Example: --ftp-method singlecwd ftp://example.com/dir1/dir2/file
-See-also: list-only
-Multi: single
----
-Control what method curl should use to reach a file on an FTP(S)
-server. The method argument should be one of the following alternatives:
-.RS
-.IP multicwd
-curl does a single CWD operation for each path part in the given URL. For deep
-hierarchies this means many commands. This is how RFC 1738 says it should
-be done. This is the default but the slowest behavior.
-.IP nocwd
-curl does no CWD at all. curl does SIZE, RETR, STOR etc and give a full
-path to the server for all these commands. This is the fastest behavior.
-.IP singlecwd
-curl does one CWD with the full target directory and then operates on the file
-"normally" (like in the multicwd case). This is somewhat more standards
-compliant than 'nocwd' but without the full penalty of 'multicwd'.
-.RE
-.IP
diff --git a/docs/cmdline-opts/ftp-method.md b/docs/cmdline-opts/ftp-method.md
new file mode 100644
index 000000000..e4e346858
--- /dev/null
+++ b/docs/cmdline-opts/ftp-method.md
@@ -0,0 +1,36 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-method
+Arg: <method>
+Help: Control CWD usage
+Protocols: FTP
+Added: 7.15.1
+Category: ftp
+Multi: single
+See-also:
+ - list-only
+Example:
+ - --ftp-method multicwd ftp://example.com/dir1/dir2/file
+ - --ftp-method nocwd ftp://example.com/dir1/dir2/file
+ - --ftp-method singlecwd ftp://example.com/dir1/dir2/file
+---
+
+# `--ftp-method`
+
+Control what method curl should use to reach a file on an FTP(S)
+server. The method argument should be one of the following alternatives:
+
+## multicwd
+curl does a single CWD operation for each path part in the given URL. For deep
+hierarchies this means many commands. This is how RFC 1738 says it should
+be done. This is the default but the slowest behavior.
+
+## nocwd
+curl does no CWD at all. curl does SIZE, RETR, STOR etc and give a full
+path to the server for all these commands. This is the fastest behavior.
+
+## singlecwd
+curl does one CWD with the full target directory and then operates on the file
+"normally" (like in the multicwd case). This is somewhat more standards
+compliant than 'nocwd' but without the full penalty of 'multicwd'.
diff --git a/docs/cmdline-opts/ftp-pasv.d b/docs/cmdline-opts/ftp-pasv.d
deleted file mode 100644
index c43bf2bee..000000000
--- a/docs/cmdline-opts/ftp-pasv.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-pasv
-Help: Use PASV/EPSV instead of PORT
-Protocols: FTP
-Added: 7.11.0
-See-also: disable-epsv
-Category: ftp
-Example: --ftp-pasv ftp://example.com/
-Multi: boolean
----
-Use passive mode for the data connection. Passive is the internal default
-behavior, but using this option can be used to override a previous --ftp-port
-option.
-
-Reversing an enforced passive really is not doable but you must then instead
-enforce the correct --ftp-port again.
-
-Passive mode means that curl tries the EPSV command first and then PASV,
-unless --disable-epsv is used.
diff --git a/docs/cmdline-opts/ftp-pasv.md b/docs/cmdline-opts/ftp-pasv.md
new file mode 100644
index 000000000..265a8e453
--- /dev/null
+++ b/docs/cmdline-opts/ftp-pasv.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-pasv
+Help: Use PASV/EPSV instead of PORT
+Protocols: FTP
+Added: 7.11.0
+Category: ftp
+Multi: boolean
+See-also:
+ - disable-epsv
+Example:
+ - --ftp-pasv ftp://example.com/
+---
+
+# `--ftp-pasv`
+
+Use passive mode for the data connection. Passive is the internal default
+behavior, but using this option can be used to override a previous --ftp-port
+option.
+
+Reversing an enforced passive really is not doable but you must then instead
+enforce the correct --ftp-port again.
+
+Passive mode means that curl tries the EPSV command first and then PASV,
+unless --disable-epsv is used.
diff --git a/docs/cmdline-opts/ftp-port.d b/docs/cmdline-opts/ftp-port.d
deleted file mode 100644
index e1f4a1dba..000000000
--- a/docs/cmdline-opts/ftp-port.d
+++ /dev/null
@@ -1,41 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-port
-Arg: <address>
-Help: Use PORT instead of PASV
-Short: P
-Protocols: FTP
-See-also: ftp-pasv disable-eprt
-Category: ftp
-Example: -P - ftp:/example.com
-Example: -P eth0 ftp:/example.com
-Example: -P 192.168.0.2 ftp:/example.com
-Added: 4.0
-Multi: single
----
-Reverses the default initiator/listener roles when connecting with FTP. This
-option makes curl use active mode. curl then tells the server to connect back
-to the client's specified address and port, while passive mode asks the server
-to setup an IP address and port for it to connect to. <address> should be one
-of:
-.RS
-.IP interface
-e.g. "eth0" to specify which interface's IP address you want to use (Unix only)
-.IP "IP address"
-e.g. "192.168.10.1" to specify the exact IP address
-.IP "host name"
-e.g. "my.host.domain" to specify the machine
-.IP "-"
-make curl pick the same IP address that is already used for the control
-connection
-.RE
-.IP
-
-Disable the use of PORT with --ftp-pasv. Disable the attempt to use the EPRT
-command instead of PORT by using --disable-eprt. EPRT is really PORT++.
-
-You can also append ":[start]-[end]\&" to the right of the address, to tell
-curl what TCP port range to use. That means you specify a port range, from a
-lower to a higher number. A single number works as well, but do note that it
-increases the risk of failure since the port may not be available.
-(Added in 7.19.5)
diff --git a/docs/cmdline-opts/ftp-port.md b/docs/cmdline-opts/ftp-port.md
new file mode 100644
index 000000000..e9ec59146
--- /dev/null
+++ b/docs/cmdline-opts/ftp-port.md
@@ -0,0 +1,51 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-port
+Arg: <address>
+Help: Use PORT instead of PASV
+Short: P
+Protocols: FTP
+Category: ftp
+Added: 4.0
+Multi: single
+See-also:
+ - ftp-pasv
+ - disable-eprt
+Example:
+ - -P - ftp:/example.com
+ - -P eth0 ftp:/example.com
+ - -P 192.168.0.2 ftp:/example.com
+---
+
+# `--ftp-port`
+
+Reverses the default initiator/listener roles when connecting with FTP. This
+option makes curl use active mode. curl then tells the server to connect back
+to the client's specified address and port, while passive mode asks the server
+to setup an IP address and port for it to connect to. <address> should be one
+of:
+
+## interface
+e.g. **eth0** to specify which interface's IP address you want to use (Unix only)
+
+## IP address
+e.g. **192.168.10.1** to specify the exact IP address
+
+## host name
+e.g. **my.host.domain** to specify the machine
+
+## -
+make curl pick the same IP address that is already used for the control
+connection. This is the recommended choice.
+
+##
+
+Disable the use of PORT with --ftp-pasv. Disable the attempt to use the EPRT
+command instead of PORT by using --disable-eprt. EPRT is really PORT++.
+
+You can also append ":[start]-[end]" to the right of the address, to tell
+curl what TCP port range to use. That means you specify a port range, from a
+lower to a higher number. A single number works as well, but do note that it
+increases the risk of failure since the port may not be available.
+(Added in 7.19.5)
diff --git a/docs/cmdline-opts/ftp-pret.d b/docs/cmdline-opts/ftp-pret.d
deleted file mode 100644
index 4bea99e6d..000000000
--- a/docs/cmdline-opts/ftp-pret.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-pret
-Help: Send PRET before PASV
-Protocols: FTP
-Added: 7.20.0
-Category: ftp
-Example: --ftp-pret ftp://example.com/
-See-also: ftp-port ftp-pasv
-Multi: boolean
----
-Tell curl to send a PRET command before PASV (and EPSV). Certain FTP servers,
-mainly drftpd, require this non-standard command for directory listings as
-well as up and downloads in PASV mode.
diff --git a/docs/cmdline-opts/ftp-pret.md b/docs/cmdline-opts/ftp-pret.md
new file mode 100644
index 000000000..accbc226d
--- /dev/null
+++ b/docs/cmdline-opts/ftp-pret.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-pret
+Help: Send PRET before PASV
+Protocols: FTP
+Added: 7.20.0
+Category: ftp
+Multi: boolean
+See-also:
+ - ftp-port
+ - ftp-pasv
+Example:
+ - --ftp-pret ftp://example.com/
+---
+
+# `--ftp-pret`
+
+Tell curl to send a PRET command before PASV (and EPSV). Certain FTP servers,
+mainly drftpd, require this non-standard command for directory listings as
+well as up and downloads in PASV mode.
diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.d b/docs/cmdline-opts/ftp-skip-pasv-ip.d
deleted file mode 100644
index 3af9c6de4..000000000
--- a/docs/cmdline-opts/ftp-skip-pasv-ip.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-skip-pasv-ip
-Help: Skip the IP address for PASV
-Protocols: FTP
-Added: 7.14.2
-See-also: ftp-pasv
-Category: ftp
-Example: --ftp-skip-pasv-ip ftp://example.com/
-Multi: boolean
----
-Tell curl to not use the IP address the server suggests in its response to
-curl's PASV command when curl connects the data connection. Instead curl
-reuses the same IP address it already uses for the control connection.
-
-This option is enabled by default (added in 7.74.0).
-
-This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
diff --git a/docs/cmdline-opts/ftp-skip-pasv-ip.md b/docs/cmdline-opts/ftp-skip-pasv-ip.md
new file mode 100644
index 000000000..ef94b34af
--- /dev/null
+++ b/docs/cmdline-opts/ftp-skip-pasv-ip.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-skip-pasv-ip
+Help: Skip the IP address for PASV
+Protocols: FTP
+Added: 7.14.2
+Category: ftp
+Multi: boolean
+See-also:
+ - ftp-pasv
+Example:
+ - --ftp-skip-pasv-ip ftp://example.com/
+---
+
+# `--ftp-skip-pasv-ip`
+
+Tell curl to not use the IP address the server suggests in its response to
+curl's PASV command when curl connects the data connection. Instead curl
+reuses the same IP address it already uses for the control connection.
+
+This option is enabled by default (added in 7.74.0).
+
+This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
diff --git a/docs/cmdline-opts/ftp-ssl-ccc-mode.d b/docs/cmdline-opts/ftp-ssl-ccc-mode.d
deleted file mode 100644
index ae9af9429..000000000
--- a/docs/cmdline-opts/ftp-ssl-ccc-mode.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-ssl-ccc-mode
-Arg: <active/passive>
-Help: Set CCC mode
-Protocols: FTP
-Added: 7.16.2
-See-also: ftp-ssl-ccc
-Category: ftp tls
-Example: --ftp-ssl-ccc-mode active --ftp-ssl-ccc ftps://example.com/
-Multi: boolean
----
-Sets the CCC mode. The passive mode does not initiate the shutdown, but
-instead waits for the server to do it, and does not reply to the shutdown from
-the server. The active mode initiates the shutdown and waits for a reply from
-the server.
diff --git a/docs/cmdline-opts/ftp-ssl-ccc-mode.md b/docs/cmdline-opts/ftp-ssl-ccc-mode.md
new file mode 100644
index 000000000..5f428dc0f
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl-ccc-mode.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-ssl-ccc-mode
+Arg: <active/passive>
+Help: Set CCC mode
+Protocols: FTP
+Added: 7.16.2
+Category: ftp tls
+Multi: boolean
+See-also:
+ - ftp-ssl-ccc
+Example:
+ - --ftp-ssl-ccc-mode active --ftp-ssl-ccc ftps://example.com/
+---
+
+# `--ftp-ssl-ccc-mode`
+
+Sets the CCC mode. The passive mode does not initiate the shutdown, but
+instead waits for the server to do it, and does not reply to the shutdown from
+the server. The active mode initiates the shutdown and waits for a reply from
+the server.
diff --git a/docs/cmdline-opts/ftp-ssl-ccc.d b/docs/cmdline-opts/ftp-ssl-ccc.d
deleted file mode 100644
index 33ae83b1c..000000000
--- a/docs/cmdline-opts/ftp-ssl-ccc.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-ssl-ccc
-Help: Send CCC after authenticating
-Protocols: FTP
-See-also: ssl ftp-ssl-ccc-mode
-Added: 7.16.1
-Category: ftp tls
-Example: --ftp-ssl-ccc ftps://example.com/
-Multi: boolean
----
-Use CCC (Clear Command Channel) Shuts down the SSL/TLS layer after
-authenticating. The rest of the control channel communication is be
-unencrypted. This allows NAT routers to follow the FTP transaction. The
-default mode is passive.
diff --git a/docs/cmdline-opts/ftp-ssl-ccc.md b/docs/cmdline-opts/ftp-ssl-ccc.md
new file mode 100644
index 000000000..d477606fe
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl-ccc.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-ssl-ccc
+Help: Send CCC after authenticating
+Protocols: FTP
+Added: 7.16.1
+Category: ftp tls
+Multi: boolean
+See-also:
+ - ssl
+ - ftp-ssl-ccc-mode
+Example:
+ - --ftp-ssl-ccc ftps://example.com/
+---
+
+# `--ftp-ssl-ccc`
+
+Use CCC (Clear Command Channel) Shuts down the SSL/TLS layer after
+authenticating. The rest of the control channel communication is be
+unencrypted. This allows NAT routers to follow the FTP transaction. The
+default mode is passive.
diff --git a/docs/cmdline-opts/ftp-ssl-control.d b/docs/cmdline-opts/ftp-ssl-control.d
deleted file mode 100644
index b89577927..000000000
--- a/docs/cmdline-opts/ftp-ssl-control.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ftp-ssl-control
-Help: Require SSL/TLS for FTP login, clear for transfer
-Protocols: FTP
-Added: 7.16.0
-Category: ftp tls
-Example: --ftp-ssl-control ftp://example.com
-See-also: ssl
-Multi: boolean
----
-Require SSL/TLS for the FTP login, clear for transfer. Allows secure
-authentication, but non-encrypted data transfers for efficiency. Fails the
-transfer if the server does not support SSL/TLS.
diff --git a/docs/cmdline-opts/ftp-ssl-control.md b/docs/cmdline-opts/ftp-ssl-control.md
new file mode 100644
index 000000000..ace1ab29f
--- /dev/null
+++ b/docs/cmdline-opts/ftp-ssl-control.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ftp-ssl-control
+Help: Require SSL/TLS for FTP login, clear for transfer
+Protocols: FTP
+Added: 7.16.0
+Category: ftp tls
+Multi: boolean
+See-also:
+ - ssl
+Example:
+ - --ftp-ssl-control ftp://example.com
+---
+
+# `--ftp-ssl-control`
+
+Require SSL/TLS for the FTP login, clear for transfer. Allows secure
+authentication, but non-encrypted data transfers for efficiency. Fails the
+transfer if the server does not support SSL/TLS.
diff --git a/docs/cmdline-opts/gen.pl b/docs/cmdline-opts/gen.pl
index 8b9b98bb2..f4dcce8ae 100755
--- a/docs/cmdline-opts/gen.pl
+++ b/docs/cmdline-opts/gen.pl
@@ -48,8 +48,14 @@ my %protolong;
my %catlong;
use POSIX qw(strftime);
-my $date = strftime "%B %d %Y", localtime;
-my $year = strftime "%Y", localtime;
+my @ts;
+if (defined($ENV{SOURCE_DATE_EPOCH})) {
+ @ts = localtime($ENV{SOURCE_DATE_EPOCH});
+} else {
+ @ts = localtime;
+}
+my $date = strftime "%B %d %Y", @ts;
+my $year = strftime "%Y", @ts;
my $version = "unknown";
my $globals;
@@ -84,52 +90,8 @@ sub printdesc {
my @desc = @_;
my $exam = 0;
for my $d (@desc) {
- if($d =~ /\(Added in ([0-9.]+)\)/i) {
- my $ver = $1;
- if(too_old($ver)) {
- $d =~ s/ *\(Added in $ver\)//gi;
- }
- }
- if($d !~ /^.\\"/) {
- # **bold**
- $d =~ s/\*\*([^ ]*)\*\*/\\fB$1\\fP/g;
- # *italics*
- $d =~ s/\*([^ ]*)\*/\\fI$1\\fP/g;
- }
- if(!$exam && ($d =~ /^ /)) {
- # start of example
- $exam = 1;
- print ".nf\n"; # no-fill
- }
- elsif($exam && ($d !~ /^ /)) {
- # end of example
- $exam = 0;
- print ".fi\n"; # fill-in
- }
- # skip lines starting with space (examples)
- if($d =~ /^[^ ]/ && $d =~ /--/) {
- # scan for options in longest-names first order
- for my $k (sort {length($b) <=> length($a)} keys %optlong) {
- # --tlsv1 is complicated since --tlsv1.2 etc are also
- # acceptable options!
- if(($k eq "tlsv1") && ($d =~ /--tlsv1\.[0-9]\\f/)) {
- next;
- }
- my $l = manpageify($k);
- $d =~ s/\-\-$k([^a-z0-9-])/$l$1/g;
- }
- }
- # quote minuses in the output
- $d =~ s/([^\\])-/$1\\-/g;
- # replace single quotes
- $d =~ s/\'/\\(aq/g;
- # handle double quotes first on the line
- $d =~ s/^(\s*)\"/$1\\(dq/;
print $d;
}
- if($exam) {
- print ".fi\n"; # fill-in
- }
}
sub seealso {
@@ -194,9 +156,173 @@ sub added {
}
}
+sub render {
+ my ($fh, $f, $line) = @_;
+ my @desc;
+ my $tablemode = 0;
+ my $header = 0;
+ # if $top is TRUE, it means a top-level page and not a command line option
+ my $top = ($line == 1);
+ my $quote;
+ $start = 0;
+
+ while(<$fh>) {
+ my $d = $_;
+ $line++;
+ if($d =~ /^\.(SH|BR|IP|B)/) {
+ print STDERR "$f:$line:1:ERROR: nroff instruction in input: \".$1\"\n";
+ return 4;
+ }
+ if(/^ *<!--/) {
+ # skip comments
+ next;
+ }
+ if((!$start) && ($_ =~ /^[\r\n]*\z/)) {
+ # skip leading blank lines
+ next;
+ }
+ $start = 1;
+ if(/^# (.*)/) {
+ $header = 1;
+ if($top != 1) {
+ # ignored for command line options
+ $blankline++;
+ next;
+ }
+ push @desc, ".SH $1\n";
+ next;
+ }
+ elsif(/^###/) {
+ print STDERR "$f:$line:1:ERROR: ### header is not supported\n";
+ exit 3;
+ }
+ elsif(/^## (.*)/) {
+ my $word = $1;
+ # if there are enclosing quotes, remove them first
+ $word =~ s/[\"\'](.*)[\"\']\z/$1/;
+
+ # remove backticks from headers
+ $words =~ s/\`//g;
+
+ # if there is a space, it needs quotes
+ if($word =~ / /) {
+ $word = "\"$word\"";
+ }
+ if($top == 1) {
+ push @desc, ".IP $word\n";
+ }
+ else {
+ if(!$tablemode) {
+ push @desc, ".RS\n";
+ $tablemode = 1;
+ }
+ push @desc, ".IP $word\n";
+ }
+ $header = 1;
+ next;
+ }
+ elsif(/^##/) {
+ if($top == 1) {
+ print STDERR "$f:$line:1:ERROR: ## empty header top-level mode\n";
+ exit 3;
+ }
+ if($tablemode) {
+ # end of table
+ push @desc, ".RE\n.IP\n";
+ $tablmode = 0;
+ }
+ $header = 1;
+ next;
+ }
+ elsif(/^\.(IP|RS|RE)/) {
+ my ($cmd) = ($1);
+ print STDERR "$f:$line:1:ERROR: $cmd detected, use ##-style\n";
+ return 3;
+ }
+ elsif(/^[ \t]*\n/) {
+ # count and ignore blank lines
+ $blankline++;
+ next;
+ }
+ elsif($d =~ /^ (.*)/) {
+ my $word = $1;
+ if(!$quote) {
+ push @desc, ".nf\n";
+ }
+ $quote = 1;
+ $d = "$word\n";
+ }
+ elsif($quote && ($d !~ /^ (.*)/)) {
+ # end of quote
+ push @desc, ".fi\n";
+ $quote = 0;
+ }
+
+ $d =~ s/`%DATE`/$date/g;
+ $d =~ s/`%VERSION`/$version/g;
+ $d =~ s/`%GLOBALS`/$globals/g;
+
+ # convert single backslahes to doubles
+ $d =~ s/\\/\\\\/g;
+
+ # convert backticks to double quotes
+ $d =~ s/\`/\"/g;
+
+ if(!$quote && $d =~ /--/) {
+ # scan for options in longest-names first order
+ for my $k (sort {length($b) <=> length($a)} keys %optlong) {
+ # --tlsv1 is complicated since --tlsv1.2 etc are also
+ # acceptable options!
+ if(($k eq "tlsv1") && ($d =~ /--tlsv1\.[0-9]\\f/)) {
+ next;
+ }
+ my $l = manpageify($k);
+ $d =~ s/\-\-$k([^a-z0-9-])/$l$1/g;
+ }
+ }
+
+ if($d =~ /\(Added in ([0-9.]+)\)/i) {
+ my $ver = $1;
+ if(too_old($ver)) {
+ $d =~ s/ *\(Added in $ver\)//gi;
+ }
+ }
+
+ if(!$quote && ($d =~ /^(.*) /)) {
+ printf STDERR "$f:$line:%d:ERROR: 2 spaces detected\n",
+ length($1);
+ return 3;
+ }
+ # quote minuses in the output
+ $d =~ s/([^\\])-/$1\\-/g;
+ # replace single quotes
+ $d =~ s/\'/\\(aq/g;
+ # handle double quotes or periods first on the line
+ $d =~ s/^([\.\"])/\\&$1/;
+ # **bold**
+ $d =~ s/\*\*(\S.*?)\*\*/\\fB$1\\fP/g;
+ # *italics*
+ $d =~ s/\*(\S.*?)\*/\\fI$1\\fP/g;
+
+ # trim trailing spaces
+ $d =~ s/[ \t]+\z//;
+ push @desc, "\n" if($blankline && !$header);
+ $blankline = 0;
+ push @desc, $d;
+ $header = 0;
+
+ }
+ if($tablemode) {
+ # end of table
+ push @desc, ".RE\n.IP\n";
+ }
+ return @desc;
+}
+
sub single {
my ($f, $standalone)=@_;
- open(F, "<:crlf", "$f") ||
+ my $fh;
+ open($fh, "<:crlf", "$f") ||
return 1;
my $short;
my $long;
@@ -207,17 +333,29 @@ sub single {
my $mutexed;
my $requires;
my $category;
- my $seealso;
+ my @seealso;
my $copyright;
my $spdx;
my @examples; # there can be more than one
my $magic; # cmdline special option
my $line;
+ my $dline;
my $multi;
my $scope;
my $experimental;
- while(<F>) {
+ my $start;
+ my $list; # identifies the list, 1 example, 2 see-also
+ while(<$fh>) {
$line++;
+ if(/^ *<!--/) {
+ next;
+ }
+ if(!$start) {
+ if(/^---/) {
+ $start = 1;
+ }
+ next;
+ }
if(/^Short: *(.)/i) {
$short=$1;
}
@@ -242,12 +380,18 @@ sub single {
elsif(/^Protocols: *(.*)/i) {
$protocols=$1;
}
- elsif(/^See-also: *(.*)/i) {
+ elsif(/^See-also: +(.+)/i) {
if($seealso) {
print STDERR "ERROR: duplicated See-also in $f\n";
return 1;
}
- $seealso=$1;
+ push @seealso, $1;
+ }
+ elsif(/^See-also:/i) {
+ $list=2;
+ }
+ elsif(/^ *- (.*)/i && ($list == 2)) {
+ push @seealso, $1;
}
elsif(/^Requires: *(.*)/i) {
$requires=$1;
@@ -255,7 +399,14 @@ sub single {
elsif(/^Category: *(.*)/i) {
$category=$1;
}
- elsif(/^Example: *(.*)/i) {
+ elsif(/^Example: +(.+)/i) {
+ push @examples, $1;
+ }
+ elsif(/^Example:/i) {
+ # '1' is the example list
+ $list = 1;
+ }
+ elsif(/^ *- (.*)/i && ($list == 1)) {
push @examples, $1;
}
elsif(/^Multi: *(.*)/i) {
@@ -277,6 +428,7 @@ sub single {
;
}
elsif(/^---/) {
+ $start++;
if(!$long) {
print STDERR "ERROR: no 'Long:' in $f\n";
return 1;
@@ -293,7 +445,7 @@ sub single {
print STDERR "$f:$line:1:ERROR: no 'Added:' version present\n";
return 2;
}
- if(!$seealso) {
+ if(!$seealso[0]) {
print STDERR "$f:$line:1:ERROR: no 'See-also:' field present\n";
return 2;
}
@@ -309,14 +461,21 @@ sub single {
}
else {
chomp;
- print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
+ print STDERR "$f:$line:1:WARN: unrecognized line in $f, ignoring:\n:'$_';"
}
}
- my @desc;
- while(<F>) {
- push @desc, $_;
+
+ if($start < 2) {
+ print STDERR "$f:1:1:ERROR: no proper meta-data header\n";
+ return 2;
+ }
+
+ my @desc = render($fh, $f, $line);
+ close($fh);
+ if($tablemode) {
+ # end of table
+ push @desc, ".RE\n.IP\n";
}
- close(F);
my $opt;
if(defined($short) && $long) {
@@ -403,30 +562,28 @@ sub single {
printdesc(@extra);
my @foot;
- if($seealso) {
- my @m=split(/ /, $seealso);
- my $mstr;
- my $and = 0;
- my $num = scalar(@m);
- if($num > 2) {
- # use commas up to this point
- $and = $num - 1;
+
+ my $mstr;
+ my $and = 0;
+ my $num = scalar(@seealso);
+ if($num > 2) {
+ # use commas up to this point
+ $and = $num - 1;
+ }
+ my $i = 0;
+ for my $k (@seealso) {
+ if(!$helplong{$k}) {
+ print STDERR "$f:$line:1:WARN: see-also a non-existing option: $k\n";
}
- my $i = 0;
- for my $k (@m) {
- if(!$helplong{$k}) {
- print STDERR "$f:$line:1:WARN: see-also a non-existing option: $k\n";
- }
- my $l = manpageify($k);
- my $sep = " and";
- if($and && ($i < $and)) {
- $sep = ",";
- }
- $mstr .= sprintf "%s$l", $mstr?"$sep ":"";
- $i++;
+ my $l = manpageify($k);
+ my $sep = " and";
+ if($and && ($i < $and)) {
+ $sep = ",";
}
- push @foot, seealso($standalone, $mstr);
+ $mstr .= sprintf "%s$l", $mstr?"$sep ":"";
+ $i++;
}
+ push @foot, seealso($standalone, $mstr);
if($requires) {
my $l = manpageify($long);
@@ -452,8 +609,10 @@ sub single {
print "\nExample$s:\n.nf\n";
foreach my $e (@examples) {
$e =~ s!\$URL!https://example.com!g;
- $e =~ s/-/\\-/g;
- $e =~ s/\'/\\(aq/g;
+ #$e =~ s/-/\\-/g;
+ #$e =~ s/\'/\\(aq/g;
+ # convert single backslahes to doubles
+ $e =~ s/\\/\\\\/g;
print " curl $e\n";
}
print ".fi\n";
@@ -479,7 +638,14 @@ sub getshortlong {
my $arg;
my $protocols;
my $category;
+ my $start = 0;
while(<F>) {
+ if(!$start) {
+ if(/^---/) {
+ $start = 1;
+ }
+ next;
+ }
if(/^Short: (.)/i) {
$short=$1;
}
@@ -524,15 +690,10 @@ sub indexoptions {
sub header {
my ($f)=@_;
- open(F, "<:crlf", "$f");
- my @d;
- while(<F>) {
- s/%DATE/$date/g;
- s/%VERSION/$version/g;
- s/%GLOBALS/$globals/g;
- push @d, $_;
- }
- close(F);
+ my $fh;
+ open($fh, "<:crlf", "$f");
+ my @d = render($fh, $f, 1);
+ close($fh);
printdesc(@d);
}
@@ -566,10 +727,10 @@ sub listhelp {
/*
* DO NOT edit tool_listhelp.c manually.
- * This source file is generated with the following command:
-
- cd \$srcroot/docs/cmdline-opts
- ./gen.pl listhelp *.d > \$srcroot/src/tool_listhelp.c
+ * This source file is generated with the following command in an autotools
+ * build:
+ *
+ * "make listhelp"
*/
const struct helptxt helptext[] = {
@@ -648,7 +809,17 @@ sub listglobals {
open(F, "<:crlf", "$f") ||
next;
my $long;
+ my $start = 0;
while(<F>) {
+ if(/^---/) {
+ if(!$start) {
+ $start = 1;
+ next;
+ }
+ else {
+ last;
+ }
+ }
if(/^Long: *(.*)/i) {
$long=$1;
}
@@ -656,9 +827,6 @@ sub listglobals {
push @globalopts, $long;
last;
}
- elsif(/^---/) {
- last;
- }
}
close(F);
}
@@ -669,20 +837,73 @@ sub listglobals {
}
}
+sub noext {
+ my $in = $_[0];
+ $in =~ s/\.d//;
+ return $in;
+}
+
+sub sortnames {
+ return noext($a) cmp noext($b);
+}
+
sub mainpage {
my (@files) = @_;
my $ret;
- # show the page header
- header("page-header");
+ my $fh;
+ open($fh, "<:crlf", "mainpage.idx") ||
+ return 1;
- # output docs for all options
- foreach my $f (sort @files) {
- $ret += single($f, 0);
- }
+ print <<HEADER
+.\\" **************************************************************************
+.\\" * _ _ ____ _
+.\\" * Project ___| | | | _ \\| |
+.\\" * / __| | | | |_) | |
+.\\" * | (__| |_| | _ <| |___
+.\\" * \\___|\\___/|_| \\_\\_____|
+.\\" *
+.\\" * Copyright (C) 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.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.
+.\\" *
+.\\" * SPDX-License-Identifier: curl
+.\\" *
+.\\" **************************************************************************
+.\\"
+.\\" DO NOT EDIT. Generated by the curl project gen.pl man page generator.
+.\\"
+.TH curl 1 "$date" "curl $version" "curl Manual"
+HEADER
+ ;
- if(!$ret) {
- header("page-footer");
+ while(<$fh>) {
+ my $f = $_;
+ chomp $f;
+ if($f =~ /^#/) {
+ # stardard comment
+ next;
+ }
+ if(/^%options/) {
+ # output docs for all options
+ foreach my $f (sort sortnames @files) {
+ $ret += single($f, 0);
+ }
+ }
+ else {
+ # render the file
+ header($f);
+ }
}
+ close($fh);
exit $ret if($ret);
}
diff --git a/docs/cmdline-opts/get.d b/docs/cmdline-opts/get.d
deleted file mode 100644
index 2e03a255b..000000000
--- a/docs/cmdline-opts/get.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: get
-Short: G
-Help: Put the post data in the URL and use GET
-Category: http upload
-Example: --get $URL
-Example: --get -d "tool=curl" -d "age=old" $URL
-Example: --get -I -d "tool=curl" $URL
-Added: 7.8.1
-See-also: data request
-Multi: boolean
----
-When used, this option makes all data specified with --data, --data-binary
-or --data-urlencode to be used in an HTTP GET request instead of the POST
-request that otherwise would be used. The data is appended to the URL
-with a '?' separator.
-
-If used in combination with --head, the POST data is instead appended to the
-URL with a HEAD request.
diff --git a/docs/cmdline-opts/get.md b/docs/cmdline-opts/get.md
new file mode 100644
index 000000000..f8c8cf2f9
--- /dev/null
+++ b/docs/cmdline-opts/get.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: get
+Short: G
+Help: Put the post data in the URL and use GET
+Protocols: HTTP
+Category: http upload
+Added: 7.8.1
+Multi: boolean
+See-also:
+ - data
+ - request
+Example:
+ - --get $URL
+ - --get -d "tool=curl" -d "age=old" $URL
+ - --get -I -d "tool=curl" $URL
+---
+
+# `--get`
+
+When used, this option makes all data specified with --data, --data-binary
+or --data-urlencode to be used in an HTTP GET request instead of the POST
+request that otherwise would be used. The data is appended to the URL
+with a '?' separator.
+
+If used in combination with --head, the POST data is instead appended to the
+URL with a HEAD request.
diff --git a/docs/cmdline-opts/globoff.d b/docs/cmdline-opts/globoff.d
deleted file mode 100644
index 53bed6ec8..000000000
--- a/docs/cmdline-opts/globoff.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: globoff
-Short: g
-Help: Disable URL sequences and ranges using {} and []
-Category: curl
-Example: -g "https://example.com/{[]}}}}"
-Added: 7.6
-See-also: config disable
-Multi: boolean
----
-This option switches off the "URL globbing parser". When you set this option,
-you can specify URLs that contain the letters {}[] without having curl itself
-interpret them. Note that these letters are not normal legal URL contents but
-they should be encoded according to the URI standard.
diff --git a/docs/cmdline-opts/globoff.md b/docs/cmdline-opts/globoff.md
new file mode 100644
index 000000000..dc3fc2ef8
--- /dev/null
+++ b/docs/cmdline-opts/globoff.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: globoff
+Short: g
+Help: Disable URL sequences and ranges using {} and []
+Category: curl
+Added: 7.6
+Multi: boolean
+See-also:
+ - config
+ - disable
+Example:
+ - -g "https://example.com/{[]}}}}"
+---
+
+# `--globoff`
+
+This option switches off the "URL globbing parser". When you set this option,
+you can specify URLs that contain the letters {}[] without having curl itself
+interpret them. Note that these letters are not normal legal URL contents but
+they should be encoded according to the URI standard.
diff --git a/docs/cmdline-opts/happy-eyeballs-timeout-ms.d b/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
deleted file mode 100644
index 29114e209..000000000
--- a/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: happy-eyeballs-timeout-ms
-Arg: <milliseconds>
-Help: Time for IPv6 before trying IPv4
-Added: 7.59.0
-Category: connection
-Example: --happy-eyeballs-timeout-ms 500 $URL
-See-also: max-time connect-timeout
-Multi: single
----
-Happy Eyeballs is an algorithm that attempts to connect to both IPv4 and IPv6
-addresses for dual-stack hosts, giving IPv6 a head-start of the specified
-number of milliseconds. If the IPv6 address cannot be connected to within that
-time, then a connection attempt is made to the IPv4 address in parallel. The
-first connection to be established is the one that is used.
-
-The range of suggested useful values is limited. Happy Eyeballs RFC 6555 says
-"It is RECOMMENDED that connection attempts be paced 150-250 ms apart to
-balance human factors against network load." libcurl currently defaults to
-200 ms. Firefox and Chrome currently default to 300 ms.
diff --git a/docs/cmdline-opts/happy-eyeballs-timeout-ms.md b/docs/cmdline-opts/happy-eyeballs-timeout-ms.md
new file mode 100644
index 000000000..0ee2cd727
--- /dev/null
+++ b/docs/cmdline-opts/happy-eyeballs-timeout-ms.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: happy-eyeballs-timeout-ms
+Arg: <milliseconds>
+Help: Time for IPv6 before trying IPv4
+Added: 7.59.0
+Category: connection
+Multi: single
+See-also:
+ - max-time
+ - connect-timeout
+Example:
+ - --happy-eyeballs-timeout-ms 500 $URL
+---
+
+# `--happy-eyeballs-timeout-ms`
+
+Happy Eyeballs is an algorithm that attempts to connect to both IPv4 and IPv6
+addresses for dual-stack hosts, giving IPv6 a head-start of the specified
+number of milliseconds. If the IPv6 address cannot be connected to within that
+time, then a connection attempt is made to the IPv4 address in parallel. The
+first connection to be established is the one that is used.
+
+The range of suggested useful values is limited. Happy Eyeballs RFC 6555 says
+"It is RECOMMENDED that connection attempts be paced 150-250 ms apart to
+balance human factors against network load." libcurl currently defaults to
+200 ms. Firefox and Chrome currently default to 300 ms.
diff --git a/docs/cmdline-opts/haproxy-clientip.d b/docs/cmdline-opts/haproxy-clientip.d
deleted file mode 100644
index 25cb7e623..000000000
--- a/docs/cmdline-opts/haproxy-clientip.d
+++ /dev/null
@@ -1,29 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: haproxy-clientip
-Help: Sets client IP in HAProxy PROXY protocol v1 header
-Protocols: HTTP
-Added: 8.2.0
-Category: http proxy
-Example: --haproxy-clientip $IP
-See-also: proxy
-Multi: single
----
-Sets a client IP in HAProxy PROXY protocol v1 header at the beginning of the
-connection.
-
-For valid requests, IPv4 addresses must be indicated as a series of exactly
-4 integers in the range [0..255] inclusive written in decimal representation
-separated by exactly one dot between each other. Heading zeroes are not
-permitted in front of numbers in order to avoid any possible confusion
-with octal numbers. IPv6 addresses must be indicated as series of 4 hexadecimal
-digits (upper or lower case) delimited by colons between each other, with the
-acceptance of one double colon sequence to replace the largest acceptable range
-of consecutive zeroes. The total number of decoded bits must exactly be 128.
-
-Otherwise, any string can be accepted for the client IP and get sent.
-
-It replaces --haproxy-protocol if used, it is not necessary to specify both flags.
-
-This option is primarily useful when sending test requests to
-verify a service is working as intended.
diff --git a/docs/cmdline-opts/haproxy-clientip.md b/docs/cmdline-opts/haproxy-clientip.md
new file mode 100644
index 000000000..470d556f0
--- /dev/null
+++ b/docs/cmdline-opts/haproxy-clientip.md
@@ -0,0 +1,33 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: haproxy-clientip
+Arg: <IP address>
+Help: Sets client IP in HAProxy PROXY protocol v1 header
+Protocols: HTTP
+Added: 8.2.0
+Category: http proxy
+Multi: single
+See-also:
+ - proxy
+Example:
+ - --haproxy-clientip $IP
+---
+
+# `--haproxy-clientip`
+
+Sets a client IP in HAProxy PROXY protocol v1 header at the beginning of the
+connection.
+
+For valid requests, IPv4 addresses must be indicated as a series of exactly
+4 integers in the range [0..255] inclusive written in decimal representation
+separated by exactly one dot between each other. Heading zeroes are not
+permitted in front of numbers in order to avoid any possible confusion
+with octal numbers. IPv6 addresses must be indicated as series of 4 hexadecimal
+digits (upper or lower case) delimited by colons between each other, with the
+acceptance of one double colon sequence to replace the largest acceptable range
+of consecutive zeroes. The total number of decoded bits must exactly be 128.
+
+Otherwise, any string can be accepted for the client IP and get sent.
+
+It replaces --haproxy-protocol if used, it is not necessary to specify both flags.
diff --git a/docs/cmdline-opts/haproxy-protocol.d b/docs/cmdline-opts/haproxy-protocol.d
deleted file mode 100644
index 34119062e..000000000
--- a/docs/cmdline-opts/haproxy-protocol.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: haproxy-protocol
-Help: Send HAProxy PROXY protocol v1 header
-Protocols: HTTP
-Added: 7.60.0
-Category: http proxy
-Example: --haproxy-protocol $URL
-See-also: proxy
-Multi: boolean
----
-Send a HAProxy PROXY protocol v1 header at the beginning of the
-connection. This is used by some load balancers and reverse proxies to
-indicate the client's true IP address and port.
-
-This option is primarily useful when sending test requests to a service that
-expects this header.
diff --git a/docs/cmdline-opts/haproxy-protocol.md b/docs/cmdline-opts/haproxy-protocol.md
new file mode 100644
index 000000000..0170039cd
--- /dev/null
+++ b/docs/cmdline-opts/haproxy-protocol.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: haproxy-protocol
+Help: Send HAProxy PROXY protocol v1 header
+Protocols: HTTP
+Added: 7.60.0
+Category: http proxy
+Multi: boolean
+See-also:
+ - proxy
+Example:
+ - --haproxy-protocol $URL
+---
+
+# `--haproxy-protocol`
+
+Send a HAProxy PROXY protocol v1 header at the beginning of the
+connection. This is used by some load balancers and reverse proxies to
+indicate the client's true IP address and port.
+
+This option is primarily useful when sending test requests to a service that
+expects this header.
diff --git a/docs/cmdline-opts/head.d b/docs/cmdline-opts/head.d
deleted file mode 100644
index bb748b72e..000000000
--- a/docs/cmdline-opts/head.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: head
-Short: I
-Help: Show document info only
-Protocols: HTTP FTP FILE
-Category: http ftp file
-Example: -I $URL
-Added: 4.0
-See-also: get verbose trace-ascii
-Multi: boolean
----
-Fetch the headers only! HTTP-servers feature the command HEAD which this uses
-to get nothing but the header of a document. When used on an FTP or FILE file,
-curl displays the file size and last modification time only.
diff --git a/docs/cmdline-opts/head.md b/docs/cmdline-opts/head.md
new file mode 100644
index 000000000..be4dbb87f
--- /dev/null
+++ b/docs/cmdline-opts/head.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: head
+Short: I
+Help: Show document info only
+Protocols: HTTP FTP FILE
+Category: http ftp file
+Added: 4.0
+Multi: boolean
+See-also:
+ - get
+ - verbose
+ - trace-ascii
+Example:
+ - -I $URL
+---
+
+# `--head`
+
+Fetch the headers only! HTTP-servers feature the command HEAD which this uses
+to get nothing but the header of a document. When used on an FTP or FILE file,
+curl displays the file size and last modification time only.
diff --git a/docs/cmdline-opts/header.d b/docs/cmdline-opts/header.d
deleted file mode 100644
index f5b768552..000000000
--- a/docs/cmdline-opts/header.d
+++ /dev/null
@@ -1,56 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: header
-Short: H
-Arg: <header/@file>
-Help: Pass custom header(s) to server
-Protocols: HTTP IMAP SMTP
-Category: http imap smtp
-See-also: user-agent referer
-Example: -H "X-First-Name: Joe" $URL
-Example: -H "User-Agent: yes-please/2000" $URL
-Example: -H "Host:" $URL
-Example: -H @headers.txt $URL
-Added: 5.0
-Multi: append
----
-Extra header to include in information sent. When used within an HTTP request,
-it is added to the regular request headers.
-
-For an IMAP or SMTP MIME uploaded mail built with --form options, it is
-prepended to the resulting MIME document, effectively including it at the mail
-global level. It does not affect raw uploaded mails (Added in 7.56.0).
-
-You may specify any number of extra headers. Note that if you should add a
-custom header that has the same name as one of the internal ones curl would
-use, your externally set header is used instead of the internal one. This
-allows you to make even trickier stuff than curl would normally do. You should
-not replace internally set headers without knowing perfectly well what you are
-doing. Remove an internal header by giving a replacement without content on
-the right side of the colon, as in: -H "Host:". If you send the custom header
-with no-value then its header must be terminated with a semicolon, such as \-H
-"X-Custom-Header;" to send "X-Custom-Header:".
-
-curl makes sure that each header you add/replace is sent with the proper
-end-of-line marker, you should thus **not** add that as a part of the header
-content: do not add newlines or carriage returns, they only mess things up for
-you.
-
-This option can take an argument in @filename style, which then adds a header
-for each line in the input file. Using @- makes curl read the header file from
-stdin. Added in 7.55.0.
-
-Please note that most anti-spam utilities check the presence and value of
-several MIME mail headers: these are "From:", "To:", "Date:" and "Subject:"
-among others and should be added with this option.
-
-You need --proxy-header to send custom headers intended for an HTTP
-proxy. Added in 7.37.0.
-
-Passing on a "Transfer-Encoding: chunked" header when doing an HTTP request
-with a request body, makes curl send the data using chunked encoding.
-
-**WARNING**: headers set with this option are set in all HTTP requests - even
-after redirects are followed, like when told with --location. This can lead to
-the header being sent to other hosts than the original host, so sensitive
-headers should be used with caution combined with following redirects.
diff --git a/docs/cmdline-opts/header.md b/docs/cmdline-opts/header.md
new file mode 100644
index 000000000..835ee61c8
--- /dev/null
+++ b/docs/cmdline-opts/header.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: header
+Short: H
+Arg: <header/@file>
+Help: Pass custom header(s) to server
+Protocols: HTTP IMAP SMTP
+Category: http imap smtp
+Added: 5.0
+Multi: append
+See-also:
+ - user-agent
+ - referer
+Example:
+ - -H "X-First-Name: Joe" $URL
+ - -H "User-Agent: yes-please/2000" $URL
+ - -H "Host:" $URL
+ - -H @headers.txt $URL
+---
+
+# `--header`
+
+Extra header to include in information sent. When used within an HTTP request,
+it is added to the regular request headers.
+
+For an IMAP or SMTP MIME uploaded mail built with --form options, it is
+prepended to the resulting MIME document, effectively including it at the mail
+global level. It does not affect raw uploaded mails (Added in 7.56.0).
+
+You may specify any number of extra headers. Note that if you should add a
+custom header that has the same name as one of the internal ones curl would
+use, your externally set header is used instead of the internal one. This
+allows you to make even trickier stuff than curl would normally do. You should
+not replace internally set headers without knowing perfectly well what you are
+doing. Remove an internal header by giving a replacement without content on
+the right side of the colon, as in: -H "Host:". If you send the custom header
+with no-value then its header must be terminated with a semicolon, such as \-H
+"X-Custom-Header;" to send "X-Custom-Header:".
+
+curl makes sure that each header you add/replace is sent with the proper
+end-of-line marker, you should thus **not** add that as a part of the header
+content: do not add newlines or carriage returns, they only mess things up for
+you. curl passes on the verbatim string you give it without any filter or
+other safe guards. That includes white space and control characters.
+
+This option can take an argument in @filename style, which then adds a header
+for each line in the input file. Using @- makes curl read the header file from
+stdin. Added in 7.55.0.
+
+Please note that most anti-spam utilities check the presence and value of
+several MIME mail headers: these are "From:", "To:", "Date:" and "Subject:"
+among others and should be added with this option.
+
+You need --proxy-header to send custom headers intended for an HTTP
+proxy. Added in 7.37.0.
+
+Passing on a "Transfer-Encoding: chunked" header when doing an HTTP request
+with a request body, makes curl send the data using chunked encoding.
+
+**WARNING**: headers set with this option are set in all HTTP requests - even
+after redirects are followed, like when told with --location. This can lead to
+the header being sent to other hosts than the original host, so sensitive
+headers should be used with caution combined with following redirects.
diff --git a/docs/cmdline-opts/help.d b/docs/cmdline-opts/help.d
deleted file mode 100644
index f8675e484..000000000
--- a/docs/cmdline-opts/help.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: help
-Arg: <category>
-Short: h
-Help: Get help for commands
-Category: important curl
-Example: --help all
-Added: 4.0
-See-also: verbose
-Multi: custom
----
-Usage help. This lists all curl command line options within the given
-**category**.
-
-If no argument is provided, curl displays only the most important command line
-arguments.
-
-For category **all**, curl displays help for all options.
-
-If **category** is specified, curl displays all available help categories.
diff --git a/docs/cmdline-opts/help.md b/docs/cmdline-opts/help.md
new file mode 100644
index 000000000..6ef812d3d
--- /dev/null
+++ b/docs/cmdline-opts/help.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: help
+Arg: <category>
+Short: h
+Help: Get help for commands
+Category: important curl
+Added: 4.0
+Multi: custom
+See-also:
+ - verbose
+Example:
+ - --help all
+---
+
+# `--help`
+
+Usage help. This lists all curl command line options within the given
+**category**.
+
+If no argument is provided, curl displays only the most important command line
+arguments.
+
+For category **all**, curl displays help for all options.
+
+If **category** is specified, curl displays all available help categories.
diff --git a/docs/cmdline-opts/hostpubmd5.d b/docs/cmdline-opts/hostpubmd5.d
deleted file mode 100644
index e9db23db0..000000000
--- a/docs/cmdline-opts/hostpubmd5.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: hostpubmd5
-Arg: <md5>
-Help: Acceptable MD5 hash of the host public key
-Protocols: SFTP SCP
-Added: 7.17.1
-Category: sftp scp
-Example: --hostpubmd5 e5c1c49020640a5ab0f2034854c321a8 sftp://example.com/
-See-also: hostpubsha256
-Multi: single
----
-Pass a string containing 32 hexadecimal digits. The string should
-be the 128 bit MD5 checksum of the remote host's public key, curl refuses
-the connection with the host unless the md5sums match.
diff --git a/docs/cmdline-opts/hostpubmd5.md b/docs/cmdline-opts/hostpubmd5.md
new file mode 100644
index 000000000..15add357d
--- /dev/null
+++ b/docs/cmdline-opts/hostpubmd5.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: hostpubmd5
+Arg: <md5>
+Help: Acceptable MD5 hash of the host public key
+Protocols: SFTP SCP
+Added: 7.17.1
+Category: sftp scp
+Multi: single
+See-also:
+ - hostpubsha256
+Example:
+ - --hostpubmd5 e5c1c49020640a5ab0f2034854c321a8 sftp://example.com/
+---
+
+# `--hostpubmd5`
+
+Pass a string containing 32 hexadecimal digits. The string should be the 128
+bit **MD5** checksum of the remote host's public key, curl refuses the
+connection with the host unless the checksums match.
diff --git a/docs/cmdline-opts/hostpubsha256.d b/docs/cmdline-opts/hostpubsha256.d
deleted file mode 100644
index b33f338bd..000000000
--- a/docs/cmdline-opts/hostpubsha256.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: hostpubsha256
-Arg: <sha256>
-Help: Acceptable SHA256 hash of the host public key
-Protocols: SFTP SCP
-Added: 7.80.0
-Category: sftp scp
-Example: --hostpubsha256 NDVkMTQxMGQ1ODdmMjQ3MjczYjAyOTY5MmRkMjVmNDQ= sftp://example.com/
-See-also: hostpubmd5
-Multi: single
----
-Pass a string containing a Base64-encoded SHA256 hash of the remote host's
-public key. Curl refuses the connection with the host unless the hashes match.
-
-This feature requires libcurl to be built with libssh2 and does not work with
-other SSH backends.
diff --git a/docs/cmdline-opts/hostpubsha256.md b/docs/cmdline-opts/hostpubsha256.md
new file mode 100644
index 000000000..b1faaf869
--- /dev/null
+++ b/docs/cmdline-opts/hostpubsha256.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: hostpubsha256
+Arg: <sha256>
+Help: Acceptable SHA256 hash of the host public key
+Protocols: SFTP SCP
+Added: 7.80.0
+Category: sftp scp
+Multi: single
+See-also:
+ - hostpubmd5
+Example:
+ - --hostpubsha256 NDVkMTQxMGQ1ODdmMjQ3MjczYjAyOTY5MmRkMjVmNDQ= sftp://example.com/
+---
+
+# `--hostpubsha256`
+
+Pass a string containing a Base64-encoded SHA256 hash of the remote host's
+public key. Curl refuses the connection with the host unless the hashes match.
+
+This feature requires libcurl to be built with libssh2 and does not work with
+other SSH backends.
diff --git a/docs/cmdline-opts/hsts.d b/docs/cmdline-opts/hsts.d
deleted file mode 100644
index e30d3b419..000000000
--- a/docs/cmdline-opts/hsts.d
+++ /dev/null
@@ -1,26 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: hsts
-Arg: <file name>
-Protocols: HTTPS
-Help: Enable HSTS with this cache file
-Added: 7.74.0
-Category: http
-Example: --hsts cache.txt $URL
-See-also: proto
-Multi: append
----
-This option enables HSTS for the transfer. If the file name points to an
-existing HSTS cache file, that is used. After a completed transfer, the
-cache is saved to the file name again if it has been modified.
-
-If curl is told to use HTTP:// for a transfer involving a host name that
-exists in the HSTS cache, it upgrades the transfer to use HTTPS. Each HSTS
-cache entry has an individual life time after which the upgrade is no longer
-performed.
-
-Specify a "" file name (zero length) to avoid loading/saving and make curl
-just handle HSTS in memory.
-
-If this option is used several times, curl loads contents from all the
-files but the last one is used for saving.
diff --git a/docs/cmdline-opts/hsts.md b/docs/cmdline-opts/hsts.md
new file mode 100644
index 000000000..82b61959a
--- /dev/null
+++ b/docs/cmdline-opts/hsts.md
@@ -0,0 +1,32 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: hsts
+Arg: <file name>
+Protocols: HTTPS
+Help: Enable HSTS with this cache file
+Added: 7.74.0
+Category: http
+Multi: append
+See-also:
+ - proto
+Example:
+ - --hsts cache.txt $URL
+---
+
+# `--hsts`
+
+This option enables HSTS for the transfer. If the file name points to an
+existing HSTS cache file, that is used. After a completed transfer, the
+cache is saved to the file name again if it has been modified.
+
+If curl is told to use HTTP:// for a transfer involving a host name that
+exists in the HSTS cache, it upgrades the transfer to use HTTPS. Each HSTS
+cache entry has an individual life time after which the upgrade is no longer
+performed.
+
+Specify a "" file name (zero length) to avoid loading/saving and make curl
+just handle HSTS in memory.
+
+If this option is used several times, curl loads contents from all the
+files but the last one is used for saving.
diff --git a/docs/cmdline-opts/http0.9.d b/docs/cmdline-opts/http0.9.d
deleted file mode 100644
index 3dd14a05c..000000000
--- a/docs/cmdline-opts/http0.9.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: http0.9
-Tags: Versions
-Protocols: HTTP
-Help: Allow HTTP 0.9 responses
-Category: http
-Example: --http0.9 $URL
-Added: 7.64.0
-See-also: http1.1 http2 http3
-Multi: boolean
----
-Tells curl to be fine with HTTP version 0.9 response.
-
-HTTP/0.9 is a response without headers and therefore you can also connect with
-this to non-HTTP servers and still get a response since curl simply
-transparently downgrades - if allowed.
-
-HTTP/0.9 is disabled by default (added in 7.66.0)
diff --git a/docs/cmdline-opts/http0.9.md b/docs/cmdline-opts/http0.9.md
new file mode 100644
index 000000000..a28961641
--- /dev/null
+++ b/docs/cmdline-opts/http0.9.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: http0.9
+Tags: Versions
+Protocols: HTTP
+Help: Allow HTTP 0.9 responses
+Category: http
+Added: 7.64.0
+Multi: boolean
+See-also:
+ - http1.1
+ - http2
+ - http3
+Example:
+ - --http0.9 $URL
+---
+
+# `--http0.9`
+
+Tells curl to be fine with HTTP version 0.9 response.
+
+HTTP/0.9 is a response without headers and therefore you can also connect with
+this to non-HTTP servers and still get a response since curl simply
+transparently downgrades - if allowed.
+
+HTTP/0.9 is disabled by default (added in 7.66.0)
diff --git a/docs/cmdline-opts/http1.0.d b/docs/cmdline-opts/http1.0.d
deleted file mode 100644
index c5f4de872..000000000
--- a/docs/cmdline-opts/http1.0.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: 0
-Long: http1.0
-Tags: Versions
-Protocols: HTTP
-Added: 7.9.1
-Mutexed: http1.1 http2 http2-prior-knowledge http3
-Help: Use HTTP 1.0
-Category: http
-Example: --http1.0 $URL
-See-also: http0.9 http1.1
-Multi: mutex
----
-Tells curl to use HTTP version 1.0 instead of using its internally preferred
-HTTP version.
diff --git a/docs/cmdline-opts/http1.0.md b/docs/cmdline-opts/http1.0.md
new file mode 100644
index 000000000..fb7d907d8
--- /dev/null
+++ b/docs/cmdline-opts/http1.0.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: 0
+Long: http1.0
+Tags: Versions
+Protocols: HTTP
+Added: 7.9.1
+Mutexed: http1.1 http2 http2-prior-knowledge http3
+Help: Use HTTP 1.0
+Category: http
+Multi: mutex
+See-also:
+ - http0.9
+ - http1.1
+Example:
+ - --http1.0 $URL
+---
+
+# `--http1.0`
+
+Tells curl to use HTTP version 1.0 instead of using its internally preferred
+HTTP version.
diff --git a/docs/cmdline-opts/http1.1.d b/docs/cmdline-opts/http1.1.d
deleted file mode 100644
index 3057aed36..000000000
--- a/docs/cmdline-opts/http1.1.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: http1.1
-Tags: Versions
-Protocols: HTTP
-Added: 7.33.0
-Mutexed: http1.0 http2 http2-prior-knowledge http3
-Help: Use HTTP 1.1
-Category: http
-Example: --http1.1 $URL
-See-also: http1.0 http0.9
-Multi: mutex
----
-Tells curl to use HTTP version 1.1.
diff --git a/docs/cmdline-opts/http1.1.md b/docs/cmdline-opts/http1.1.md
new file mode 100644
index 000000000..3c4fe303a
--- /dev/null
+++ b/docs/cmdline-opts/http1.1.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: http1.1
+Tags: Versions
+Protocols: HTTP
+Added: 7.33.0
+Mutexed: http1.0 http2 http2-prior-knowledge http3
+Help: Use HTTP 1.1
+Category: http
+Multi: mutex
+See-also:
+ - http1.0
+ - http0.9
+Example:
+ - --http1.1 $URL
+---
+
+# `--http1.1`
+
+Tells curl to use HTTP version 1.1.
diff --git a/docs/cmdline-opts/http2-prior-knowledge.d b/docs/cmdline-opts/http2-prior-knowledge.d
deleted file mode 100644
index 7d7cabfd8..000000000
--- a/docs/cmdline-opts/http2-prior-knowledge.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: http2-prior-knowledge
-Tags: Versions
-Protocols: HTTP
-Added: 7.49.0
-Mutexed: http1.1 http1.0 http2 http3
-Requires: HTTP/2
-Help: Use HTTP 2 without HTTP/1.1 Upgrade
-Category: http
-Example: --http2-prior-knowledge $URL
-See-also: http2 http3
-Multi: boolean
----
-Tells curl to issue its non-TLS HTTP requests using HTTP/2 without HTTP/1.1
-Upgrade. It requires prior knowledge that the server supports HTTP/2 straight
-away. HTTPS requests still do HTTP/2 the standard way with negotiated protocol
-version in the TLS handshake.
diff --git a/docs/cmdline-opts/http2-prior-knowledge.md b/docs/cmdline-opts/http2-prior-knowledge.md
new file mode 100644
index 000000000..80a52141b
--- /dev/null
+++ b/docs/cmdline-opts/http2-prior-knowledge.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: http2-prior-knowledge
+Tags: Versions
+Protocols: HTTP
+Added: 7.49.0
+Mutexed: http1.1 http1.0 http2 http3
+Requires: HTTP/2
+Help: Use HTTP 2 without HTTP/1.1 Upgrade
+Category: http
+Multi: boolean
+See-also:
+ - http2
+ - http3
+Example:
+ - --http2-prior-knowledge $URL
+---
+
+# `--http2-prior-knowledge`
+
+Tells curl to issue its non-TLS HTTP requests using HTTP/2 without HTTP/1.1
+Upgrade. It requires prior knowledge that the server supports HTTP/2 straight
+away. HTTPS requests still do HTTP/2 the standard way with negotiated protocol
+version in the TLS handshake.
diff --git a/docs/cmdline-opts/http2.d b/docs/cmdline-opts/http2.d
deleted file mode 100644
index af5f3c4f5..000000000
--- a/docs/cmdline-opts/http2.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: http2
-Tags: Versions
-Protocols: HTTP
-Added: 7.33.0
-Mutexed: http1.1 http1.0 http2-prior-knowledge http3
-Requires: HTTP/2
-Help: Use HTTP/2
-See-also: http1.1 http3 no-alpn
-Category: http
-Example: --http2 $URL
-Multi: mutex
----
-Tells curl to use HTTP version 2.
-
-For HTTPS, this means curl negotiates HTTP/2 in the TLS handshake. curl does
-this by default.
-
-For HTTP, this means curl attempts to upgrade the request to HTTP/2 using the
-Upgrade: request header.
-
-When curl uses HTTP/2 over HTTPS, it does not itself insist on TLS 1.2 or
-higher even though that is required by the specification. A user can add this
-version requirement with --tlsv1.2.
diff --git a/docs/cmdline-opts/http2.md b/docs/cmdline-opts/http2.md
new file mode 100644
index 000000000..db4cf3462
--- /dev/null
+++ b/docs/cmdline-opts/http2.md
@@ -0,0 +1,33 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: http2
+Tags: Versions
+Protocols: HTTP
+Added: 7.33.0
+Mutexed: http1.1 http1.0 http2-prior-knowledge http3
+Requires: HTTP/2
+Help: Use HTTP/2
+Category: http
+Multi: mutex
+See-also:
+ - http1.1
+ - http3
+ - no-alpn
+Example:
+ - --http2 $URL
+---
+
+# `--http2`
+
+Tells curl to use HTTP version 2.
+
+For HTTPS, this means curl negotiates HTTP/2 in the TLS handshake. curl does
+this by default.
+
+For HTTP, this means curl attempts to upgrade the request to HTTP/2 using the
+Upgrade: request header.
+
+When curl uses HTTP/2 over HTTPS, it does not itself insist on TLS 1.2 or
+higher even though that is required by the specification. A user can add this
+version requirement with --tlsv1.2.
diff --git a/docs/cmdline-opts/http3-only.d b/docs/cmdline-opts/http3-only.d
deleted file mode 100644
index c3f0f31aa..000000000
--- a/docs/cmdline-opts/http3-only.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: http3-only
-Tags: Versions
-Protocols: HTTP
-Added: 7.88.0
-Mutexed: http1.1 http1.0 http2 http2-prior-knowledge http3
-Requires: HTTP/3
-Help: Use HTTP v3 only
-See-also: http1.1 http2 http3
-Category: http
-Example: --http3-only $URL
-Multi: mutex
-Experimental: yes
----
-Instructs curl to use HTTP/3 to the host in the URL, with no fallback to
-earlier HTTP versions. HTTP/3 can only be used for HTTPS and not for HTTP
-URLs. For HTTP, this option triggers an error.
-
-This option allows a user to avoid using the Alt-Svc method of upgrading to
-HTTP/3 when you know that the target speaks HTTP/3 on the given host and port.
-
-This option makes curl fail if a QUIC connection cannot be established, it
-does not attempt any other HTTP versions on its own. Use --http3 for similar
-functionality *with* a fallback.
diff --git a/docs/cmdline-opts/http3-only.md b/docs/cmdline-opts/http3-only.md
new file mode 100644
index 000000000..c565f8b95
--- /dev/null
+++ b/docs/cmdline-opts/http3-only.md
@@ -0,0 +1,32 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: http3-only
+Tags: Versions
+Protocols: HTTP
+Added: 7.88.0
+Mutexed: http1.1 http1.0 http2 http2-prior-knowledge http3
+Requires: HTTP/3
+Help: Use HTTP v3 only
+Category: http
+Multi: mutex
+See-also:
+ - http1.1
+ - http2
+ - http3
+Example:
+ - --http3-only $URL
+---
+
+# `--http3-only`
+
+Instructs curl to use HTTP/3 to the host in the URL, with no fallback to
+earlier HTTP versions. HTTP/3 can only be used for HTTPS and not for HTTP
+URLs. For HTTP, this option triggers an error.
+
+This option allows a user to avoid using the Alt-Svc method of upgrading to
+HTTP/3 when you know that the target speaks HTTP/3 on the given host and port.
+
+This option makes curl fail if a QUIC connection cannot be established, it
+does not attempt any other HTTP versions on its own. Use --http3 for similar
+functionality *with* a fallback.
diff --git a/docs/cmdline-opts/http3.d b/docs/cmdline-opts/http3.d
deleted file mode 100644
index a8258c4d3..000000000
--- a/docs/cmdline-opts/http3.d
+++ /dev/null
@@ -1,27 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: http3
-Tags: Versions
-Protocols: HTTP
-Added: 7.66.0
-Mutexed: http1.1 http1.0 http2 http2-prior-knowledge http3-only
-Requires: HTTP/3
-Help: Use HTTP v3
-See-also: http1.1 http2
-Category: http
-Example: --http3 $URL
-Multi: mutex
-Experimental: yes
----
-Tells curl to try HTTP/3 to the host in the URL, but fallback to earlier
-HTTP versions if the HTTP/3 connection establishment fails. HTTP/3 is only
-available for HTTPS and not for HTTP URLs.
-
-This option allows a user to avoid using the Alt-Svc method of upgrading to
-HTTP/3 when you know that the target speaks HTTP/3 on the given host and port.
-
-When asked to use HTTP/3, curl issues a separate attempt to use older HTTP
-versions with a slight delay, so if the HTTP/3 transfer fails or is slow, curl
-still tries to proceed with an older HTTP version.
-
-Use --http3-only for similar functionality *without* a fallback.
diff --git a/docs/cmdline-opts/http3.md b/docs/cmdline-opts/http3.md
new file mode 100644
index 000000000..d30c7bd90
--- /dev/null
+++ b/docs/cmdline-opts/http3.md
@@ -0,0 +1,33 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: http3
+Tags: Versions
+Protocols: HTTP
+Added: 7.66.0
+Mutexed: http1.1 http1.0 http2 http2-prior-knowledge http3-only
+Requires: HTTP/3
+Help: Use HTTP v3
+Category: http
+Multi: mutex
+See-also:
+ - http1.1
+ - http2
+Example:
+ - --http3 $URL
+---
+
+# `--http3`
+
+Tells curl to try HTTP/3 to the host in the URL, but fallback to earlier
+HTTP versions if the HTTP/3 connection establishment fails. HTTP/3 is only
+available for HTTPS and not for HTTP URLs.
+
+This option allows a user to avoid using the Alt-Svc method of upgrading to
+HTTP/3 when you know that the target speaks HTTP/3 on the given host and port.
+
+When asked to use HTTP/3, curl issues a separate attempt to use older HTTP
+versions with a slight delay, so if the HTTP/3 transfer fails or is slow, curl
+still tries to proceed with an older HTTP version.
+
+Use --http3-only for similar functionality *without* a fallback.
diff --git a/docs/cmdline-opts/ignore-content-length.d b/docs/cmdline-opts/ignore-content-length.d
deleted file mode 100644
index 505c04c18..000000000
--- a/docs/cmdline-opts/ignore-content-length.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ignore-content-length
-Help: Ignore the size of the remote resource
-Protocols: FTP HTTP
-Category: http ftp
-Example: --ignore-content-length $URL
-Added: 7.14.1
-See-also: ftp-skip-pasv-ip
-Multi: boolean
----
-For HTTP, Ignore the Content-Length header. This is particularly useful for
-servers running Apache 1.x, which reports incorrect Content-Length for
-files larger than 2 gigabytes.
-
-For FTP, this makes curl skip the SIZE command to figure out the size before
-downloading a file (added in 7.46.0).
-
-This option does not work for HTTP if libcurl was built to use hyper.
diff --git a/docs/cmdline-opts/ignore-content-length.md b/docs/cmdline-opts/ignore-content-length.md
new file mode 100644
index 000000000..b9f7522da
--- /dev/null
+++ b/docs/cmdline-opts/ignore-content-length.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ignore-content-length
+Help: Ignore the size of the remote resource
+Protocols: FTP HTTP
+Category: http ftp
+Added: 7.14.1
+Multi: boolean
+See-also:
+ - ftp-skip-pasv-ip
+Example:
+ - --ignore-content-length $URL
+---
+
+# `--ignore-content-length`
+
+For HTTP, Ignore the Content-Length header. This is particularly useful for
+servers running Apache 1.x, which reports incorrect Content-Length for
+files larger than 2 gigabytes.
+
+For FTP, this makes curl skip the SIZE command to figure out the size before
+downloading a file (added in 7.46.0).
+
+This option does not work for HTTP if libcurl was built to use hyper.
diff --git a/docs/cmdline-opts/include.d b/docs/cmdline-opts/include.d
deleted file mode 100644
index ce7b9d87b..000000000
--- a/docs/cmdline-opts/include.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: include
-Short: i
-Help: Include protocol response headers in the output
-See-also: verbose
-Category: important verbose
-Example: -i $URL
-Added: 4.8
-Multi: boolean
----
-Include the HTTP response headers in the output. The HTTP response headers can
-include things like server name, cookies, date of the document, HTTP version
-and more...
-
-To view the request headers, consider the --verbose option.
-
-Prior to 7.75.0 curl did not print the headers if --fail was used in
-combination with this option and there was error reported by server.
diff --git a/docs/cmdline-opts/include.md b/docs/cmdline-opts/include.md
new file mode 100644
index 000000000..aedf5da0b
--- /dev/null
+++ b/docs/cmdline-opts/include.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: include
+Short: i
+Help: Include protocol response headers in the output
+Protocols: HTTP FTP
+Category: important verbose
+Added: 4.8
+Multi: boolean
+See-also:
+ - verbose
+Example:
+ - -i $URL
+---
+
+# `--include`
+
+Include response headers in the output. HTTP response headers can include
+things like server name, cookies, date of the document, HTTP version and
+more... With non-HTTP protocols, the "headers" are other server communication.
+
+To view the request headers, consider the --verbose option.
+
+Prior to 7.75.0 curl did not print the headers if --fail was used in
+combination with this option and there was error reported by server.
diff --git a/docs/cmdline-opts/insecure.d b/docs/cmdline-opts/insecure.d
deleted file mode 100644
index e48d50002..000000000
--- a/docs/cmdline-opts/insecure.d
+++ /dev/null
@@ -1,33 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: insecure
-Short: k
-Help: Allow insecure server connections
-Protocols: TLS SFTP SCP
-See-also: proxy-insecure cacert capath
-Category: tls sftp scp
-Example: --insecure $URL
-Added: 7.10
-Multi: boolean
----
-By default, every secure connection curl makes is verified to be secure before
-the transfer takes place. This option makes curl skip the verification step
-and proceed without checking.
-
-When this option is not used for protocols using TLS, curl verifies the
-server's TLS certificate before it continues: that the certificate contains
-the right name which matches the host name used in the URL and that the
-certificate has been signed by a CA certificate present in the cert store.
-See this online resource for further details:
- https://curl.se/docs/sslcerts.html
-
-For SFTP and SCP, this option makes curl skip the *known_hosts* verification.
-*known_hosts* is a file normally stored in the user's home directory in the
-".ssh" subdirectory, which contains host names and their public keys.
-
-**WARNING**: using this option makes the transfer insecure.
-
-When curl uses secure protocols it trusts responses and allows for example
-HSTS and Alt-Svc information to be stored and used subsequently. Using
---insecure can make curl trust and use such information from malicious
-servers.
diff --git a/docs/cmdline-opts/insecure.md b/docs/cmdline-opts/insecure.md
new file mode 100644
index 000000000..1f5d048f7
--- /dev/null
+++ b/docs/cmdline-opts/insecure.md
@@ -0,0 +1,41 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: insecure
+Short: k
+Help: Allow insecure server connections
+Protocols: TLS SFTP SCP
+Category: tls sftp scp
+Added: 7.10
+Multi: boolean
+See-also:
+ - proxy-insecure
+ - cacert
+ - capath
+Example:
+ - --insecure $URL
+---
+
+# `--insecure`
+
+By default, every secure connection curl makes is verified to be secure before
+the transfer takes place. This option makes curl skip the verification step
+and proceed without checking.
+
+When this option is not used for protocols using TLS, curl verifies the
+server's TLS certificate before it continues: that the certificate contains
+the right name which matches the host name used in the URL and that the
+certificate has been signed by a CA certificate present in the cert store.
+See this online resource for further details:
+**https://curl.se/docs/sslcerts.html**
+
+For SFTP and SCP, this option makes curl skip the *known_hosts* verification.
+*known_hosts* is a file normally stored in the user's home directory in the
+".ssh" subdirectory, which contains host names and their public keys.
+
+**WARNING**: using this option makes the transfer insecure.
+
+When curl uses secure protocols it trusts responses and allows for example
+HSTS and Alt-Svc information to be stored and used subsequently. Using
+--insecure can make curl trust and use such information from malicious
+servers.
diff --git a/docs/cmdline-opts/interface.d b/docs/cmdline-opts/interface.d
deleted file mode 100644
index 026ceaef5..000000000
--- a/docs/cmdline-opts/interface.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: interface
-Arg: <name>
-Help: Use network INTERFACE (or address)
-See-also: dns-interface
-Category: connection
-Example: --interface eth0 $URL
-Added: 7.3
-Multi: single
----
-Perform an operation using a specified interface. You can enter interface
-name, IP address or host name. An example could look like:
-
- curl --interface eth0:1 https://www.example.com/
-
-On Linux it can be used to specify a **VRF**, but the binary needs to either
-have **CAP_NET_RAW** or to be run as root. More information about Linux
-**VRF**: https://www.kernel.org/doc/Documentation/networking/vrf.txt
diff --git a/docs/cmdline-opts/interface.md b/docs/cmdline-opts/interface.md
new file mode 100644
index 000000000..44221d366
--- /dev/null
+++ b/docs/cmdline-opts/interface.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: interface
+Arg: <name>
+Help: Use network INTERFACE (or address)
+Category: connection
+Added: 7.3
+Multi: single
+See-also:
+ - dns-interface
+Example:
+ - --interface eth0 $URL
+---
+
+# `--interface`
+
+Perform an operation using a specified interface. You can enter interface
+name, IP address or host name. An example could look like:
+
+ curl --interface eth0:1 https://www.example.com/
+
+On Linux it can be used to specify a **VRF**, but the binary needs to either
+have **CAP_NET_RAW** or to be run as root. More information about Linux
+**VRF**: https://www.kernel.org/doc/Documentation/networking/vrf.txt
diff --git a/docs/cmdline-opts/ipfs-gateway.d b/docs/cmdline-opts/ipfs-gateway.d
deleted file mode 100644
index 5d5f8b2d4..000000000
--- a/docs/cmdline-opts/ipfs-gateway.d
+++ /dev/null
@@ -1,44 +0,0 @@
-c: Copyright (C) 2023, Mark Gaiser, <markg85@gmail.com>
-SPDX-License-Identifier: curl
-Long: ipfs-gateway
-Arg: <URL>
-Help: Gateway for IPFS
-Added: 8.4.0
-See-also: help manual
-Category: ipfs
-Example: --ipfs-gateway $URL ipfs://
-Multi: single
----
-Specifies which gateway to use for IPFS and IPNS URLs.
-Not specifying this argument will let cURL try to automatically
-check if IPFS_GATEWAY environment variable is set,
-or if ~/.ipfs/gateway plain text file exists.
-
-If you run a local IPFS node, this gateway is by default
-available under http://localhost:8080. A full example URL would
-look like:
-
- curl --ipfs-gateway http://localhost:8080 ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi
-
-
-You can also specify publicly available gateways. One such
-gateway is https://ipfs.io. A full example url would look like:
-
- curl --ipfs-gateway https://ipfs.io ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi
-
-
-There are many public IPFS gateways. As a starting point to find
-one that works for your case, consult this page:
-
- https://ipfs.github.io/public-gateway-checker/
-
-
-A word of caution! When you opt to go for a remote gateway you should
-be aware that you completely trust the gateway. This is fine in local gateways
-as you host it yourself. With remote gateways there could potentially be
-a malicious actor returning you data that does not match the request you made,
-inspect or even interfere with the request. You won't notice this when using cURL.
-A mitigation could be to go for a "trustless" gateway. This means you
-locally verify that the data. Consult the docs page on trusted vs trustless:
-https://docs.ipfs.tech/reference/http/gateway/#trusted-vs-trustless
-
diff --git a/docs/cmdline-opts/ipfs-gateway.md b/docs/cmdline-opts/ipfs-gateway.md
new file mode 100644
index 000000000..57c747b0c
--- /dev/null
+++ b/docs/cmdline-opts/ipfs-gateway.md
@@ -0,0 +1,39 @@
+---
+c: Copyright (C) Mark Gaiser, <markg85@gmail.com>
+SPDX-License-Identifier: curl
+Long: ipfs-gateway
+Arg: <URL>
+Help: Gateway for IPFS
+Protocols: IPFS
+Added: 8.4.0
+Category: ipfs
+Multi: single
+See-also:
+ - help
+ - manual
+Example:
+ - --ipfs-gateway $URL ipfs://
+---
+
+# `--ipfs-gateway`
+
+Specify which gateway to use for IPFS and IPNS URLs. Not specifying this will
+instead make curl check if the IPFS_GATEWAY environment variable is set, or if
+a `~/.ipfs/gateway` file holding the gateway URL exists.
+
+If you run a local IPFS node, this gateway is by default available under
+`http://localhost:8080`. A full example URL would look like:
+
+ curl --ipfs-gateway http://localhost:8080 ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi
+
+There are many public IPFS gateways. See for example:
+https://ipfs.github.io/public-gateway-checker/
+
+WARNING: If you opt to go for a remote gateway you should be aware that you
+completely trust the gateway. This is fine in local gateways as you host it
+yourself. With remote gateways there could potentially be a malicious actor
+returning you data that does not match the request you made, inspect or even
+interfere with the request. You will not notice this when using curl. A
+mitigation could be to go for a "trustless" gateway. This means you locally
+verify that the data. Consult the docs page on trusted vs trustless:
+https://docs.ipfs.tech/reference/http/gateway/#trusted-vs-trustless
diff --git a/docs/cmdline-opts/ipv4.d b/docs/cmdline-opts/ipv4.d
deleted file mode 100644
index 60690bedc..000000000
--- a/docs/cmdline-opts/ipv4.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: 4
-Long: ipv4
-Tags: Versions
-Protocols:
-Added: 7.10.8
-Mutexed: ipv6
-Requires:
-See-also: http1.1 http2
-Help: Resolve names to IPv4 addresses
-Category: connection dns
-Example: --ipv4 $URL
-Multi: mutex
----
-This option tells curl to use IPv4 addresses only when resolving host names,
-and not for example try IPv6.
diff --git a/docs/cmdline-opts/ipv4.md b/docs/cmdline-opts/ipv4.md
new file mode 100644
index 000000000..49d4df970
--- /dev/null
+++ b/docs/cmdline-opts/ipv4.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: 4
+Long: ipv4
+Tags: Versions
+Protocols:
+Added: 7.10.8
+Mutexed: ipv6
+Requires:
+Help: Resolve names to IPv4 addresses
+Category: connection dns
+Multi: mutex
+See-also:
+ - http1.1
+ - http2
+Example:
+ - --ipv4 $URL
+---
+
+# `--ipv4`
+
+This option tells curl to use IPv4 addresses only when resolving host names,
+and not for example try IPv6.
diff --git a/docs/cmdline-opts/ipv6.d b/docs/cmdline-opts/ipv6.d
deleted file mode 100644
index 24ce201a2..000000000
--- a/docs/cmdline-opts/ipv6.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: 6
-Long: ipv6
-Tags: Versions
-Protocols:
-Added: 7.10.8
-Mutexed: ipv4
-Requires:
-See-also: http1.1 http2
-Help: Resolve names to IPv6 addresses
-Category: connection dns
-Example: --ipv6 $URL
-Multi: mutex
----
-This option tells curl to use IPv6 addresses only when resolving host names,
-and not for example try IPv4.
diff --git a/docs/cmdline-opts/ipv6.md b/docs/cmdline-opts/ipv6.md
new file mode 100644
index 000000000..0612ec1bf
--- /dev/null
+++ b/docs/cmdline-opts/ipv6.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: 6
+Long: ipv6
+Tags: Versions
+Protocols:
+Added: 7.10.8
+Mutexed: ipv4
+Requires:
+Help: Resolve names to IPv6 addresses
+Category: connection dns
+Multi: mutex
+See-also:
+ - http1.1
+ - http2
+Example:
+ - --ipv6 $URL
+---
+
+# `--ipv6`
+
+This option tells curl to use IPv6 addresses only when resolving host names,
+and not for example try IPv4.
diff --git a/docs/cmdline-opts/json.d b/docs/cmdline-opts/json.d
deleted file mode 100644
index aa3b49de2..000000000
--- a/docs/cmdline-opts/json.d
+++ /dev/null
@@ -1,35 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: json
-Arg: <data>
-Help: HTTP POST JSON
-Protocols: HTTP
-See-also: data-binary data-raw
-Mutexed: form head upload-file
-Category: http post upload
-Example: --json '{ "drink": "coffe" }' $URL
-Example: --json '{ "drink":' --json ' "coffe" }' $URL
-Example: --json @prepared $URL
-Example: --json @- $URL < json.txt
-Added: 7.82.0
-Multi: append
----
-Sends the specified JSON data in a POST request to the HTTP server. --json
-works as a shortcut for passing on these three options:
-
- --data [arg]
- --header "Content-Type: application/json"
- --header "Accept: application/json"
-
-There is **no verification** that the passed in data is actual JSON or that
-the syntax is correct.
-
-If you start the data with the letter @, the rest should be a file name to
-read the data from, or a single dash (-) if you want curl to read the data
-from stdin. Posting data from a file named 'foobar' would thus be done with
---json @foobar and to instead read the data from stdin, use --json @-.
-
-If this option is used more than once on the same command line, the additional
-data pieces are concatenated to the previous before sending.
-
-The headers this option sets can be overridden with --header as usual.
diff --git a/docs/cmdline-opts/json.md b/docs/cmdline-opts/json.md
new file mode 100644
index 000000000..03d064029
--- /dev/null
+++ b/docs/cmdline-opts/json.md
@@ -0,0 +1,42 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: json
+Arg: <data>
+Help: HTTP POST JSON
+Protocols: HTTP
+Mutexed: form head upload-file
+Category: http post upload
+Added: 7.82.0
+Multi: append
+See-also:
+ - data-binary
+ - data-raw
+Example:
+ - --json '{ "drink": "coffe" }' $URL
+ - --json '{ "drink":' --json ' "coffe" }' $URL
+ - --json @prepared $URL
+ - --json @- $URL < json.txt
+---
+
+# `--json`
+
+Sends the specified JSON data in a POST request to the HTTP server. --json
+works as a shortcut for passing on these three options:
+
+ --data [arg]
+ --header "Content-Type: application/json"
+ --header "Accept: application/json"
+
+There is **no verification** that the passed in data is actual JSON or that
+the syntax is correct.
+
+If you start the data with the letter @, the rest should be a file name to
+read the data from, or a single dash (-) if you want curl to read the data
+from stdin. Posting data from a file named 'foobar' would thus be done with
+--json @foobar and to instead read the data from stdin, use --json @-.
+
+If this option is used more than once on the same command line, the additional
+data pieces are concatenated to the previous before sending.
+
+The headers this option sets can be overridden with --header as usual.
diff --git a/docs/cmdline-opts/junk-session-cookies.d b/docs/cmdline-opts/junk-session-cookies.d
deleted file mode 100644
index daea7840a..000000000
--- a/docs/cmdline-opts/junk-session-cookies.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: junk-session-cookies
-Short: j
-Help: Ignore session cookies read from file
-Protocols: HTTP
-See-also: cookie cookie-jar
-Category: http
-Example: --junk-session-cookies -b cookies.txt $URL
-Added: 7.9.7
-Multi: boolean
----
-When curl is told to read cookies from a given file, this option makes it
-discard all "session cookies". This has the same effect as if a new session is
-started. Typical browsers discard session cookies when they are closed down.
diff --git a/docs/cmdline-opts/junk-session-cookies.md b/docs/cmdline-opts/junk-session-cookies.md
new file mode 100644
index 000000000..63971050c
--- /dev/null
+++ b/docs/cmdline-opts/junk-session-cookies.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: junk-session-cookies
+Short: j
+Help: Ignore session cookies read from file
+Protocols: HTTP
+Category: http
+Added: 7.9.7
+Multi: boolean
+See-also:
+ - cookie
+ - cookie-jar
+Example:
+ - --junk-session-cookies -b cookies.txt $URL
+---
+
+# `--junk-session-cookies`
+
+When curl is told to read cookies from a given file, this option makes it
+discard all "session cookies". This has the same effect as if a new session is
+started. Typical browsers discard session cookies when they are closed down.
diff --git a/docs/cmdline-opts/keepalive-time.d b/docs/cmdline-opts/keepalive-time.d
deleted file mode 100644
index 5e284774d..000000000
--- a/docs/cmdline-opts/keepalive-time.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: keepalive-time
-Arg: <seconds>
-Help: Interval time for keepalive probes
-Added: 7.18.0
-Category: connection
-Example: --keepalive-time 20 $URL
-See-also: no-keepalive max-time
-Multi: single
----
-This option sets the time a connection needs to remain idle before sending
-keepalive probes and the time between individual keepalive probes. It is
-currently effective on operating systems offering the TCP_KEEPIDLE and
-TCP_KEEPINTVL socket options (meaning Linux, recent AIX, HP-UX and more).
-Keepalives are used by the TCP stack to detect broken networks on idle
-connections. The number of missed keepalive probes before declaring the
-connection down is OS dependent and is commonly 9 or 10. This option has no
-effect if --no-keepalive is used.
-
-If unspecified, the option defaults to 60 seconds.
diff --git a/docs/cmdline-opts/keepalive-time.md b/docs/cmdline-opts/keepalive-time.md
new file mode 100644
index 000000000..ce3d0f030
--- /dev/null
+++ b/docs/cmdline-opts/keepalive-time.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: keepalive-time
+Arg: <seconds>
+Help: Interval time for keepalive probes
+Added: 7.18.0
+Category: connection
+Multi: single
+See-also:
+ - no-keepalive
+ - max-time
+Example:
+ - --keepalive-time 20 $URL
+---
+
+# `--keepalive-time`
+
+This option sets the time a connection needs to remain idle before sending
+keepalive probes and the time between individual keepalive probes. It is
+currently effective on operating systems offering the `TCP_KEEPIDLE` and
+`TCP_KEEPINTVL` socket options (meaning Linux, recent AIX, HP-UX and more).
+Keepalive is used by the TCP stack to detect broken networks on idle
+connections. The number of missed keepalive probes before declaring the
+connection down is OS dependent and is commonly 9 or 10. This option has no
+effect if --no-keepalive is used.
+
+If unspecified, the option defaults to 60 seconds.
diff --git a/docs/cmdline-opts/key-type.d b/docs/cmdline-opts/key-type.d
deleted file mode 100644
index 22339b4c9..000000000
--- a/docs/cmdline-opts/key-type.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: key-type
-Arg: <type>
-Help: Private key file type (DER/PEM/ENG)
-Protocols: TLS
-Category: tls
-Example: --key-type DER --key here $URL
-Added: 7.9.3
-See-also: key
-Multi: single
----
-Private key file type. Specify which type your --key provided private key
-is. DER, PEM, and ENG are supported. If not specified, PEM is assumed.
diff --git a/docs/cmdline-opts/key-type.md b/docs/cmdline-opts/key-type.md
new file mode 100644
index 000000000..4128bfeaf
--- /dev/null
+++ b/docs/cmdline-opts/key-type.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: key-type
+Arg: <type>
+Help: Private key file type (DER/PEM/ENG)
+Protocols: TLS
+Category: tls
+Added: 7.9.3
+Multi: single
+See-also:
+ - key
+Example:
+ - --key-type DER --key here $URL
+---
+
+# `--key-type`
+
+Private key file type. Specify which type your --key provided private key
+is. DER, PEM, and ENG are supported. If not specified, PEM is assumed.
diff --git a/docs/cmdline-opts/key.d b/docs/cmdline-opts/key.d
deleted file mode 100644
index 4236218c9..000000000
--- a/docs/cmdline-opts/key.d
+++ /dev/null
@@ -1,27 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: key
-Arg: <key>
-Protocols: TLS SSH
-Help: Private key file name
-Category: tls ssh
-Example: --cert certificate --key here $URL
-Added: 7.9.3
-See-also: key-type cert
-Multi: single
----
-Private key file name. Allows you to provide your private key in this separate
-file. For SSH, if not specified, curl tries the following candidates in order:
-'~/.ssh/id_rsa', '~/.ssh/id_dsa', './id_rsa', './id_dsa'.
-
-If curl is built against OpenSSL library, and the engine pkcs11 is available,
-then a PKCS#11 URI (RFC 7512) can be used to specify a private key located in
-a PKCS#11 device. A string beginning with "pkcs11:" is interpreted as a
-PKCS#11 URI. If a PKCS#11 URI is provided, then the --engine option is set as
-"pkcs11" if none was provided and the --key-type option is set as "ENG" if
-none was provided.
-
-If curl is built against Secure Transport or Schannel then this option is
-ignored for TLS protocols (HTTPS, etc). Those backends expect the private key
-to be already present in the keychain or PKCS#12 file containing the
-certificate.
diff --git a/docs/cmdline-opts/key.md b/docs/cmdline-opts/key.md
new file mode 100644
index 000000000..1d3d79996
--- /dev/null
+++ b/docs/cmdline-opts/key.md
@@ -0,0 +1,34 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: key
+Arg: <key>
+Protocols: TLS SSH
+Help: Private key file name
+Category: tls ssh
+Added: 7.9.3
+Multi: single
+See-also:
+ - key-type
+ - cert
+Example:
+ - --cert certificate --key here $URL
+---
+
+# `--key`
+
+Private key file name. Allows you to provide your private key in this separate
+file. For SSH, if not specified, curl tries the following candidates in order:
+`~/.ssh/id_rsa`, `~/.ssh/id_dsa`, `./id_rsa`, `./id_dsa`.
+
+If curl is built against OpenSSL library, and the engine pkcs11 is available,
+then a PKCS#11 URI (RFC 7512) can be used to specify a private key located in
+a PKCS#11 device. A string beginning with `pkcs11:` is interpreted as a
+PKCS#11 URI. If a PKCS#11 URI is provided, then the --engine option is set as
+`pkcs11` if none was provided and the --key-type option is set as `ENG` if
+none was provided.
+
+If curl is built against Secure Transport or Schannel then this option is
+ignored for TLS protocols (HTTPS, etc). Those backends expect the private key
+to be already present in the keychain or PKCS#12 file containing the
+certificate.
diff --git a/docs/cmdline-opts/krb.d b/docs/cmdline-opts/krb.d
deleted file mode 100644
index 42aa67ada..000000000
--- a/docs/cmdline-opts/krb.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: krb
-Arg: <level>
-Help: Enable Kerberos with security <level>
-Protocols: FTP
-Requires: Kerberos
-Category: ftp
-Example: --krb clear ftp://example.com/
-Added: 7.3
-See-also: delegation ssl
-Multi: single
----
-Enable Kerberos authentication and use. The level must be entered and should
-be one of 'clear', 'safe', 'confidential', or 'private'. Should you use a
-level that is not one of these, 'private' is used.
diff --git a/docs/cmdline-opts/krb.md b/docs/cmdline-opts/krb.md
new file mode 100644
index 000000000..c353a0c74
--- /dev/null
+++ b/docs/cmdline-opts/krb.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: krb
+Arg: <level>
+Help: Enable Kerberos with security <level>
+Protocols: FTP
+Requires: Kerberos
+Category: ftp
+Added: 7.3
+Multi: single
+See-also:
+ - delegation
+ - ssl
+Example:
+ - --krb clear ftp://example.com/
+---
+
+# `--krb`
+
+Enable Kerberos authentication and use. The level must be entered and should
+be one of 'clear', 'safe', 'confidential', or 'private'. Should you use a
+level that is not one of these, 'private' is used.
diff --git a/docs/cmdline-opts/libcurl.d b/docs/cmdline-opts/libcurl.d
deleted file mode 100644
index 52e252f3b..000000000
--- a/docs/cmdline-opts/libcurl.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: libcurl
-Arg: <file>
-Help: Dump libcurl equivalent code of this command line
-Added: 7.16.1
-Category: curl
-Example: --libcurl client.c $URL
-See-also: verbose
-Multi: single
-Scope: global
----
-Append this option to any ordinary curl command line, and you get
-libcurl-using C source code written to the file that does the equivalent of
-what your command-line operation does!
diff --git a/docs/cmdline-opts/libcurl.md b/docs/cmdline-opts/libcurl.md
new file mode 100644
index 000000000..4b3c13d4c
--- /dev/null
+++ b/docs/cmdline-opts/libcurl.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: libcurl
+Arg: <file>
+Help: Dump libcurl equivalent code of this command line
+Added: 7.16.1
+Category: curl
+Multi: single
+Scope: global
+See-also:
+ - verbose
+Example:
+ - --libcurl client.c $URL
+---
+
+# `--libcurl`
+
+Append this option to any ordinary curl command line, and you get
+libcurl-using C source code written to the file that does the equivalent of
+what your command-line operation does!
diff --git a/docs/cmdline-opts/limit-rate.d b/docs/cmdline-opts/limit-rate.d
deleted file mode 100644
index 43ebf2c23..000000000
--- a/docs/cmdline-opts/limit-rate.d
+++ /dev/null
@@ -1,29 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: limit-rate
-Arg: <speed>
-Help: Limit transfer speed to RATE
-Category: connection
-Example: --limit-rate 100K $URL
-Example: --limit-rate 1000 $URL
-Example: --limit-rate 10M $URL
-Added: 7.10
-See-also: rate speed-limit speed-time
-Multi: single
----
-Specify the maximum transfer rate you want curl to use - for both downloads
-and uploads. This feature is useful if you have a limited pipe and you would like
-your transfer not to use your entire bandwidth. To make it slower than it
-otherwise would be.
-
-The given speed is measured in bytes/second, unless a suffix is appended.
-Appending 'k' or 'K' counts the number as kilobytes, 'm' or 'M' makes it
-megabytes, while 'g' or 'G' makes it gigabytes. The suffixes (k, M, G, T, P)
-are 1024 based. For example 1k is 1024. Examples: 200K, 3m and 1G.
-
-The rate limiting logic works on averaging the transfer speed to no more than
-the set threshold over a period of multiple seconds.
-
-If you also use the --speed-limit option, that option takes precedence and
-might cripple the rate-limiting slightly, to help keeping the speed-limit
-logic working.
diff --git a/docs/cmdline-opts/limit-rate.md b/docs/cmdline-opts/limit-rate.md
new file mode 100644
index 000000000..ab94c2f2d
--- /dev/null
+++ b/docs/cmdline-opts/limit-rate.md
@@ -0,0 +1,37 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: limit-rate
+Arg: <speed>
+Help: Limit transfer speed to RATE
+Category: connection
+Added: 7.10
+Multi: single
+See-also:
+ - rate
+ - speed-limit
+ - speed-time
+Example:
+ - --limit-rate 100K $URL
+ - --limit-rate 1000 $URL
+ - --limit-rate 10M $URL
+---
+
+# `--limit-rate`
+
+Specify the maximum transfer rate you want curl to use - for both downloads
+and uploads. This feature is useful if you have a limited pipe and you would like
+your transfer not to use your entire bandwidth. To make it slower than it
+otherwise would be.
+
+The given speed is measured in bytes/second, unless a suffix is appended.
+Appending 'k' or 'K' counts the number as kilobytes, 'm' or 'M' makes it
+megabytes, while 'g' or 'G' makes it gigabytes. The suffixes (k, M, G, T, P)
+are 1024 based. For example 1k is 1024. Examples: 200K, 3m and 1G.
+
+The rate limiting logic works on averaging the transfer speed to no more than
+the set threshold over a period of multiple seconds.
+
+If you also use the --speed-limit option, that option takes precedence and
+might cripple the rate-limiting slightly, to help keeping the speed-limit
+logic working.
diff --git a/docs/cmdline-opts/list-only.d b/docs/cmdline-opts/list-only.d
deleted file mode 100644
index dcfbf2ccc..000000000
--- a/docs/cmdline-opts/list-only.d
+++ /dev/null
@@ -1,36 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: list-only
-Short: l
-Protocols: FTP POP3 SFTP
-Help: List only mode
-Added: 4.0
-Category: ftp pop3 sftp
-Example: --list-only ftp://example.com/dir/
-See-also: quote request
-Multi: boolean
----
-(FTP)
-When listing an FTP directory, this switch forces a name-only view. This is
-especially useful if the user wants to machine-parse the contents of an FTP
-directory since the normal directory view does not use a standard look or
-format. When used like this, the option causes an NLST command to be sent to
-the server instead of LIST.
-
-Note: Some FTP servers list only files in their response to NLST; they do not
-include sub-directories and symbolic links.
-
-(SFTP)
-When listing an SFTP directory, this switch forces a name-only view, one per line.
-This is especially useful if the user wants to machine-parse the contents of an
-SFTP directory since the normal directory view provides more information than just
-file names.
-
-(POP3)
-When retrieving a specific email from POP3, this switch forces a LIST command
-to be performed instead of RETR. This is particularly useful if the user wants
-to see if a specific message-id exists on the server and what size it is.
-
-Note: When combined with --request, this option can be used to send a UIDL
-command instead, so the user may use the email's unique identifier rather than
-its message-id to make the request.
diff --git a/docs/cmdline-opts/list-only.md b/docs/cmdline-opts/list-only.md
new file mode 100644
index 000000000..4f688f7b8
--- /dev/null
+++ b/docs/cmdline-opts/list-only.md
@@ -0,0 +1,43 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: list-only
+Short: l
+Protocols: FTP POP3 SFTP
+Help: List only mode
+Added: 4.0
+Category: ftp pop3 sftp
+Multi: boolean
+See-also:
+ - quote
+ - request
+Example:
+ - --list-only ftp://example.com/dir/
+---
+
+# `--list-only`
+
+(FTP)
+When listing an FTP directory, this switch forces a name-only view. This is
+especially useful if the user wants to machine-parse the contents of an FTP
+directory since the normal directory view does not use a standard look or
+format. When used like this, the option causes an NLST command to be sent to
+the server instead of LIST.
+
+Note: Some FTP servers list only files in their response to NLST; they do not
+include sub-directories and symbolic links.
+
+(SFTP)
+When listing an SFTP directory, this switch forces a name-only view, one per line.
+This is especially useful if the user wants to machine-parse the contents of an
+SFTP directory since the normal directory view provides more information than just
+file names.
+
+(POP3)
+When retrieving a specific email from POP3, this switch forces a LIST command
+to be performed instead of RETR. This is particularly useful if the user wants
+to see if a specific message-id exists on the server and what size it is.
+
+Note: When combined with --request, this option can be used to send a UIDL
+command instead, so the user may use the email's unique identifier rather than
+its message-id to make the request.
diff --git a/docs/cmdline-opts/local-port.d b/docs/cmdline-opts/local-port.d
deleted file mode 100644
index d6949b7ee..000000000
--- a/docs/cmdline-opts/local-port.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: local-port
-Arg: <num/range>
-Help: Force use of RANGE for local port numbers
-Added: 7.15.2
-Category: connection
-Example: --local-port 1000-3000 $URL
-See-also: globoff
-Multi: single
----
-Set a preferred single number or range (FROM-TO) of local port numbers to use
-for the connection(s). Note that port numbers by nature are a scarce resource
-so setting this range to something too narrow might cause unnecessary
-connection setup failures.
diff --git a/docs/cmdline-opts/local-port.md b/docs/cmdline-opts/local-port.md
new file mode 100644
index 000000000..ef01a7c04
--- /dev/null
+++ b/docs/cmdline-opts/local-port.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: local-port
+Arg: <num/range>
+Help: Force use of RANGE for local port numbers
+Added: 7.15.2
+Category: connection
+Multi: single
+See-also:
+ - globoff
+Example:
+ - --local-port 1000-3000 $URL
+---
+
+# `--local-port`
+
+Set a preferred single number or range (FROM-TO) of local port numbers to use
+for the connection(s). Note that port numbers by nature are a scarce resource
+so setting this range to something too narrow might cause unnecessary
+connection setup failures.
diff --git a/docs/cmdline-opts/location-trusted.d b/docs/cmdline-opts/location-trusted.d
deleted file mode 100644
index 9f83d0ef0..000000000
--- a/docs/cmdline-opts/location-trusted.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: location-trusted
-Help: Like --location, and send auth to other hosts
-Protocols: HTTP
-See-also: user
-Category: http auth
-Example: --location-trusted -u user:password $URL
-Added: 7.10.4
-Multi: boolean
----
-Like --location, but allows sending the name + password to all hosts that the
-site may redirect to. This may or may not introduce a security breach if the
-site redirects you to a site to which you send your authentication info
-(which is plaintext in the case of HTTP Basic authentication).
diff --git a/docs/cmdline-opts/location-trusted.md b/docs/cmdline-opts/location-trusted.md
new file mode 100644
index 000000000..050cd9dbf
--- /dev/null
+++ b/docs/cmdline-opts/location-trusted.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: location-trusted
+Help: Like --location, and send auth to other hosts
+Protocols: HTTP
+Category: http auth
+Added: 7.10.4
+Multi: boolean
+See-also:
+ - user
+Example:
+ - --location-trusted -u user:password $URL
+---
+
+# `--location-trusted`
+
+Like --location, but allows sending the name + password to all hosts that the
+site may redirect to. This may or may not introduce a security breach if the
+site redirects you to a site to which you send your authentication info
+(which is clear-text in the case of HTTP Basic authentication).
diff --git a/docs/cmdline-opts/location.d b/docs/cmdline-opts/location.d
deleted file mode 100644
index 9a99a0513..000000000
--- a/docs/cmdline-opts/location.d
+++ /dev/null
@@ -1,33 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: location
-Short: L
-Help: Follow redirects
-Protocols: HTTP
-Category: http
-Example: -L $URL
-Added: 4.9
-See-also: resolve alt-svc
-Multi: boolean
----
-If the server reports that the requested page has moved to a different
-location (indicated with a Location: header and a 3XX response code), this
-option makes curl redo the request on the new place. If used together with
---include or --head, headers from all requested pages are shown.
-
-When authentication is used, curl only sends its credentials to the initial
-host. If a redirect takes curl to a different host, it does not get the
-user+password pass on. See also --location-trusted on how to change this.
-
-Limit the amount of redirects to follow by using the --max-redirs option.
-
-When curl follows a redirect and if the request is a POST, it sends the
-following request with a GET if the HTTP response was 301, 302, or 303. If the
-response code was any other 3xx code, curl resends the following request using
-the same unmodified method.
-
-You can tell curl to not change POST requests to GET after a 30x response by
-using the dedicated options for that: --post301, --post302 and --post303.
-
-The method set with --request overrides the method curl would otherwise select
-to use.
diff --git a/docs/cmdline-opts/location.md b/docs/cmdline-opts/location.md
new file mode 100644
index 000000000..62e3d470a
--- /dev/null
+++ b/docs/cmdline-opts/location.md
@@ -0,0 +1,40 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: location
+Short: L
+Help: Follow redirects
+Protocols: HTTP
+Category: http
+Added: 4.9
+Multi: boolean
+See-also:
+ - resolve
+ - alt-svc
+Example:
+ - -L $URL
+---
+
+# `--location`
+
+If the server reports that the requested page has moved to a different
+location (indicated with a Location: header and a 3XX response code), this
+option makes curl redo the request on the new place. If used together with
+--include or --head, headers from all requested pages are shown.
+
+When authentication is used, curl only sends its credentials to the initial
+host. If a redirect takes curl to a different host, it does not get the
+user+password pass on. See also --location-trusted on how to change this.
+
+Limit the amount of redirects to follow by using the --max-redirs option.
+
+When curl follows a redirect and if the request is a POST, it sends the
+following request with a GET if the HTTP response was 301, 302, or 303. If the
+response code was any other 3xx code, curl resends the following request using
+the same unmodified method.
+
+You can tell curl to not change POST requests to GET after a 30x response by
+using the dedicated options for that: --post301, --post302 and --post303.
+
+The method set with --request overrides the method curl would otherwise select
+to use.
diff --git a/docs/cmdline-opts/login-options.d b/docs/cmdline-opts/login-options.d
deleted file mode 100644
index c67be90f8..000000000
--- a/docs/cmdline-opts/login-options.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: login-options
-Arg: <options>
-Protocols: IMAP LDAP POP3 SMTP
-Help: Server login options
-Added: 7.34.0
-Category: imap pop3 smtp auth
-Example: --login-options 'AUTH=*' imap://example.com
-See-also: user
-Multi: single
----
-Specify the login options to use during server authentication.
-
-You can use login options to specify protocol specific options that may be
-used during authentication. At present only IMAP, POP3 and SMTP support login
-options. For more information about login options please see RFC 2384,
-RFC 5092 and the IETF draft
-https://datatracker.ietf.org/doc/html/draft-earhart-url-smtp-00.
-
-Since 8.2.0, IMAP supports the login option "AUTH=+LOGIN". With this option,
-curl uses the plain (not SASL) LOGIN IMAP command even if the server
-advertises SASL authentication. Care should be taken in using this option, as
-it sends your password over the network in plain text. This does not work if
-the IMAP server disables the plain LOGIN (e.g. to prevent password snooping).
diff --git a/docs/cmdline-opts/login-options.md b/docs/cmdline-opts/login-options.md
new file mode 100644
index 000000000..fdeeda52a
--- /dev/null
+++ b/docs/cmdline-opts/login-options.md
@@ -0,0 +1,32 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: login-options
+Arg: <options>
+Protocols: IMAP LDAP POP3 SMTP
+Help: Server login options
+Added: 7.34.0
+Category: imap pop3 smtp auth
+Multi: single
+See-also:
+ - user
+Example:
+ - --login-options 'AUTH=*' imap://example.com
+---
+
+# `--login-options`
+
+Specify the login options to use during server authentication.
+
+You can use login options to specify protocol specific options that may be
+used during authentication. At present only IMAP, POP3 and SMTP support login
+options. For more information about login options please see RFC 2384,
+RFC 5092 and the IETF draft
+https://datatracker.ietf.org/doc/html/draft-earhart-url-smtp-00
+
+Since 8.2.0, IMAP supports the login option `AUTH=+LOGIN`. With this option,
+curl uses the plain (not SASL) `LOGIN IMAP` command even if the server
+advertises SASL authentication. Care should be taken in using this option, as
+it sends your password over the network in plain text. This does not work if
+the IMAP server disables the plain `LOGIN` (e.g. to prevent password
+snooping).
diff --git a/docs/cmdline-opts/mail-auth.d b/docs/cmdline-opts/mail-auth.d
deleted file mode 100644
index 45ceebd99..000000000
--- a/docs/cmdline-opts/mail-auth.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: mail-auth
-Arg: <address>
-Protocols: SMTP
-Help: Originator address of the original email
-Added: 7.25.0
-See-also: mail-rcpt mail-from
-Category: smtp
-Example: --mail-auth user@example.come -T mail smtp://example.com/
-Multi: single
----
-Specify a single address. This is used to specify the authentication address
-(identity) of a submitted message that is being relayed to another server.
diff --git a/docs/cmdline-opts/mail-auth.md b/docs/cmdline-opts/mail-auth.md
new file mode 100644
index 000000000..3692c1596
--- /dev/null
+++ b/docs/cmdline-opts/mail-auth.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: mail-auth
+Arg: <address>
+Protocols: SMTP
+Help: Originator address of the original email
+Added: 7.25.0
+Category: smtp
+Multi: single
+See-also:
+ - mail-rcpt
+ - mail-from
+Example:
+ - --mail-auth user@example.come -T mail smtp://example.com/
+---
+
+# `--mail-auth`
+
+Specify a single address. This is used to specify the authentication address
+(identity) of a submitted message that is being relayed to another server.
diff --git a/docs/cmdline-opts/mail-from.d b/docs/cmdline-opts/mail-from.d
deleted file mode 100644
index 0729e841a..000000000
--- a/docs/cmdline-opts/mail-from.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: mail-from
-Arg: <address>
-Help: Mail from this address
-Protocols: SMTP
-Added: 7.20.0
-See-also: mail-rcpt mail-auth
-Category: smtp
-Example: --mail-from user@example.com -T mail smtp://example.com/
-Multi: single
----
-Specify a single address that the given mail should get sent from.
diff --git a/docs/cmdline-opts/mail-from.md b/docs/cmdline-opts/mail-from.md
new file mode 100644
index 000000000..96b062501
--- /dev/null
+++ b/docs/cmdline-opts/mail-from.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: mail-from
+Arg: <address>
+Help: Mail from this address
+Protocols: SMTP
+Added: 7.20.0
+Category: smtp
+Multi: single
+See-also:
+ - mail-rcpt
+ - mail-auth
+Example:
+ - --mail-from user@example.com -T mail smtp://example.com/
+---
+
+# `--mail-from`
+
+Specify a single address that the given mail should get sent from.
diff --git a/docs/cmdline-opts/mail-rcpt-allowfails.d b/docs/cmdline-opts/mail-rcpt-allowfails.d
deleted file mode 100644
index d2a5f39d3..000000000
--- a/docs/cmdline-opts/mail-rcpt-allowfails.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: mail-rcpt-allowfails
-Help: Allow RCPT TO command to fail for some recipients
-Protocols: SMTP
-Added: 7.69.0
-Category: smtp
-Example: --mail-rcpt-allowfails --mail-rcpt dest@example.com smtp://example.com
-See-also: mail-rcpt
-Multi: boolean
----
-When sending data to multiple recipients, by default curl aborts SMTP
-conversation if at least one of the recipients causes RCPT TO command to
-return an error.
-
-The default behavior can be changed by passing --mail-rcpt-allowfails
-command-line option which makes curl ignore errors and proceed with the
-remaining valid recipients.
-
-If all recipients trigger RCPT TO failures and this flag is specified, curl
-still aborts the SMTP conversation and returns the error received from to the
-last RCPT TO command.
diff --git a/docs/cmdline-opts/mail-rcpt-allowfails.md b/docs/cmdline-opts/mail-rcpt-allowfails.md
new file mode 100644
index 000000000..1b670adb0
--- /dev/null
+++ b/docs/cmdline-opts/mail-rcpt-allowfails.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: mail-rcpt-allowfails
+Help: Allow RCPT TO command to fail for some recipients
+Protocols: SMTP
+Added: 7.69.0
+Category: smtp
+Multi: boolean
+See-also:
+ - mail-rcpt
+Example:
+ - --mail-rcpt-allowfails --mail-rcpt dest@example.com smtp://example.com
+---
+
+# `--mail-rcpt-allowfails`
+
+When sending data to multiple recipients, by default curl aborts SMTP
+conversation if at least one of the recipients causes RCPT TO command to
+return an error.
+
+The default behavior can be changed by passing --mail-rcpt-allowfails
+command-line option which makes curl ignore errors and proceed with the
+remaining valid recipients.
+
+If all recipients trigger RCPT TO failures and this flag is specified, curl
+still aborts the SMTP conversation and returns the error received from to the
+last RCPT TO command.
diff --git a/docs/cmdline-opts/mail-rcpt.d b/docs/cmdline-opts/mail-rcpt.d
deleted file mode 100644
index a4b16c4f7..000000000
--- a/docs/cmdline-opts/mail-rcpt.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: mail-rcpt
-Arg: <address>
-Help: Mail to this address
-Protocols: SMTP
-Added: 7.20.0
-Category: smtp
-Example: --mail-rcpt user@example.net smtp://example.com
-See-also: mail-rcpt-allowfails
-Multi: append
----
-Specify a single email address, user name or mailing list name. Repeat this
-option several times to send to multiple recipients.
-
-When performing an address verification (**VRFY** command), the recipient should be
-specified as the user name or user name and domain (as per Section 3.5 of
-RFC 5321). (Added in 7.34.0)
-
-When performing a mailing list expand (EXPN command), the recipient should be
-specified using the mailing list name, such as "Friends" or "London-Office".
-(Added in 7.34.0)
diff --git a/docs/cmdline-opts/mail-rcpt.md b/docs/cmdline-opts/mail-rcpt.md
new file mode 100644
index 000000000..3f89feb23
--- /dev/null
+++ b/docs/cmdline-opts/mail-rcpt.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: mail-rcpt
+Arg: <address>
+Help: Mail to this address
+Protocols: SMTP
+Added: 7.20.0
+Category: smtp
+Multi: append
+See-also:
+ - mail-rcpt-allowfails
+Example:
+ - --mail-rcpt user@example.net smtp://example.com
+---
+
+# `--mail-rcpt`
+
+Specify a single email address, user name or mailing list name. Repeat this
+option several times to send to multiple recipients.
+
+When performing an address verification (**VRFY** command), the recipient should be
+specified as the user name or user name and domain (as per Section 3.5 of
+RFC 5321). (Added in 7.34.0)
+
+When performing a mailing list expand (EXPN command), the recipient should be
+specified using the mailing list name, such as "Friends" or "London-Office".
+(Added in 7.34.0)
diff --git a/docs/cmdline-opts/mainpage.idx b/docs/cmdline-opts/mainpage.idx
new file mode 100644
index 000000000..8496ee46d
--- /dev/null
+++ b/docs/cmdline-opts/mainpage.idx
@@ -0,0 +1,43 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+_NAME.md
+_SYNOPSIS.md
+_DESCRIPTION.md
+_URL.md
+_GLOBBING.md
+_VARIABLES.md
+_OUTPUT.md
+_PROTOCOLS.md
+_PROGRESS.md
+_VERSION.md
+_OPTIONS.md
+%options
+_FILES.md
+_ENVIRONMENT.md
+_PROXYPREFIX.md
+_EXITCODES.md
+_BUGS.md
+_AUTHORS.md
+_WWW.md
+_SEEALSO.md
diff --git a/docs/cmdline-opts/manual.d b/docs/cmdline-opts/manual.d
deleted file mode 100644
index 9ee4d075a..000000000
--- a/docs/cmdline-opts/manual.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: manual
-Short: M
-Help: Display the full manual
-Category: curl
-Example: --manual
-Added: 5.2
-See-also: verbose libcurl trace
-Multi: custom
----
-Manual. Display the huge help text.
diff --git a/docs/cmdline-opts/manual.md b/docs/cmdline-opts/manual.md
new file mode 100644
index 000000000..bf44f3b8a
--- /dev/null
+++ b/docs/cmdline-opts/manual.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: manual
+Short: M
+Help: Display the full manual
+Category: curl
+Added: 5.2
+Multi: custom
+See-also:
+ - verbose
+ - libcurl
+ - trace
+Example:
+ - --manual
+---
+
+# `--manual`
+
+Manual. Display the huge help text.
diff --git a/docs/cmdline-opts/max-filesize.d b/docs/cmdline-opts/max-filesize.d
deleted file mode 100644
index 7541a2712..000000000
--- a/docs/cmdline-opts/max-filesize.d
+++ /dev/null
@@ -1,26 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: max-filesize
-Arg: <bytes>
-Help: Maximum file size to download
-Protocols: FTP HTTP MQTT
-See-also: limit-rate
-Category: connection
-Example: --max-filesize 100K $URL
-Added: 7.10.8
-Multi: single
----
-Specify the maximum size (in bytes) of a file to download. If the file
-requested is larger than this value, the transfer does not start and curl
-returns with exit code 63.
-
-A size modifier may be used. For example, Appending 'k' or 'K' counts the
-number as kilobytes, 'm' or 'M' makes it megabytes, while 'g' or 'G' makes it
-gigabytes. Examples: 200K, 3m and 1G. (Added in 7.58.0)
-
-**NOTE**: before curl 8.4.0, when the file size is not known prior to
-download, for such files this option has no effect even if the file transfer
-ends up being larger than this given limit.
-
-Starting with curl 8.4.0, this option aborts the transfer if it reaches the
-threshold during transfer.
diff --git a/docs/cmdline-opts/max-filesize.md b/docs/cmdline-opts/max-filesize.md
new file mode 100644
index 000000000..998359cf7
--- /dev/null
+++ b/docs/cmdline-opts/max-filesize.md
@@ -0,0 +1,32 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: max-filesize
+Arg: <bytes>
+Help: Maximum file size to download
+Protocols: FTP HTTP MQTT
+Category: connection
+Added: 7.10.8
+Multi: single
+See-also:
+ - limit-rate
+Example:
+ - --max-filesize 100K $URL
+---
+
+# `--max-filesize`
+
+Specify the maximum size (in bytes) of a file to download. If the file
+requested is larger than this value, the transfer does not start and curl
+returns with exit code 63.
+
+A size modifier may be used. For example, Appending 'k' or 'K' counts the
+number as kilobytes, 'm' or 'M' makes it megabytes, while 'g' or 'G' makes it
+gigabytes. Examples: 200K, 3m and 1G. (Added in 7.58.0)
+
+**NOTE**: before curl 8.4.0, when the file size is not known prior to
+download, for such files this option has no effect even if the file transfer
+ends up being larger than this given limit.
+
+Starting with curl 8.4.0, this option aborts the transfer if it reaches the
+threshold during transfer.
diff --git a/docs/cmdline-opts/max-redirs.d b/docs/cmdline-opts/max-redirs.d
deleted file mode 100644
index 31ce98ea5..000000000
--- a/docs/cmdline-opts/max-redirs.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: max-redirs
-Arg: <num>
-Help: Maximum number of redirects allowed
-Protocols: HTTP
-Category: http
-Example: --max-redirs 3 --location $URL
-Added: 7.5
-See-also: location
-Multi: single
----
-Set maximum number of redirections to follow. When --location is used, to
-prevent curl from following too many redirects, by default, the limit is
-set to 50 redirects. Set this option to -1 to make it unlimited.
diff --git a/docs/cmdline-opts/max-redirs.md b/docs/cmdline-opts/max-redirs.md
new file mode 100644
index 000000000..52b0c5721
--- /dev/null
+++ b/docs/cmdline-opts/max-redirs.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: max-redirs
+Arg: <num>
+Help: Maximum number of redirects allowed
+Protocols: HTTP
+Category: http
+Added: 7.5
+Multi: single
+See-also:
+ - location
+Example:
+ - --max-redirs 3 --location $URL
+---
+
+# `--max-redirs`
+
+Set maximum number of redirections to follow. When --location is used, to
+prevent curl from following too many redirects, by default, the limit is
+set to 50 redirects. Set this option to -1 to make it unlimited.
diff --git a/docs/cmdline-opts/max-time.d b/docs/cmdline-opts/max-time.d
deleted file mode 100644
index 0d5747b26..000000000
--- a/docs/cmdline-opts/max-time.d
+++ /dev/null
@@ -1,23 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: max-time
-Short: m
-Arg: <fractional seconds>
-Help: Maximum time allowed for transfer
-See-also: connect-timeout retry-max-time
-Category: connection
-Example: --max-time 10 $URL
-Example: --max-time 2.92 $URL
-Added: 4.0
-Multi: single
----
-Maximum time in seconds that you allow each transfer to take. This is useful
-for preventing your batch jobs from hanging for hours due to slow networks or
-links going down. This option accepts decimal values (added in 7.32.0).
-
-If you enable retrying the transfer (--retry) then the maximum time counter is
-reset each time the transfer is retried. You can use --retry-max-time to limit
-the retry time.
-
-The decimal value needs to provided using a dot (.) as decimal separator - not
-the local version even if it might be using another separator.
diff --git a/docs/cmdline-opts/max-time.md b/docs/cmdline-opts/max-time.md
new file mode 100644
index 000000000..ad8bdedc2
--- /dev/null
+++ b/docs/cmdline-opts/max-time.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: max-time
+Short: m
+Arg: <fractional seconds>
+Help: Maximum time allowed for transfer
+Category: connection
+Added: 4.0
+Multi: single
+See-also:
+ - connect-timeout
+ - retry-max-time
+Example:
+ - --max-time 10 $URL
+ - --max-time 2.92 $URL
+---
+
+# `--max-time`
+
+Maximum time in seconds that you allow each transfer to take. This is useful
+for preventing your batch jobs from hanging for hours due to slow networks or
+links going down. This option accepts decimal values (added in 7.32.0).
+
+If you enable retrying the transfer (--retry) then the maximum time counter is
+reset each time the transfer is retried. You can use --retry-max-time to limit
+the retry time.
+
+The decimal value needs to provided using a dot (.) as decimal separator - not
+the local version even if it might be using another separator.
diff --git a/docs/cmdline-opts/metalink.d b/docs/cmdline-opts/metalink.d
deleted file mode 100644
index 88f012176..000000000
--- a/docs/cmdline-opts/metalink.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: metalink
-Help: Process given URLs as metalink XML file
-Added: 7.27.0
-Category: misc
-Example: --metalink file $URL
-See-also: parallel
-Multi: single
----
-This option was previously used to specify a Metalink resource. Metalink
-support is disabled in curl for security reasons (added in 7.78.0).
diff --git a/docs/cmdline-opts/metalink.md b/docs/cmdline-opts/metalink.md
new file mode 100644
index 000000000..0c39b46ed
--- /dev/null
+++ b/docs/cmdline-opts/metalink.md
@@ -0,0 +1,18 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: metalink
+Help: Process given URLs as metalink XML file
+Added: 7.27.0
+Category: misc
+Multi: single
+See-also:
+ - parallel
+Example:
+ - --metalink file $URL
+---
+
+# `--metalink`
+
+This option was previously used to specify a Metalink resource. Metalink
+support is disabled in curl for security reasons (added in 7.78.0).
diff --git a/docs/cmdline-opts/negotiate.d b/docs/cmdline-opts/negotiate.d
deleted file mode 100644
index f1dd34dba..000000000
--- a/docs/cmdline-opts/negotiate.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: negotiate
-Help: Use HTTP Negotiate (SPNEGO) authentication
-Protocols: HTTP
-See-also: basic ntlm anyauth proxy-negotiate
-Category: auth http
-Example: --negotiate -u : $URL
-Added: 7.10.6
-Multi: mutex
----
-Enables Negotiate (SPNEGO) authentication.
-
-This option requires a library built with GSS-API or SSPI support. Use
---version to see if your curl supports GSS-API/SSPI or SPNEGO.
-
-When using this option, you must also provide a fake --user option to activate
-the authentication code properly. Sending a '-u :' is enough as the user name
-and password from the --user option are not actually used.
diff --git a/docs/cmdline-opts/negotiate.md b/docs/cmdline-opts/negotiate.md
new file mode 100644
index 000000000..f55f9212d
--- /dev/null
+++ b/docs/cmdline-opts/negotiate.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: negotiate
+Help: Use HTTP Negotiate (SPNEGO) authentication
+Protocols: HTTP
+Category: auth http
+Added: 7.10.6
+Multi: mutex
+See-also:
+ - basic
+ - ntlm
+ - anyauth
+ - proxy-negotiate
+Example:
+ - --negotiate -u : $URL
+---
+
+# `--negotiate`
+
+Enables Negotiate (SPNEGO) authentication.
+
+This option requires a library built with GSS-API or SSPI support. Use
+--version to see if your curl supports GSS-API/SSPI or SPNEGO.
+
+When using this option, you must also provide a fake --user option to activate
+the authentication code properly. Sending a '-u :' is enough as the user name
+and password from the --user option are not actually used.
diff --git a/docs/cmdline-opts/netrc-file.d b/docs/cmdline-opts/netrc-file.d
deleted file mode 100644
index 7b1a214da..000000000
--- a/docs/cmdline-opts/netrc-file.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: netrc-file
-Help: Specify FILE for netrc
-Arg: <filename>
-Added: 7.21.5
-Mutexed: netrc
-Category: curl
-Example: --netrc-file netrc $URL
-See-also: netrc user config
-Multi: single
----
-This option is similar to --netrc, except that you provide the path (absolute
-or relative) to the netrc file that curl should use. You can only specify one
-netrc file per invocation.
-
-It abides by --netrc-optional if specified.
diff --git a/docs/cmdline-opts/netrc-file.md b/docs/cmdline-opts/netrc-file.md
new file mode 100644
index 000000000..e37020ea8
--- /dev/null
+++ b/docs/cmdline-opts/netrc-file.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: netrc-file
+Help: Specify FILE for netrc
+Arg: <filename>
+Added: 7.21.5
+Mutexed: netrc
+Category: curl
+Multi: single
+See-also:
+ - netrc
+ - user
+ - config
+Example:
+ - --netrc-file netrc $URL
+---
+
+# `--netrc-file`
+
+This option is similar to --netrc, except that you provide the path (absolute
+or relative) to the netrc file that curl should use. You can only specify one
+netrc file per invocation.
+
+It abides by --netrc-optional if specified.
diff --git a/docs/cmdline-opts/netrc-optional.d b/docs/cmdline-opts/netrc-optional.d
deleted file mode 100644
index a7759640f..000000000
--- a/docs/cmdline-opts/netrc-optional.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: netrc-optional
-Help: Use either .netrc or URL
-Mutexed: netrc
-See-also: netrc-file
-Category: curl
-Example: --netrc-optional $URL
-Added: 7.9.8
-Multi: boolean
----
-Similar to --netrc, but this option makes the .netrc usage **optional**
-and not mandatory as the --netrc option does.
diff --git a/docs/cmdline-opts/netrc-optional.md b/docs/cmdline-opts/netrc-optional.md
new file mode 100644
index 000000000..6aa76954a
--- /dev/null
+++ b/docs/cmdline-opts/netrc-optional.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: netrc-optional
+Help: Use either .netrc or URL
+Mutexed: netrc
+Category: curl
+Added: 7.9.8
+Multi: boolean
+See-also:
+ - netrc-file
+Example:
+ - --netrc-optional $URL
+---
+
+# `--netrc-optional`
+
+Similar to --netrc, but this option makes the .netrc usage **optional**
+and not mandatory as the --netrc option does.
diff --git a/docs/cmdline-opts/netrc.d b/docs/cmdline-opts/netrc.d
deleted file mode 100644
index f0ec75f37..000000000
--- a/docs/cmdline-opts/netrc.d
+++ /dev/null
@@ -1,30 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: netrc
-Short: n
-Help: Must read .netrc for user name and password
-Category: curl
-Example: --netrc $URL
-Added: 4.6
-See-also: netrc-file config user
-Mutexed: netrc-file netrc-optional
-Multi: boolean
----
-Makes curl scan the *.netrc* file in the user's home directory for login name
-and password. This is typically used for FTP on Unix. If used with HTTP, curl
-enables user authentication. See *netrc(5)* and *ftp(1)* for details on the
-file format. Curl does not complain if that file does not have the right
-permissions (it should be neither world- nor group-readable). The environment
-variable "HOME" is used to find the home directory.
-
-On Windows two filenames in the home directory are checked: *.netrc* and
-*_netrc*, preferring the former. Older versions on Windows checked for *_netrc*
-only.
-
-A quick and simple example of how to setup a *.netrc* to allow curl to FTP to
-the machine host.domain.com with user name 'myself' and password 'secret'
-could look similar to:
-
- machine host.domain.com
- login myself
- password secret
diff --git a/docs/cmdline-opts/netrc.md b/docs/cmdline-opts/netrc.md
new file mode 100644
index 000000000..dad3e6b00
--- /dev/null
+++ b/docs/cmdline-opts/netrc.md
@@ -0,0 +1,38 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: netrc
+Short: n
+Help: Must read .netrc for user name and password
+Category: curl
+Added: 4.6
+Mutexed: netrc-file netrc-optional
+Multi: boolean
+See-also:
+ - netrc-file
+ - config
+ - user
+Example:
+ - --netrc $URL
+---
+
+# `--netrc`
+
+Makes curl scan the *.netrc* file in the user's home directory for login name
+and password. This is typically used for FTP on Unix. If used with HTTP, curl
+enables user authentication. See *netrc(5)* and *ftp(1)* for details on the
+file format. Curl does not complain if that file does not have the right
+permissions (it should be neither world- nor group-readable). The environment
+variable "HOME" is used to find the home directory.
+
+On Windows two filenames in the home directory are checked: *.netrc* and
+*_netrc*, preferring the former. Older versions on Windows checked for *_netrc*
+only.
+
+A quick and simple example of how to setup a *.netrc* to allow curl to FTP to
+the machine host.domain.com with user name 'myself' and password 'secret'
+could look similar to:
+
+ machine host.domain.com
+ login myself
+ password secret
diff --git a/docs/cmdline-opts/next.d b/docs/cmdline-opts/next.d
deleted file mode 100644
index 93c9c45b3..000000000
--- a/docs/cmdline-opts/next.d
+++ /dev/null
@@ -1,27 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: :
-Long: next
-Tags:
-Protocols:
-Added: 7.36.0
-Magic: divider
-Help: Make next URL use its separate set of options
-Category: curl
-Example: $URL --next -d postthis www2.example.com
-Example: -I $URL --next https://example.net/
-See-also: parallel config
-Multi: append
----
-Tells curl to use a separate operation for the following URL and associated
-options. This allows you to send several URL requests, each with their own
-specific options, for example, such as different user names or custom requests
-for each.
-
---next resets all local options and only global ones have their values survive
-over to the operation following the --next instruction. Global options include
---verbose, --trace, --trace-ascii and --fail-early.
-
-For example, you can do both a GET and a POST in a single command line:
-
- curl www1.example.com --next -d postthis www2.example.com
diff --git a/docs/cmdline-opts/next.md b/docs/cmdline-opts/next.md
new file mode 100644
index 000000000..ef647b6eb
--- /dev/null
+++ b/docs/cmdline-opts/next.md
@@ -0,0 +1,34 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: :
+Long: next
+Tags:
+Protocols:
+Added: 7.36.0
+Magic: divider
+Help: Make next URL use its separate set of options
+Category: curl
+Multi: append
+See-also:
+ - parallel
+ - config
+Example:
+ - $URL --next -d postthis www2.example.com
+ - -I $URL --next https://example.net/
+---
+
+# `--next`
+
+Tells curl to use a separate operation for the following URL and associated
+options. This allows you to send several URL requests, each with their own
+specific options, for example, such as different user names or custom requests
+for each.
+
+--next resets all local options and only global ones have their values survive
+over to the operation following the --next instruction. Global options include
+--verbose, --trace, --trace-ascii and --fail-early.
+
+For example, you can do both a GET and a POST in a single command line:
+
+ curl www1.example.com --next -d postthis www2.example.com
diff --git a/docs/cmdline-opts/no-alpn.d b/docs/cmdline-opts/no-alpn.d
deleted file mode 100644
index 102f2990e..000000000
--- a/docs/cmdline-opts/no-alpn.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: no-alpn
-Tags: HTTP/2
-Protocols: HTTPS
-Added: 7.36.0
-See-also: no-npn http2
-Requires: TLS
-Help: Disable the ALPN TLS extension
-Category: tls http
-Example: --no-alpn $URL
-Multi: boolean
----
-Disable the ALPN TLS extension. ALPN is enabled by default if libcurl was built
-with an SSL library that supports ALPN. ALPN is used by a libcurl that supports
-HTTP/2 to negotiate HTTP/2 support with the server during https sessions.
-
-Note that this is the negated option name documented. You can use --alpn to
-enable ALPN.
diff --git a/docs/cmdline-opts/no-alpn.md b/docs/cmdline-opts/no-alpn.md
new file mode 100644
index 000000000..475294878
--- /dev/null
+++ b/docs/cmdline-opts/no-alpn.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: no-alpn
+Tags: HTTP/2
+Protocols: HTTPS
+Added: 7.36.0
+Requires: TLS
+Help: Disable the ALPN TLS extension
+Category: tls http
+Multi: boolean
+See-also:
+ - no-npn
+ - http2
+Example:
+ - --no-alpn $URL
+---
+
+# `--no-alpn`
+
+Disable the ALPN TLS extension. ALPN is enabled by default if libcurl was built
+with an SSL library that supports ALPN. ALPN is used by a libcurl that supports
+HTTP/2 to negotiate HTTP/2 support with the server during https sessions.
+
+Note that this is the negated option name documented. You can use --alpn to
+enable ALPN.
diff --git a/docs/cmdline-opts/no-buffer.d b/docs/cmdline-opts/no-buffer.d
deleted file mode 100644
index 33f6fbc5b..000000000
--- a/docs/cmdline-opts/no-buffer.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: no-buffer
-Short: N
-Help: Disable buffering of the output stream
-Category: curl
-Example: --no-buffer $URL
-Added: 6.5
-See-also: progress-bar
-Multi: boolean
----
-Disables the buffering of the output stream. In normal work situations, curl
-uses a standard buffered output stream that has the effect that it outputs the
-data in chunks, not necessarily exactly when the data arrives. Using this
-option disables that buffering.
-
-Note that this is the negated option name documented. You can use --buffer to
-enable buffering again.
diff --git a/docs/cmdline-opts/no-buffer.md b/docs/cmdline-opts/no-buffer.md
new file mode 100644
index 000000000..41328b165
--- /dev/null
+++ b/docs/cmdline-opts/no-buffer.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: no-buffer
+Short: N
+Help: Disable buffering of the output stream
+Category: curl
+Added: 6.5
+Multi: boolean
+See-also:
+ - progress-bar
+Example:
+ - --no-buffer $URL
+---
+
+# `--no-buffer`
+
+Disables the buffering of the output stream. In normal work situations, curl
+uses a standard buffered output stream that has the effect that it outputs the
+data in chunks, not necessarily exactly when the data arrives. Using this
+option disables that buffering.
+
+Note that this is the negated option name documented. You can use --buffer to
+enable buffering again.
diff --git a/docs/cmdline-opts/no-clobber.d b/docs/cmdline-opts/no-clobber.d
deleted file mode 100644
index 9325558da..000000000
--- a/docs/cmdline-opts/no-clobber.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: no-clobber
-Help: Do not overwrite files that already exist
-Category: curl output
-Added: 7.83.0
-See-also: output remote-name
-Example: --no-clobber --output local/dir/file $URL
-Multi: boolean
----
-When used in conjunction with the --output, --remote-header-name,
---remote-name, or --remote-name-all options, curl avoids overwriting files
-that already exist. Instead, a dot and a number gets appended to the name of
-the file that would be created, up to filename.100 after which it does not
-create any file.
-
-Note that this is the negated option name documented. You can thus use
---clobber to enforce the clobbering, even if --remote-header-name is
-specified.
diff --git a/docs/cmdline-opts/no-clobber.md b/docs/cmdline-opts/no-clobber.md
new file mode 100644
index 000000000..58646224c
--- /dev/null
+++ b/docs/cmdline-opts/no-clobber.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: no-clobber
+Help: Do not overwrite files that already exist
+Category: curl output
+Added: 7.83.0
+Multi: boolean
+See-also:
+ - output
+ - remote-name
+Example:
+ - --no-clobber --output local/dir/file $URL
+---
+
+# `--no-clobber`
+
+When used in conjunction with the --output, --remote-header-name,
+--remote-name, or --remote-name-all options, curl avoids overwriting files
+that already exist. Instead, a dot and a number gets appended to the name of
+the file that would be created, up to filename.100 after which it does not
+create any file.
+
+Note that this is the negated option name documented. You can thus use
+--clobber to enforce the clobbering, even if --remote-header-name is
+specified.
diff --git a/docs/cmdline-opts/no-keepalive.d b/docs/cmdline-opts/no-keepalive.d
deleted file mode 100644
index 0aeaef8d5..000000000
--- a/docs/cmdline-opts/no-keepalive.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: no-keepalive
-Help: Disable TCP keepalive on the connection
-Category: connection
-Example: --no-keepalive $URL
-Added: 7.18.0
-See-also: keepalive-time
-Multi: boolean
----
-Disables the use of keepalive messages on the TCP connection. curl otherwise
-enables them by default.
-
-Note that this is the negated option name documented. You can thus use
---keepalive to enforce keepalive.
diff --git a/docs/cmdline-opts/no-keepalive.md b/docs/cmdline-opts/no-keepalive.md
new file mode 100644
index 000000000..1829e8c4e
--- /dev/null
+++ b/docs/cmdline-opts/no-keepalive.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: no-keepalive
+Help: Disable TCP keepalive on the connection
+Category: connection
+Added: 7.18.0
+Multi: boolean
+See-also:
+ - keepalive-time
+Example:
+ - --no-keepalive $URL
+---
+
+# `--no-keepalive`
+
+Disables the use of keepalive messages on the TCP connection. curl otherwise
+enables them by default.
+
+Note that this is the negated option name documented. You can thus use
+--keepalive to enforce keepalive.
diff --git a/docs/cmdline-opts/no-npn.d b/docs/cmdline-opts/no-npn.d
deleted file mode 100644
index cd0e5e2af..000000000
--- a/docs/cmdline-opts/no-npn.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: no-npn
-Tags: Versions HTTP/2
-Protocols: HTTPS
-Added: 7.36.0
-Mutexed:
-See-also: no-alpn http2
-Requires: TLS
-Help: Disable the NPN TLS extension
-Category: tls http
-Example: --no-npn $URL
-Multi: boolean
----
-curl never uses NPN, this option has no effect (added in 7.86.0).
-
-Disable the NPN TLS extension. NPN is enabled by default if libcurl was built
-with an SSL library that supports NPN. NPN is used by a libcurl that supports
-HTTP/2 to negotiate HTTP/2 support with the server during https sessions.
diff --git a/docs/cmdline-opts/no-npn.md b/docs/cmdline-opts/no-npn.md
new file mode 100644
index 000000000..d8ad6a251
--- /dev/null
+++ b/docs/cmdline-opts/no-npn.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: no-npn
+Tags: Versions HTTP/2
+Protocols: HTTPS
+Added: 7.36.0
+Mutexed:
+Requires: TLS
+Help: Disable the NPN TLS extension
+Category: tls http
+Multi: boolean
+See-also:
+ - no-alpn
+ - http2
+Example:
+ - --no-npn $URL
+---
+
+# `--no-npn`
+
+curl never uses NPN, this option has no effect (added in 7.86.0).
+
+Disable the NPN TLS extension. NPN is enabled by default if libcurl was built
+with an SSL library that supports NPN. NPN is used by a libcurl that supports
+HTTP/2 to negotiate HTTP/2 support with the server during https sessions.
diff --git a/docs/cmdline-opts/no-progress-meter.d b/docs/cmdline-opts/no-progress-meter.d
deleted file mode 100644
index 820557d9d..000000000
--- a/docs/cmdline-opts/no-progress-meter.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: no-progress-meter
-Help: Do not show the progress meter
-See-also: verbose silent
-Added: 7.67.0
-Category: verbose
-Example: --no-progress-meter -o store $URL
-Multi: boolean
----
-Option to switch off the progress meter output without muting or otherwise
-affecting warning and informational messages like --silent does.
-
-Note that this is the negated option name documented. You can thus use
---progress-meter to enable the progress meter again.
diff --git a/docs/cmdline-opts/no-progress-meter.md b/docs/cmdline-opts/no-progress-meter.md
new file mode 100644
index 000000000..72ec99376
--- /dev/null
+++ b/docs/cmdline-opts/no-progress-meter.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: no-progress-meter
+Help: Do not show the progress meter
+Added: 7.67.0
+Category: verbose
+Multi: boolean
+See-also:
+ - verbose
+ - silent
+Example:
+ - --no-progress-meter -o store $URL
+---
+
+# `--no-progress-meter`
+
+Option to switch off the progress meter output without muting or otherwise
+affecting warning and informational messages like --silent does.
+
+Note that this is the negated option name documented. You can thus use
+--progress-meter to enable the progress meter again.
diff --git a/docs/cmdline-opts/no-sessionid.d b/docs/cmdline-opts/no-sessionid.d
deleted file mode 100644
index 9699f46bc..000000000
--- a/docs/cmdline-opts/no-sessionid.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: no-sessionid
-Help: Disable SSL session-ID reusing
-Protocols: TLS
-Added: 7.16.0
-Category: tls
-Example: --no-sessionid $URL
-See-also: insecure
-Multi: boolean
----
-Disable curl's use of SSL session-ID caching. By default all transfers are
-done using the cache. Note that while nothing should ever get hurt by
-attempting to reuse SSL session-IDs, there seem to be broken SSL
-implementations in the wild that may require you to disable this in order for
-you to succeed.
-
-Note that this is the negated option name documented. You can thus use
---sessionid to enforce session-ID caching.
diff --git a/docs/cmdline-opts/no-sessionid.md b/docs/cmdline-opts/no-sessionid.md
new file mode 100644
index 000000000..08ba990be
--- /dev/null
+++ b/docs/cmdline-opts/no-sessionid.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: no-sessionid
+Help: Disable SSL session-ID reusing
+Protocols: TLS
+Added: 7.16.0
+Category: tls
+Multi: boolean
+See-also:
+ - insecure
+Example:
+ - --no-sessionid $URL
+---
+
+# `--no-sessionid`
+
+Disable curl's use of SSL session-ID caching. By default all transfers are
+done using the cache. Note that while nothing should ever get hurt by
+attempting to reuse SSL session-IDs, there seem to be broken SSL
+implementations in the wild that may require you to disable this in order for
+you to succeed.
+
+Note that this is the negated option name documented. You can thus use
+--sessionid to enforce session-ID caching.
diff --git a/docs/cmdline-opts/noproxy.d b/docs/cmdline-opts/noproxy.d
deleted file mode 100644
index 001c109b6..000000000
--- a/docs/cmdline-opts/noproxy.d
+++ /dev/null
@@ -1,27 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: noproxy
-Arg: <no-proxy-list>
-Help: List of hosts which do not use proxy
-Added: 7.19.4
-Category: proxy
-Example: --noproxy "www.example" $URL
-See-also: proxy
-Multi: single
----
-Comma-separated list of hosts for which not to use a proxy, if one is
-specified. The only wildcard is a single * character, which matches all hosts,
-and effectively disables the proxy. Each name in this list is matched as
-either a domain which contains the hostname, or the hostname itself. For
-example, local.com would match local.com, local.com:80, and www.local.com, but
-not www.notlocal.com.
-
-This option overrides the environment variables that disable the proxy
-('no_proxy' and 'NO_PROXY') (added in 7.53.0). If there is an environment
-variable disabling a proxy, you can set the no proxy list to "" to override
-it.
-
-IP addresses specified to this option can be provided using CIDR notation
-(added in 7.86.0): an appended slash and number specifies the number of
-"network bits" out of the address to use in the comparison. For example
-"192.168.0.0/16" would match all addresses starting with "192.168".
diff --git a/docs/cmdline-opts/noproxy.md b/docs/cmdline-opts/noproxy.md
new file mode 100644
index 000000000..698549e15
--- /dev/null
+++ b/docs/cmdline-opts/noproxy.md
@@ -0,0 +1,33 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: noproxy
+Arg: <no-proxy-list>
+Help: List of hosts which do not use proxy
+Added: 7.19.4
+Category: proxy
+Multi: single
+See-also:
+ - proxy
+Example:
+ - --noproxy "www.example" $URL
+---
+
+# `--noproxy`
+
+Comma-separated list of hosts for which not to use a proxy, if one is
+specified. The only wildcard is a single `*` character, which matches all
+hosts, and effectively disables the proxy. Each name in this list is matched
+as either a domain which contains the hostname, or the hostname itself. For
+example, `local.com` would match `local.com`, `local.com:80`, and
+`www.local.com`, but not `www.notlocal.com`.
+
+This option overrides the environment variables that disable the proxy
+(`no_proxy` and `NO_PROXY`) (added in 7.53.0). If there is an environment
+variable disabling a proxy, you can set the no proxy list to "" to override
+it.
+
+IP addresses specified to this option can be provided using CIDR notation
+(added in 7.86.0): an appended slash and number specifies the number of
+network bits out of the address to use in the comparison. For example
+`192.168.0.0/16` would match all addresses starting with `192.168`.
diff --git a/docs/cmdline-opts/ntlm-wb.d b/docs/cmdline-opts/ntlm-wb.d
deleted file mode 100644
index 4a3225293..000000000
--- a/docs/cmdline-opts/ntlm-wb.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ntlm-wb
-Help: Use HTTP NTLM authentication with winbind
-Protocols: HTTP
-See-also: ntlm proxy-ntlm
-Category: auth http
-Example: --ntlm-wb -u user:password $URL
-Added: 7.22.0
-Multi: mutex
----
-Enables NTLM much in the style --ntlm does, but hand over the authentication
-to the separate binary ntlmauth application that is executed when needed.
diff --git a/docs/cmdline-opts/ntlm-wb.md b/docs/cmdline-opts/ntlm-wb.md
new file mode 100644
index 000000000..bc75dda5b
--- /dev/null
+++ b/docs/cmdline-opts/ntlm-wb.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ntlm-wb
+Help: Use HTTP NTLM authentication with winbind
+Protocols: HTTP
+Category: auth http
+Added: 7.22.0
+Multi: mutex
+See-also:
+ - ntlm
+ - proxy-ntlm
+Example:
+ - --ntlm-wb -u user:password $URL
+---
+
+# `--ntlm-wb`
+
+Enables NTLM much in the style --ntlm does, but hand over the authentication
+to the separate binary `ntlmauth` application that is executed when needed.
diff --git a/docs/cmdline-opts/ntlm.d b/docs/cmdline-opts/ntlm.d
deleted file mode 100644
index cc98c51e3..000000000
--- a/docs/cmdline-opts/ntlm.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ntlm
-Help: Use HTTP NTLM authentication
-Mutexed: basic negotiate digest anyauth
-See-also: proxy-ntlm
-Protocols: HTTP
-Requires: TLS
-Category: auth http
-Example: --ntlm -u user:password $URL
-Added: 7.10.6
-Multi: mutex
----
-Enables NTLM authentication. The NTLM authentication method was designed by
-Microsoft and is used by IIS web servers. It is a proprietary protocol,
-reverse-engineered by clever people and implemented in curl based on their
-efforts. This kind of behavior should not be endorsed, you should encourage
-everyone who uses NTLM to switch to a public and documented authentication
-method instead, such as Digest.
-
-If you want to enable NTLM for your proxy authentication, then use
---proxy-ntlm.
diff --git a/docs/cmdline-opts/ntlm.md b/docs/cmdline-opts/ntlm.md
new file mode 100644
index 000000000..c0a58a636
--- /dev/null
+++ b/docs/cmdline-opts/ntlm.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ntlm
+Help: Use HTTP NTLM authentication
+Mutexed: basic negotiate digest anyauth
+Protocols: HTTP
+Requires: TLS
+Category: auth http
+Added: 7.10.6
+Multi: mutex
+See-also:
+ - proxy-ntlm
+Example:
+ - --ntlm -u user:password $URL
+---
+
+# `--ntlm`
+
+Enables NTLM authentication. The NTLM authentication method was designed by
+Microsoft and is used by IIS web servers. It is a proprietary protocol,
+reverse-engineered by clever people and implemented in curl based on their
+efforts. This kind of behavior should not be endorsed, you should encourage
+everyone who uses NTLM to switch to a public and documented authentication
+method instead, such as Digest.
+
+If you want to enable NTLM for your proxy authentication, then use
+--proxy-ntlm.
diff --git a/docs/cmdline-opts/oauth2-bearer.d b/docs/cmdline-opts/oauth2-bearer.d
deleted file mode 100644
index 6f3514784..000000000
--- a/docs/cmdline-opts/oauth2-bearer.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: oauth2-bearer
-Help: OAuth 2 Bearer Token
-Arg: <token>
-Protocols: IMAP LDAP POP3 SMTP HTTP
-Category: auth
-Example: --oauth2-bearer "mF_9.B5f-4.1JqM" $URL
-Added: 7.33.0
-See-also: basic ntlm digest
-Multi: single
----
-Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
-is used in conjunction with the user name which can be specified as part of
-the --url or --user options.
-
-The Bearer Token and user name are formatted according to RFC 6750.
diff --git a/docs/cmdline-opts/oauth2-bearer.md b/docs/cmdline-opts/oauth2-bearer.md
new file mode 100644
index 000000000..ebbcbeb54
--- /dev/null
+++ b/docs/cmdline-opts/oauth2-bearer.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: oauth2-bearer
+Help: OAuth 2 Bearer Token
+Arg: <token>
+Protocols: IMAP LDAP POP3 SMTP HTTP
+Category: auth
+Added: 7.33.0
+Multi: single
+See-also:
+ - basic
+ - ntlm
+ - digest
+Example:
+ - --oauth2-bearer "mF_9.B5f-4.1JqM" $URL
+---
+
+# `--oauth2-bearer`
+
+Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
+is used in conjunction with the user name which can be specified as part of
+the --url or --user options.
+
+The Bearer Token and user name are formatted according to RFC 6750.
diff --git a/docs/cmdline-opts/output-dir.d b/docs/cmdline-opts/output-dir.d
deleted file mode 100644
index 803b2948b..000000000
--- a/docs/cmdline-opts/output-dir.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: output-dir
-Arg: <dir>
-Help: Directory to save files in
-Added: 7.73.0
-See-also: remote-name remote-header-name
-Category: curl
-Example: --output-dir "tmp" -O $URL
-Multi: single
----
-This option specifies the directory in which files should be stored, when
---remote-name or --output are used.
-
-The given output directory is used for all URLs and output options on the
-command line, up until the first --next.
-
-If the specified target directory does not exist, the operation fails unless
---create-dirs is also used.
diff --git a/docs/cmdline-opts/output-dir.md b/docs/cmdline-opts/output-dir.md
new file mode 100644
index 000000000..9f494d87a
--- /dev/null
+++ b/docs/cmdline-opts/output-dir.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: output-dir
+Arg: <dir>
+Help: Directory to save files in
+Added: 7.73.0
+Category: curl
+Multi: single
+See-also:
+ - remote-name
+ - remote-header-name
+Example:
+ - --output-dir "tmp" -O $URL
+---
+
+# `--output-dir`
+
+This option specifies the directory in which files should be stored, when
+--remote-name or --output are used.
+
+The given output directory is used for all URLs and output options on the
+command line, up until the first --next.
+
+If the specified target directory does not exist, the operation fails unless
+--create-dirs is also used.
diff --git a/docs/cmdline-opts/output.d b/docs/cmdline-opts/output.d
deleted file mode 100644
index 316f10999..000000000
--- a/docs/cmdline-opts/output.d
+++ /dev/null
@@ -1,49 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: output
-Arg: <file>
-Short: o
-Help: Write to file instead of stdout
-See-also: remote-name remote-name-all remote-header-name
-Category: important curl
-Example: -o file $URL
-Example: "http://{one,two}.example.com" -o "file_#1.txt"
-Example: "http://{site,host}.host[1-5].example" -o "#1_#2"
-Example: -o file $URL -o file2 https://example.net
-Added: 4.0
-Multi: append
----
-Write output to <file> instead of stdout. If you are using {} or [] to fetch
-multiple documents, you should quote the URL and you can use '#' followed by a
-number in the <file> specifier. That variable is replaced with the current
-string for the URL being fetched. Like in:
-
- curl "http://{one,two}.example.com" -o "file_#1.txt"
-
-or use several variables like:
-
- curl "http://{site,host}.host[1-5].example" -o "#1_#2"
-
-You may use this option as many times as the number of URLs you have. For
-example, if you specify two URLs on the same command line, you can use it like
-this:
-
- curl -o aa example.com -o bb example.net
-
-and the order of the -o options and the URLs does not matter, just that the
-first -o is for the first URL and so on, so the above command line can also be
-written as
-
- curl example.com example.net -o aa -o bb
-
-See also the --create-dirs option to create the local directories
-dynamically. Specifying the output as '-' (a single dash) passes the output to
-stdout.
-
-To suppress response bodies, you can redirect output to /dev/null:
-
- curl example.com -o /dev/null
-
-Or for Windows:
-
- curl example.com -o nul
diff --git a/docs/cmdline-opts/output.md b/docs/cmdline-opts/output.md
new file mode 100644
index 000000000..876c90c81
--- /dev/null
+++ b/docs/cmdline-opts/output.md
@@ -0,0 +1,57 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: output
+Arg: <file>
+Short: o
+Help: Write to file instead of stdout
+Category: important curl
+Added: 4.0
+Multi: append
+See-also:
+ - remote-name
+ - remote-name-all
+ - remote-header-name
+Example:
+ - -o file $URL
+ - "http://{one,two}.example.com" -o "file_#1.txt"
+ - "http://{site,host}.host[1-5].example" -o "#1_#2"
+ - -o file $URL -o file2 https://example.net
+---
+
+# `--output`
+
+Write output to <file> instead of stdout. If you are using {} or [] to fetch
+multiple documents, you should quote the URL and you can use '#' followed by a
+number in the <file> specifier. That variable is replaced with the current
+string for the URL being fetched. Like in:
+
+ curl "http://{one,two}.example.com" -o "file_#1.txt"
+
+or use several variables like:
+
+ curl "http://{site,host}.host[1-5].example" -o "#1_#2"
+
+You may use this option as many times as the number of URLs you have. For
+example, if you specify two URLs on the same command line, you can use it like
+this:
+
+ curl -o aa example.com -o bb example.net
+
+and the order of the -o options and the URLs does not matter, just that the
+first -o is for the first URL and so on, so the above command line can also be
+written as
+
+ curl example.com example.net -o aa -o bb
+
+See also the --create-dirs option to create the local directories
+dynamically. Specifying the output as '-' (a single dash) passes the output to
+stdout.
+
+To suppress response bodies, you can redirect output to /dev/null:
+
+ curl example.com -o /dev/null
+
+Or for Windows:
+
+ curl example.com -o nul
diff --git a/docs/cmdline-opts/page-footer b/docs/cmdline-opts/page-footer
deleted file mode 100644
index beae49ac1..000000000
--- a/docs/cmdline-opts/page-footer
+++ /dev/null
@@ -1,322 +0,0 @@
-.SH FILES
-.I ~/.curlrc
-.RS
-Default config file, see --config for details.
-.SH ENVIRONMENT
-The environment variables can be specified in lower case or upper case. The
-lower case version has precedence. http_proxy is an exception as it is only
-available in lower case.
-
-Using an environment variable to set the proxy has the same effect as using
-the --proxy option.
-
-.IP "http_proxy [protocol://]<host>[:port]"
-Sets the proxy server to use for HTTP.
-.IP "HTTPS_PROXY [protocol://]<host>[:port]"
-Sets the proxy server to use for HTTPS.
-.IP "[url-protocol]_PROXY [protocol://]<host>[:port]"
-Sets the proxy server to use for [url-protocol], where the protocol is a
-protocol that curl supports and as specified in a URL. FTP, FTPS, POP3, IMAP,
-SMTP, LDAP, etc.
-.IP "ALL_PROXY [protocol://]<host>[:port]"
-Sets the proxy server to use if no protocol-specific proxy is set.
-.IP "NO_PROXY <comma-separated list of hosts/domains>"
-list of host names that should not go through any proxy. If set to an asterisk
-'*' only, it matches all hosts. Each name in this list is matched as either
-a domain name which contains the hostname, or the hostname itself.
-
-This environment variable disables use of the proxy even when specified with
-the --proxy option. That is
-.B NO_PROXY=direct.example.com curl -x http://proxy.example.com
-.B http://direct.example.com
-accesses the target URL directly, and
-.B NO_PROXY=direct.example.com curl -x http://proxy.example.com
-.B http://somewhere.example.com
-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 addresses can be specified using CIDR notation: an appended slash and
-number specifies the number of "network bits" out of the address to use in the
-comparison (added in 7.86.0). For example "192.168.0.0/16" would match all
-addresses starting with "192.168".
-.IP "APPDATA <dir>"
-On Windows, this variable is used when trying to find the home directory. If
-the primary home variable are all unset.
-.IP "COLUMNS <terminal width>"
-If set, the specified number of characters is used as the terminal width when
-the alternative progress-bar is shown. If not set, curl tries to figure it out
-using other ways.
-.IP "CURL_CA_BUNDLE <file>"
-If set, it is used as the --cacert value.
-.IP "CURL_HOME <dir>"
-If set, is the first variable curl checks when trying to find its home
-directory. If not set, it continues to check *XDG_CONFIG_HOME*
-.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
-invoked. Setting a name that is not a built-in alternative makes curl stay
-with the default.
-
-SSL backend names (case-insensitive): **bearssl**, **gnutls**, **mbedtls**,
-**openssl**, **rustls**, **schannel**, **secure-transport**, **wolfssl**
-.IP "HOME <dir>"
-If set, this is used to find the home directory when that is needed. Like when
-looking for the default .curlrc. *CURL_HOME* and *XDG_CONFIG_HOME*
-have preference.
-.IP "QLOGDIR <directory name>"
-If curl was built with HTTP/3 support, setting this environment variable to a
-local directory makes 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 the ngtcp2 and quiche QUIC backends.
-.IP SHELL
-Used on VMS when trying to detect if using a **DCL** or a **unix** shell.
-.IP "SSL_CERT_DIR <dir>"
-If set, it is used as the --capath value.
-.IP "SSL_CERT_FILE <path>"
-If set, it is used as the --cacert value.
-.IP "SSLKEYLOGFILE <file name>"
-If you set this environment variable to a file name, curl stores 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
-and wolfSSL.
-.IP "USERPROFILE <dir>"
-On Windows, this variable is used when trying to find the home directory. If
-the other, primary, variable are all unset. If set, curl uses the path
-**"$USERPROFILE\\Application Data"**.
-.IP "XDG_CONFIG_HOME <dir>"
-If *CURL_HOME* is not set, this variable is checked when looking for a
-default .curlrc file.
-.SH "PROXY PROTOCOL PREFIXES"
-The proxy string may be specified with a protocol:// prefix to specify
-alternative proxy protocols. (Added in 7.21.7)
-
-If no protocol is specified in the proxy string or if the string does not
-match a supported one, the proxy is treated as an HTTP proxy.
-
-The supported proxy protocol prefixes are as follows:
-.IP "http://"
-Makes it use it as an HTTP proxy. The default if no scheme prefix is used.
-.IP "https://"
-Makes it treated as an **HTTPS** proxy.
-.IP "socks4://"
-Makes it the equivalent of --socks4
-.IP "socks4a://"
-Makes it the equivalent of --socks4a
-.IP "socks5://"
-Makes it the equivalent of --socks5
-.IP "socks5h://"
-Makes it the equivalent of --socks5-hostname
-.SH EXIT CODES
-There are a bunch of different error codes and their corresponding error
-messages that may appear under error conditions. At the time of this writing,
-the exit codes are:
-.IP 0
-Success. The operation completed successfully according to the instructions.
-.IP 1
-Unsupported protocol. This build of curl has no support for this protocol.
-.IP 2
-Failed to initialize.
-.IP 3
-URL malformed. The syntax was not correct.
-.IP 4
-A feature or option that was needed to perform the desired request was not
-enabled or was explicitly disabled at build-time. To make curl able to do
-this, you probably need another build of libcurl.
-.IP 5
-Could not resolve proxy. The given proxy host could not be resolved.
-.IP 6
-Could not resolve host. The given remote host could not be resolved.
-.IP 7
-Failed to connect to host.
-.IP 8
-Weird server reply. The server sent data curl could not parse.
-.IP 9
-FTP access denied. The server denied login or denied access to the particular
-resource or directory you wanted to reach. Most often you tried to change to a
-directory that does not exist on the server.
-.IP 10
-FTP accept failed. While waiting for the server to connect back when an active
-FTP session is used, an error code was sent over the control connection or
-similar.
-.IP 11
-FTP weird PASS reply. Curl could not parse the reply sent to the PASS request.
-.IP 12
-During an active FTP session while waiting for the server to connect back to
-curl, the timeout expired.
-.IP 13
-FTP weird PASV reply, Curl could not parse the reply sent to the PASV request.
-.IP 14
-FTP weird 227 format. Curl could not parse the 227-line the server sent.
-.IP 15
-FTP cannot use host. Could not resolve the host IP we got in the 227-line.
-.IP 16
-HTTP/2 error. A problem was detected in the HTTP2 framing layer. This is
-somewhat generic and can be one out of several problems, see the error message
-for details.
-.IP 17
-FTP could not set binary. Could not change transfer method to binary.
-.IP 18
-Partial file. Only a part of the file was transferred.
-.IP 19
-FTP could not download/access the given file, the RETR (or similar) command
-failed.
-.IP 21
-FTP quote error. A quote command returned error from the server.
-.IP 22
-HTTP page not retrieved. The requested URL was not found or returned another
-error with the HTTP error code being 400 or above. This return code only
-appears if --fail is used.
-.IP 23
-Write error. Curl could not write data to a local filesystem or similar.
-.IP 25
-FTP could not STOR file. The server denied the STOR operation, used for FTP
-uploading.
-.IP 26
-Read error. Various reading problems.
-.IP 27
-Out of memory. A memory allocation request failed.
-.IP 28
-Operation timeout. The specified time-out period was reached according to the
-conditions.
-.IP 30
-FTP PORT failed. The PORT command failed. Not all FTP servers support the PORT
-command, try doing a transfer using PASV instead!
-.IP 31
-FTP could not use REST. The REST command failed. This command is used for
-resumed FTP transfers.
-.IP 33
-HTTP range error. The range "command" did not work.
-.IP 34
-HTTP post error. Internal post-request generation error.
-.IP 35
-SSL connect error. The SSL handshaking failed.
-.IP 36
-Bad download resume. Could not continue an earlier aborted download.
-.IP 37
-FILE could not read file. Failed to open the file. Permissions?
-.IP 38
-LDAP cannot bind. LDAP bind operation failed.
-.IP 39
-LDAP search failed.
-.IP 41
-Function not found. A required LDAP function was not found.
-.IP 42
-Aborted by callback. An application told curl to abort the operation.
-.IP 43
-Internal error. A function was called with a bad parameter.
-.IP 45
-Interface error. A specified outgoing interface could not be used.
-.IP 47
-Too many redirects. When following redirects, curl hit the maximum amount.
-.IP 48
-Unknown option specified to libcurl. This indicates that you passed a weird
-option to curl that was passed on to libcurl and rejected. Read up in the
-manual!
-.IP 49
-Malformed telnet option.
-.IP 52
-The server did not reply anything, which here is considered an error.
-.IP 53
-SSL crypto engine not found.
-.IP 54
-Cannot set SSL crypto engine as default.
-.IP 55
-Failed sending network data.
-.IP 56
-Failure in receiving network data.
-.IP 58
-Problem with the local certificate.
-.IP 59
-Could not use specified SSL cipher.
-.IP 60
-Peer certificate cannot be authenticated with known CA certificates.
-.IP 61
-Unrecognized transfer encoding.
-.IP 63
-Maximum file size exceeded.
-.IP 64
-Requested FTP SSL level failed.
-.IP 65
-Sending the data requires a rewind that failed.
-.IP 66
-Failed to initialize SSL Engine.
-.IP 67
-The user name, password, or similar was not accepted and curl failed to log in.
-.IP 68
-File not found on TFTP server.
-.IP 69
-Permission problem on TFTP server.
-.IP 70
-Out of disk space on TFTP server.
-.IP 71
-Illegal TFTP operation.
-.IP 72
-Unknown TFTP transfer ID.
-.IP 73
-File already exists (TFTP).
-.IP 74
-No such user (TFTP).
-.IP 77
-Problem reading the SSL CA cert (path? access rights?).
-.IP 78
-The resource referenced in the URL does not exist.
-.IP 79
-An unspecified error occurred during the SSH session.
-.IP 80
-Failed to shut down the SSL connection.
-.IP 82
-Could not load CRL file, missing or wrong format (added in 7.19.0).
-.IP 83
-Issuer check failed (added in 7.19.0).
-.IP 84
-The FTP PRET command failed.
-.IP 85
-Mismatch of RTSP CSeq numbers.
-.IP 86
-Mismatch of RTSP Session Identifiers.
-.IP 87
-Unable to parse FTP file list.
-.IP 88
-FTP chunk callback reported error.
-.IP 89
-No connection available, the session is queued.
-.IP 90
-SSL public key does not matched pinned public key.
-.IP 91
-Invalid SSL certificate status.
-.IP 92
-Stream error in HTTP/2 framing layer.
-.IP 93
-An API function was called from inside a callback.
-.IP 94
-An authentication function returned an error.
-.IP 95
-A problem was detected in the HTTP/3 layer. This is somewhat generic and can
-be one out of several problems, see the error message for details.
-.IP 96
-QUIC connection error. This error may be caused by an SSL library error. QUIC
-is the protocol used for HTTP/3 transfers.
-.IP 97
-Proxy handshake error.
-.IP 98
-A client-side certificate is required to complete the TLS handshake.
-.IP 99
-Poll or select returned fatal error.
-.IP XX
-More error codes might appear here in future releases. The existing ones are
-meant to never change.
-.SH BUGS
-If you experience any problems with curl, submit an issue in the project's bug
-tracker on GitHub: https://github.com/curl/curl/issues
-.SH AUTHORS / CONTRIBUTORS
-Daniel Stenberg is the main author, but the whole list of contributors is
-found in the separate THANKS file.
-.SH WWW
-https://curl.se
-.SH "SEE ALSO"
-.BR ftp (1),
-.BR wget (1)
diff --git a/docs/cmdline-opts/page-header b/docs/cmdline-opts/page-header
deleted file mode 100644
index 7d14f4c45..000000000
--- a/docs/cmdline-opts/page-header
+++ /dev/null
@@ -1,258 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.\" DO NOT EDIT. Generated by the curl project gen.pl man page generator.
-.\"
-.TH curl 1 "%DATE" "curl %VERSION" "curl Manual"
-.SH NAME
-curl \- transfer a URL
-.SH SYNOPSIS
-.B curl [options / URLs]
-.SH DESCRIPTION
-**curl** is a tool for transferring data from or to a server using URLs. It
-supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS,
-IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP,
-SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.
-
-curl is powered by libcurl for all transfer-related features. See
-*libcurl(3)* for details.
-.SH URL
-The URL syntax is protocol-dependent. You find a detailed description in
-RFC 3986.
-
-If you provide a URL without a leading **protocol://** scheme, curl guesses
-what protocol you want. It then defaults to HTTP but assumes others based on
-often-used host name prefixes. For example, for host names starting with
-"ftp." curl assumes you want FTP.
-
-You can specify any amount of URLs on the command line. They are fetched in a
-sequential manner in the specified order unless you use --parallel. You can
-specify command line options and URLs mixed and in any order on the command
-line.
-
-curl attempts to reuse connections when doing multiple transfers, so that
-getting many files from the same server do not use multiple connects and setup
-handshakes. This improves speed. Connection reuse can only be done for URLs
-specified for a single command line invocation and cannot be performed between
-separate curl runs.
-
-Provide an IPv6 zone id in the URL with an escaped percentage sign. Like in
-
- "http://[fe80::3%25eth0]/"
-
-Everything provided on the command line that is not a command line option or
-its argument, curl assumes is a URL and treats it as such.
-.SH GLOBBING
-You can specify multiple URLs or parts of URLs by writing lists within braces
-or ranges within brackets. We call this "globbing".
-
-Provide a list with three different names like this:
-
- "http://site.{one,two,three}.com"
-
-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[001-100].txt" (with leading zeros)
-
- "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"
-
-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[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
-interfering with it. This also goes for other characters treated special, like
-for example '&', '?' and '*'.
-
-Switch off globbing with --globoff.
-.SH VARIABLES
-curl supports command line variables (added in 8.3.0). Set variables with
---variable name=content or --variable name@file (where "file" can be stdin if
-set to a single dash (-)).
-
-Variable contents can expanded in option parameters using "{{name}}" (without
-the quotes) if the option name is prefixed with "--expand-". This gets the
-contents of the variable "name" inserted, or a blank if the name does not
-exist as a variable. Insert "{{" verbatim in the string by prefixing it with a
-backslash, like "\\{{".
-
-You an access and expand environment variables by first importing them. You
-can select to either require the environment variable to be set or you can
-provide a default value in case it is not already set. Plain --variable %name
-imports the variable called 'name' but exits with an error if that environment
-variable is not already set. To provide a default value if it is not set, use
---variable %name=content or --variable %name@content.
-
-Example. Get the USER environment variable into the URL, fail if USER is not
-set:
-
- --variable '%USER'
- --expand-url = "https://example.com/api/{{USER}}/method"
-
-When expanding variables, curl supports a set of functions that can make the
-variable contents more convenient to use. It can trim leading and trailing
-white space with *trim*, it can output the contents as a JSON quoted string
-with *json*, URL encode the string with *url* or base64 encode it with
-*b64*. You apply function to a variable expansion, add them colon separated to
-the right side of the variable. Variable content holding null bytes that are
-not encoded when expanded cause error.
-
-Example: get the contents of a file called $HOME/.secret into a variable
-called "fix". Make sure that the content is trimmed and percent-encoded sent
-as POST data:
-
- --variable %HOME
- --expand-variable fix@{{HOME}}/.secret
- --expand-data "{{fix:trim:url}}"
- https://example.com/
-
-Command line variables and expansions were added in in 8.3.0.
-.SH OUTPUT
-If not told otherwise, curl writes the received data to stdout. It can be
-instructed to instead save that data into a local file, using the --output or
---remote-name options. If curl is given multiple URLs to transfer on the
-command line, it similarly needs multiple options for where to save them.
-
-curl does not parse or otherwise "understand" the content it gets or writes as
-output. It does no encoding or decoding, unless explicitly asked to with
-dedicated command line options.
-.SH PROTOCOLS
-curl supports numerous protocols, or put in URL terms: schemes. Your
-particular build may not support them all.
-.IP DICT
-Lets you lookup words using online dictionaries.
-.IP FILE
-Read or write local files. curl does not support accessing file:// URL
-remotely, but when running on Microsoft Windows using the native UNC approach
-works.
-.IP FTP(S)
-curl supports the File Transfer Protocol with a lot of tweaks and levers. With
-or without using TLS.
-.IP GOPHER(S)
-Retrieve files.
-.IP HTTP(S)
-curl supports HTTP with numerous options and variations. It can speak HTTP
-version 0.9, 1.0, 1.1, 2 and 3 depending on build options and the correct
-command line options.
-.IP IMAP(S)
-Using the mail reading protocol, curl can "download" emails for you. With or
-without using TLS.
-.IP LDAP(S)
-curl can do directory lookups for you, with or without TLS.
-.IP MQTT
-curl supports MQTT version 3. Downloading over MQTT equals "subscribe" to a
-topic while uploading/posting equals "publish" on a topic. MQTT over TLS is
-not supported (yet).
-.IP POP3(S)
-Downloading from a pop3 server means getting a mail. With or without using
-TLS.
-.IP RTMP(S)
-The **Realtime Messaging Protocol** is primarily used to serve streaming media
-and curl can download it.
-.IP RTSP
-curl supports RTSP 1.0 downloads.
-.IP SCP
-curl supports SSH version 2 scp transfers.
-.IP SFTP
-curl supports SFTP (draft 5) done over SSH version 2.
-.IP SMB(S)
-curl supports SMB version 1 for upload and download.
-.IP SMTP(S)
-Uploading contents to an SMTP server means sending an email. With or without
-TLS.
-.IP TELNET
-Telling curl to fetch a telnet URL starts an interactive session where it
-sends what it reads on stdin and outputs what the server sends it.
-.IP TFTP
-curl can do TFTP downloads and uploads.
-.SH "PROGRESS METER"
-curl normally displays a progress meter during operations, indicating the
-amount of transferred data, transfer speeds and estimated time left, etc. The
-progress meter displays the transfer rate in bytes per second. The suffixes
-(k, M, G, T, P) are 1024 based. For example 1k is 1024 bytes. 1M is 1048576
-bytes.
-
-curl displays this data to the terminal by default, so if you invoke curl to
-do an operation and it is about to write data to the terminal, it
-*disables* the progress meter as otherwise it would mess up the output
-mixing progress meter and response data.
-
-If you want a progress meter for HTTP POST or PUT requests, you need to
-redirect the response output to a file, using shell redirect (>), --output or
-similar.
-
-This does not apply to FTP upload as that operation does not spit out any
-response data to the terminal.
-
-If you prefer a progress "bar" instead of the regular meter, --progress-bar is
-your friend. You can also disable the progress meter completely with the
---silent option.
-.SH VERSION
-This man page describes curl %VERSION. If you use a later version, chances are
-this man page does not fully document it. If you use an earlier version, this
-document tries to include version information about which specific version
-that introduced changes.
-
-You can always learn which the latest curl version is by running
-
- curl https://curl.se/info
-
-The online version of this man page is always showing the latest incarnation:
-https://curl.se/docs/manpage.html
-.SH OPTIONS
-Options start with one or two dashes. Many of the options require an
-additional value next to them. If provided text does not start with a dash, it
-is presumed to be and treated as a URL.
-
-The short "single-dash" form of the options, -d for example, may be used with
-or without a space between it and its value, although a space is a recommended
-separator. The long "double-dash" form, --data for example, requires a space
-between it and its value.
-
-Short version options that do not need any additional values can be used
-immediately next to each other, like for example you can specify all the
-options *-O*, *-L* and *-v* at once as *-OLv*.
-
-In general, all boolean options are enabled with --**option** and yet again
-disabled with --**no-**option. That is, you use the same option name but
-prefix it with "no-". However, in this list we mostly only list and show the
-*--option* version of them.
-
-When --next is used, it resets the parser state and you start again with a
-clean option state, except for the options that are "global". Global options
-retain their values and meaning even after --next.
-
-The following options are global:
-%GLOBALS.
diff --git a/docs/cmdline-opts/parallel-immediate.d b/docs/cmdline-opts/parallel-immediate.d
deleted file mode 100644
index b534dd512..000000000
--- a/docs/cmdline-opts/parallel-immediate.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: parallel-immediate
-Help: Do not wait for multiplexing (with --parallel)
-Added: 7.68.0
-See-also: parallel parallel-max
-Category: connection curl
-Example: --parallel-immediate -Z $URL -o file1 $URL -o file2
-Multi: boolean
-Scope: global
----
-When doing parallel transfers, this option instructs curl that it should
-rather prefer opening up more connections in parallel at once rather than
-waiting to see if new transfers can be added as multiplexed streams on another
-connection.
diff --git a/docs/cmdline-opts/parallel-immediate.md b/docs/cmdline-opts/parallel-immediate.md
new file mode 100644
index 000000000..f93a355f2
--- /dev/null
+++ b/docs/cmdline-opts/parallel-immediate.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: parallel-immediate
+Help: Do not wait for multiplexing (with --parallel)
+Added: 7.68.0
+Category: connection curl
+Multi: boolean
+Scope: global
+See-also:
+ - parallel
+ - parallel-max
+Example:
+ - --parallel-immediate -Z $URL -o file1 $URL -o file2
+---
+
+# `--parallel-immediate`
+
+When doing parallel transfers, this option instructs curl that it should
+rather prefer opening up more connections in parallel at once rather than
+waiting to see if new transfers can be added as multiplexed streams on another
+connection.
diff --git a/docs/cmdline-opts/parallel-max.d b/docs/cmdline-opts/parallel-max.d
deleted file mode 100644
index cc6d32d18..000000000
--- a/docs/cmdline-opts/parallel-max.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: parallel-max
-Arg: <num>
-Help: Maximum concurrency for parallel transfers
-Added: 7.66.0
-See-also: parallel
-Category: connection curl
-Example: --parallel-max 100 -Z $URL ftp://example.com/
-Multi: single
----
-When asked to do parallel transfers, using --parallel, this option controls
-the maximum amount of transfers to do simultaneously.
-
-This option is global and does not need to be specified for each use of
---next.
-
-The default is 50.
diff --git a/docs/cmdline-opts/parallel-max.md b/docs/cmdline-opts/parallel-max.md
new file mode 100644
index 000000000..f3d2ad198
--- /dev/null
+++ b/docs/cmdline-opts/parallel-max.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: parallel-max
+Arg: <num>
+Help: Maximum concurrency for parallel transfers
+Added: 7.66.0
+Category: connection curl
+Multi: single
+See-also:
+ - parallel
+Example:
+ - --parallel-max 100 -Z $URL ftp://example.com/
+---
+
+# `--parallel-max`
+
+When asked to do parallel transfers, using --parallel, this option controls
+the maximum amount of transfers to do simultaneously.
+
+This option is global and does not need to be specified for each use of
+--next.
+
+The default is 50.
diff --git a/docs/cmdline-opts/parallel.d b/docs/cmdline-opts/parallel.d
deleted file mode 100644
index 4f698f8b3..000000000
--- a/docs/cmdline-opts/parallel.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: Z
-Long: parallel
-Help: Perform transfers in parallel
-Added: 7.66.0
-Category: connection curl
-Example: --parallel $URL -o file1 $URL -o file2
-See-also: next verbose
-Multi: boolean
-Scope: global
----
-Makes curl perform its transfers in parallel as compared to the regular serial
-manner.
diff --git a/docs/cmdline-opts/parallel.md b/docs/cmdline-opts/parallel.md
new file mode 100644
index 000000000..f67598a0b
--- /dev/null
+++ b/docs/cmdline-opts/parallel.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: Z
+Long: parallel
+Help: Perform transfers in parallel
+Added: 7.66.0
+Category: connection curl
+Multi: boolean
+Scope: global
+See-also:
+ - next
+ - verbose
+Example:
+ - --parallel $URL -o file1 $URL -o file2
+---
+
+# `--parallel`
+
+Makes curl perform its transfers in parallel as compared to the regular serial
+manner.
diff --git a/docs/cmdline-opts/pass.d b/docs/cmdline-opts/pass.d
deleted file mode 100644
index 2c0a2bef6..000000000
--- a/docs/cmdline-opts/pass.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: pass
-Arg: <phrase>
-Help: Pass phrase for the private key
-Protocols: SSH TLS
-Category: ssh tls auth
-Example: --pass secret --key file $URL
-Added: 7.9.3
-See-also: key user
-Multi: single
----
-Passphrase for the private key.
diff --git a/docs/cmdline-opts/pass.md b/docs/cmdline-opts/pass.md
new file mode 100644
index 000000000..a0d94563e
--- /dev/null
+++ b/docs/cmdline-opts/pass.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: pass
+Arg: <phrase>
+Help: Pass phrase for the private key
+Protocols: SSH TLS
+Category: ssh tls auth
+Added: 7.9.3
+Multi: single
+See-also:
+ - key
+ - user
+Example:
+ - --pass secret --key file $URL
+---
+
+# `--pass`
+
+Passphrase for the private key.
diff --git a/docs/cmdline-opts/path-as-is.d b/docs/cmdline-opts/path-as-is.d
deleted file mode 100644
index 9897d882f..000000000
--- a/docs/cmdline-opts/path-as-is.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: path-as-is
-Help: Do not squash .. sequences in URL path
-Added: 7.42.0
-Category: curl
-Example: --path-as-is https://example.com/../../etc/passwd
-See-also: request-target
-Multi: boolean
----
-Tell curl to not handle sequences of /../ or /./ in the given URL
-path. Normally curl squashes or merges them according to standards but with
-this option set you tell it not to do that.
diff --git a/docs/cmdline-opts/path-as-is.md b/docs/cmdline-opts/path-as-is.md
new file mode 100644
index 000000000..768faa50a
--- /dev/null
+++ b/docs/cmdline-opts/path-as-is.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: path-as-is
+Help: Do not squash .. sequences in URL path
+Added: 7.42.0
+Category: curl
+Multi: boolean
+See-also:
+ - request-target
+Example:
+ - --path-as-is https://example.com/../../etc/passwd
+---
+
+# `--path-as-is`
+
+Tell curl to not handle sequences of /../ or /./ in the given URL
+path. Normally curl squashes or merges them according to standards but with
+this option set you tell it not to do that.
diff --git a/docs/cmdline-opts/pinnedpubkey.d b/docs/cmdline-opts/pinnedpubkey.d
deleted file mode 100644
index d799bfac8..000000000
--- a/docs/cmdline-opts/pinnedpubkey.d
+++ /dev/null
@@ -1,38 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: pinnedpubkey
-Arg: <hashes>
-Help: FILE/HASHES Public key to verify peer against
-Protocols: TLS
-Category: tls
-Example: --pinnedpubkey keyfile $URL
-Example: --pinnedpubkey 'sha256//ce118b51897f4452dc' $URL
-Added: 7.39.0
-See-also: hostpubsha256
-Multi: single
----
-Tells curl to use the specified public key file (or hashes) to verify the
-peer. This can be a path to a file which contains a single public key in PEM
-or DER format, or any number of base64 encoded sha256 hashes preceded by
-'sha256//' and separated by ';'.
-
-When negotiating a TLS or SSL connection, the server sends a certificate
-indicating its identity. A public key is extracted from this certificate and
-if it does not exactly match the public key provided to this option, curl
-aborts the connection before sending or receiving any data.
-
-This option is independent of option --insecure. If you use both options
-together then the peer is still verified by public key.
-
-PEM/DER support:
-
-OpenSSL and GnuTLS (added in 7.39.0), wolfSSL (added in 7.43.0), mbedTLS
-(added in 7.47.0), Secure Transport macOS 10.7+/iOS 10+ (7.54.1), Schannel
-(7.58.1)
-
-sha256 support:
-
-OpenSSL, GnuTLS and wolfSSL (added in 7.44.0), mbedTLS (added in 7.47.0),
-Secure Transport macOS 10.7+/iOS 10+ (7.54.1), Schannel (7.58.1)
-
-Other SSL backends not supported.
diff --git a/docs/cmdline-opts/pinnedpubkey.md b/docs/cmdline-opts/pinnedpubkey.md
new file mode 100644
index 000000000..cdbd31dca
--- /dev/null
+++ b/docs/cmdline-opts/pinnedpubkey.md
@@ -0,0 +1,44 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: pinnedpubkey
+Arg: <hashes>
+Help: FILE/HASHES Public key to verify peer against
+Protocols: TLS
+Category: tls
+Added: 7.39.0
+Multi: single
+See-also:
+ - hostpubsha256
+Example:
+ - --pinnedpubkey keyfile $URL
+ - --pinnedpubkey 'sha256//ce118b51897f4452dc' $URL
+---
+
+# `--pinnedpubkey`
+
+Tells curl to use the specified public key file (or hashes) to verify the
+peer. This can be a path to a file which contains a single public key in PEM
+or DER format, or any number of base64 encoded sha256 hashes preceded by
+'sha256//' and separated by ';'.
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. A public key is extracted from this certificate and
+if it does not exactly match the public key provided to this option, curl
+aborts the connection before sending or receiving any data.
+
+This option is independent of option --insecure. If you use both options
+together then the peer is still verified by public key.
+
+PEM/DER support:
+
+OpenSSL and GnuTLS (added in 7.39.0), wolfSSL (added in 7.43.0), mbedTLS
+(added in 7.47.0), Secure Transport macOS 10.7+/iOS 10+ (7.54.1), Schannel
+(7.58.1)
+
+sha256 support:
+
+OpenSSL, GnuTLS and wolfSSL (added in 7.44.0), mbedTLS (added in 7.47.0),
+Secure Transport macOS 10.7+/iOS 10+ (7.54.1), Schannel (7.58.1)
+
+Other SSL backends not supported.
diff --git a/docs/cmdline-opts/post301.d b/docs/cmdline-opts/post301.d
deleted file mode 100644
index d067fc8cc..000000000
--- a/docs/cmdline-opts/post301.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: post301
-Help: Do not switch to GET after following a 301
-Protocols: HTTP
-See-also: post302 post303 location
-Added: 7.17.1
-Category: http post
-Example: --post301 --location -d "data" $URL
-Multi: boolean
----
-Tells curl to respect RFC 7231/6.4.2 and not convert POST requests into GET
-requests when following a 301 redirection. The non-RFC behavior is ubiquitous
-in web browsers, so curl does the conversion by default to maintain
-consistency. However, a server may require a POST to remain a POST after such
-a redirection. This option is meaningful only when using --location.
diff --git a/docs/cmdline-opts/post301.md b/docs/cmdline-opts/post301.md
new file mode 100644
index 000000000..5a7ce0632
--- /dev/null
+++ b/docs/cmdline-opts/post301.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: post301
+Help: Do not switch to GET after following a 301
+Protocols: HTTP
+Added: 7.17.1
+Category: http post
+Multi: boolean
+See-also:
+ - post302
+ - post303
+ - location
+Example:
+ - --post301 --location -d "data" $URL
+---
+
+# `--post301`
+
+Tells curl to respect RFC 7231/6.4.2 and not convert POST requests into GET
+requests when following a 301 redirection. The non-RFC behavior is ubiquitous
+in web browsers, so curl does the conversion by default to maintain
+consistency. However, a server may require a POST to remain a POST after such
+a redirection. This option is meaningful only when using --location.
diff --git a/docs/cmdline-opts/post302.d b/docs/cmdline-opts/post302.d
deleted file mode 100644
index b7190ce0f..000000000
--- a/docs/cmdline-opts/post302.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: post302
-Help: Do not switch to GET after following a 302
-Protocols: HTTP
-See-also: post301 post303 location
-Added: 7.19.1
-Category: http post
-Example: --post302 --location -d "data" $URL
-Multi: boolean
----
-Tells curl to respect RFC 7231/6.4.3 and not convert POST requests into GET
-requests when following a 302 redirection. The non-RFC behavior is ubiquitous
-in web browsers, so curl does the conversion by default to maintain
-consistency. However, a server may require a POST to remain a POST after such
-a redirection. This option is meaningful only when using --location.
diff --git a/docs/cmdline-opts/post302.md b/docs/cmdline-opts/post302.md
new file mode 100644
index 000000000..7eefc0cd6
--- /dev/null
+++ b/docs/cmdline-opts/post302.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: post302
+Help: Do not switch to GET after following a 302
+Protocols: HTTP
+Added: 7.19.1
+Category: http post
+Multi: boolean
+See-also:
+ - post301
+ - post303
+ - location
+Example:
+ - --post302 --location -d "data" $URL
+---
+
+# `--post302`
+
+Tells curl to respect RFC 7231/6.4.3 and not convert POST requests into GET
+requests when following a 302 redirection. The non-RFC behavior is ubiquitous
+in web browsers, so curl does the conversion by default to maintain
+consistency. However, a server may require a POST to remain a POST after such
+a redirection. This option is meaningful only when using --location.
diff --git a/docs/cmdline-opts/post303.d b/docs/cmdline-opts/post303.d
deleted file mode 100644
index 52d440c45..000000000
--- a/docs/cmdline-opts/post303.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: post303
-Help: Do not switch to GET after following a 303
-Protocols: HTTP
-See-also: post302 post301 location
-Added: 7.26.0
-Category: http post
-Example: --post303 --location -d "data" $URL
-Multi: boolean
----
-Tells curl to violate RFC 7231/6.4.4 and not convert POST requests into GET
-requests when following 303 redirections. A server may require a POST to
-remain a POST after a 303 redirection. This option is meaningful only when
-using --location.
diff --git a/docs/cmdline-opts/post303.md b/docs/cmdline-opts/post303.md
new file mode 100644
index 000000000..4ea749c2e
--- /dev/null
+++ b/docs/cmdline-opts/post303.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: post303
+Help: Do not switch to GET after following a 303
+Protocols: HTTP
+Added: 7.26.0
+Category: http post
+Multi: boolean
+See-also:
+ - post302
+ - post301
+ - location
+Example:
+ - --post303 --location -d "data" $URL
+---
+
+# `--post303`
+
+Tells curl to violate RFC 7231/6.4.4 and not convert POST requests into GET
+requests when following 303 redirections. A server may require a POST to
+remain a POST after a 303 redirection. This option is meaningful only when
+using --location.
diff --git a/docs/cmdline-opts/preproxy.d b/docs/cmdline-opts/preproxy.d
deleted file mode 100644
index b55c1d47a..000000000
--- a/docs/cmdline-opts/preproxy.d
+++ /dev/null
@@ -1,26 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: preproxy
-Arg: [protocol://]host[:port]
-Help: Use this proxy first
-Added: 7.52.0
-Category: proxy
-Example: --preproxy socks5://proxy.example -x http://http.example $URL
-See-also: proxy socks5
-Multi: single
----
-Use the specified SOCKS proxy before connecting to an HTTP or HTTPS --proxy. In
-such a case curl first connects to the SOCKS proxy and then connects (through
-SOCKS) to the HTTP or HTTPS proxy. Hence pre proxy.
-
-The pre proxy string should be specified with a protocol:// prefix to specify
-alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
-socks5h:// to request the specific SOCKS version to be used. No protocol
-specified makes curl default to SOCKS4.
-
-If the port number is not specified in the proxy string, it is assumed to be
-1080.
-
-User and password that might be provided in the proxy string are URL decoded
-by curl. This allows you to pass in special characters such as @ by using %40
-or pass in a colon with %3a.
diff --git a/docs/cmdline-opts/preproxy.md b/docs/cmdline-opts/preproxy.md
new file mode 100644
index 000000000..dabccfc5e
--- /dev/null
+++ b/docs/cmdline-opts/preproxy.md
@@ -0,0 +1,33 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: preproxy
+Arg: [protocol://]host[:port]
+Help: Use this proxy first
+Added: 7.52.0
+Category: proxy
+Multi: single
+See-also:
+ - proxy
+ - socks5
+Example:
+ - --preproxy socks5://proxy.example -x http://http.example $URL
+---
+
+# `--preproxy`
+
+Use the specified SOCKS proxy before connecting to an HTTP or HTTPS --proxy. In
+such a case curl first connects to the SOCKS proxy and then connects (through
+SOCKS) to the HTTP or HTTPS proxy. Hence pre proxy.
+
+The pre proxy string should be specified with a protocol:// prefix to specify
+alternative proxy protocols. Use socks4://, socks4a://, socks5:// or
+socks5h:// to request the specific SOCKS version to be used. No protocol
+specified makes curl default to SOCKS4.
+
+If the port number is not specified in the proxy string, it is assumed to be
+1080.
+
+User and password that might be provided in the proxy string are URL decoded
+by curl. This allows you to pass in special characters such as @ by using %40
+or pass in a colon with %3a.
diff --git a/docs/cmdline-opts/progress-bar.d b/docs/cmdline-opts/progress-bar.d
deleted file mode 100644
index fee170979..000000000
--- a/docs/cmdline-opts/progress-bar.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: #
-Long: progress-bar
-Help: Display transfer progress as a bar
-Category: verbose
-Example: -# -O $URL
-Added: 5.10
-See-also: styled-output
-Multi: boolean
-Scope: global
----
-Make curl display transfer progress as a simple progress bar instead of the
-standard, more informational, meter.
-
-This progress bar draws a single line of '#' characters across the screen and
-shows a percentage if the transfer size is known. For transfers without a
-known size, there is a space ship (-=o=-) that moves back and forth but only
-while data is being transferred, with a set of flying hash sign symbols on
-top.
diff --git a/docs/cmdline-opts/progress-bar.md b/docs/cmdline-opts/progress-bar.md
new file mode 100644
index 000000000..7b9c599b9
--- /dev/null
+++ b/docs/cmdline-opts/progress-bar.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: #
+Long: progress-bar
+Help: Display transfer progress as a bar
+Category: verbose
+Added: 5.10
+Multi: boolean
+Scope: global
+See-also:
+ - styled-output
+Example:
+ - -# -O $URL
+---
+
+# `--progress-bar`
+
+Make curl display transfer progress as a simple progress bar instead of the
+standard, more informational, meter.
+
+This progress bar draws a single line of '#' characters across the screen and
+shows a percentage if the transfer size is known. For transfers without a
+known size, there is a space ship (-=o=-) that moves back and forth but only
+while data is being transferred, with a set of flying hash sign symbols on
+top.
diff --git a/docs/cmdline-opts/proto-default.d b/docs/cmdline-opts/proto-default.d
deleted file mode 100644
index d5b4bcd10..000000000
--- a/docs/cmdline-opts/proto-default.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proto-default
-Help: Use PROTOCOL for any URL missing a scheme
-Arg: <protocol>
-Added: 7.45.0
-Category: connection curl
-Example: --proto-default https ftp.example.com
-See-also: proto proto-redir
-Multi: single
----
-Tells curl to use *protocol* for any URL missing a scheme name.
-
-An unknown or unsupported protocol causes error
-*CURLE_UNSUPPORTED_PROTOCOL* (1).
-
-This option does not change the default proxy protocol (http).
-
-Without this option set, curl guesses protocol based on the host name, see
---url for details.
diff --git a/docs/cmdline-opts/proto-default.md b/docs/cmdline-opts/proto-default.md
new file mode 100644
index 000000000..69a4c2cbe
--- /dev/null
+++ b/docs/cmdline-opts/proto-default.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proto-default
+Help: Use PROTOCOL for any URL missing a scheme
+Arg: <protocol>
+Added: 7.45.0
+Category: connection curl
+Multi: single
+See-also:
+ - proto
+ - proto-redir
+Example:
+ - --proto-default https ftp.example.com
+---
+
+# `--proto-default`
+
+Tells curl to use *protocol* for any URL missing a scheme name.
+
+An unknown or unsupported protocol causes error
+*CURLE_UNSUPPORTED_PROTOCOL* (1).
+
+This option does not change the default proxy protocol (http).
+
+Without this option set, curl guesses protocol based on the host name, see
+--url for details.
diff --git a/docs/cmdline-opts/proto-redir.d b/docs/cmdline-opts/proto-redir.d
deleted file mode 100644
index dec871614..000000000
--- a/docs/cmdline-opts/proto-redir.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proto-redir
-Arg: <protocols>
-Help: Enable/disable PROTOCOLS on redirect
-Added: 7.20.2
-Category: connection curl
-Example: --proto-redir =http,https $URL
-See-also: proto
-Multi: single
----
-Tells curl to limit what protocols it may use on redirect. Protocols denied by
---proto are not overridden by this option. See --proto for how protocols are
-represented.
-
-Example, allow only HTTP and HTTPS on redirect:
-
- curl --proto-redir -all,http,https http://example.com
-
-By default curl only allows HTTP, HTTPS, FTP and FTPS on redirects (added in
-7.65.2). Specifying *all* or *+all* enables all protocols on redirects, which
-is not good for security.
diff --git a/docs/cmdline-opts/proto-redir.md b/docs/cmdline-opts/proto-redir.md
new file mode 100644
index 000000000..f0a307a17
--- /dev/null
+++ b/docs/cmdline-opts/proto-redir.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proto-redir
+Arg: <protocols>
+Help: Enable/disable PROTOCOLS on redirect
+Added: 7.20.2
+Category: connection curl
+Multi: single
+See-also:
+ - proto
+Example:
+ - --proto-redir =http,https $URL
+---
+
+# `--proto-redir`
+
+Tells curl to limit what protocols it may use on redirect. Protocols denied by
+--proto are not overridden by this option. See --proto for how protocols are
+represented.
+
+Example, allow only HTTP and HTTPS on redirect:
+
+ curl --proto-redir -all,http,https http://example.com
+
+By default curl only allows HTTP, HTTPS, FTP and FTPS on redirects (added in
+7.65.2). Specifying *all* or *+all* enables all protocols on redirects, which
+is not good for security.
diff --git a/docs/cmdline-opts/proto.d b/docs/cmdline-opts/proto.d
deleted file mode 100644
index ac024bf42..000000000
--- a/docs/cmdline-opts/proto.d
+++ /dev/null
@@ -1,48 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proto
-Arg: <protocols>
-Help: Enable/disable PROTOCOLS
-See-also: proto-redir proto-default
-Added: 7.20.2
-Category: connection curl
-Example: --proto =http,https,sftp $URL
-Multi: single
----
-Tells curl to limit what protocols it may use for transfers. Protocols are
-evaluated left to right, are comma separated, and are each a protocol name or
-'all', optionally prefixed by zero or more modifiers. Available modifiers are:
-.RS
-.TP 3
-.B +
-Permit this protocol in addition to protocols already permitted (this is
-the default if no modifier is used).
-.TP
-.B -
-Deny this protocol, removing it from the list of protocols already permitted.
-.TP
-.B =
-Permit only this protocol (ignoring the list already permitted), though
-subject to later modification by subsequent entries in the comma separated
-list.
-.RE
-.IP
-For example:
-.RS
-.TP 15
-.B --proto -ftps
-uses the default protocols, but disables ftps
-.TP
-.B --proto -all,https,+http
-only enables http and https
-.TP
-.B --proto =http,https
-also only enables http and https
-.RE
-.IP
-Unknown and disabled protocols produce a warning. This allows scripts to
-safely rely on being able to disable potentially dangerous protocols, without
-relying upon support for that protocol being built into curl to avoid an error.
-
-This option can be used multiple times, in which case the effect is the same
-as concatenating the protocols into one instance of the option.
diff --git a/docs/cmdline-opts/proto.md b/docs/cmdline-opts/proto.md
new file mode 100644
index 000000000..a70455449
--- /dev/null
+++ b/docs/cmdline-opts/proto.md
@@ -0,0 +1,48 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proto
+Arg: <protocols>
+Help: Enable/disable PROTOCOLS
+Added: 7.20.2
+Category: connection curl
+Multi: single
+See-also:
+ - proto-redir
+ - proto-default
+Example:
+ - --proto =http,https,sftp $URL
+---
+
+# `--proto`
+
+Tells curl to limit what protocols it may use for transfers. Protocols are
+evaluated left to right, are comma separated, and are each a protocol name or
+'all', optionally prefixed by zero or more modifiers. Available modifiers are:
+
+## +
+Permit this protocol in addition to protocols already permitted (this is
+the default if no modifier is used).
+
+## -
+Deny this protocol, removing it from the list of protocols already permitted.
+
+## =
+Permit only this protocol (ignoring the list already permitted), though
+subject to later modification by subsequent entries in the comma separated
+list.
+
+##
+
+For example: --proto -ftps uses the default protocols, but disables ftps
+
+--proto -all,https,+http only enables http and https
+
+--proto =http,https also only enables http and https
+
+Unknown and disabled protocols produce a warning. This allows scripts to
+safely rely on being able to disable potentially dangerous protocols, without
+relying upon support for that protocol being built into curl to avoid an error.
+
+This option can be used multiple times, in which case the effect is the same
+as concatenating the protocols into one instance of the option.
diff --git a/docs/cmdline-opts/proxy-anyauth.d b/docs/cmdline-opts/proxy-anyauth.d
deleted file mode 100644
index fa460876e..000000000
--- a/docs/cmdline-opts/proxy-anyauth.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-anyauth
-Help: Pick any proxy authentication method
-Added: 7.13.2
-See-also: proxy proxy-basic proxy-digest
-Category: proxy auth
-Example: --proxy-anyauth --proxy-user user:passwd -x proxy $URL
-Multi: mutex
----
-Tells curl to pick a suitable authentication method when communicating with
-the given HTTP proxy. This might cause an extra request/response round-trip.
diff --git a/docs/cmdline-opts/proxy-anyauth.md b/docs/cmdline-opts/proxy-anyauth.md
new file mode 100644
index 000000000..dcb3952ef
--- /dev/null
+++ b/docs/cmdline-opts/proxy-anyauth.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-anyauth
+Help: Pick any proxy authentication method
+Added: 7.13.2
+Category: proxy auth
+Multi: mutex
+See-also:
+ - proxy
+ - proxy-basic
+ - proxy-digest
+Example:
+ - --proxy-anyauth --proxy-user user:passwd -x proxy $URL
+---
+
+# `--proxy-anyauth`
+
+Tells curl to pick a suitable authentication method when communicating with
+the given HTTP proxy. This might cause an extra request/response round-trip.
diff --git a/docs/cmdline-opts/proxy-basic.d b/docs/cmdline-opts/proxy-basic.d
deleted file mode 100644
index ff56631f7..000000000
--- a/docs/cmdline-opts/proxy-basic.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-basic
-Help: Use Basic authentication on the proxy
-See-also: proxy proxy-anyauth proxy-digest
-Category: proxy auth
-Example: --proxy-basic --proxy-user user:passwd -x proxy $URL
-Added: 7.12.0
-Multi: mutex
----
-Tells curl to use HTTP Basic authentication when communicating with the given
-proxy. Use --basic for enabling HTTP Basic with a remote host. Basic is the
-default authentication method curl uses with proxies.
diff --git a/docs/cmdline-opts/proxy-basic.md b/docs/cmdline-opts/proxy-basic.md
new file mode 100644
index 000000000..4262a74f9
--- /dev/null
+++ b/docs/cmdline-opts/proxy-basic.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-basic
+Help: Use Basic authentication on the proxy
+Category: proxy auth
+Added: 7.12.0
+Multi: mutex
+See-also:
+ - proxy
+ - proxy-anyauth
+ - proxy-digest
+Example:
+ - --proxy-basic --proxy-user user:passwd -x proxy $URL
+---
+
+# `--proxy-basic`
+
+Tells curl to use HTTP Basic authentication when communicating with the given
+proxy. Use --basic for enabling HTTP Basic with a remote host. Basic is the
+default authentication method curl uses with proxies.
diff --git a/docs/cmdline-opts/proxy-ca-native.d b/docs/cmdline-opts/proxy-ca-native.d
deleted file mode 100644
index aab4fcabc..000000000
--- a/docs/cmdline-opts/proxy-ca-native.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-ca-native
-Help: Use CA certificates from the native OS for proxy
-Protocols: TLS
-Category: tls
-See-also: cacert capath insecure
-Example: --ca-native $URL
-Added: 8.2.0
-Multi: boolean
----
-Tells curl to use the CA store from the native operating system to verify the
-HTTPS proxy. By default, curl uses a CA store provided in a single file or
-directory, but when using this option it interfaces the operating system's own
-vault.
-
-This option only works for curl on Windows when built to use OpenSSL. When
-curl on Windows is built to use Schannel, this feature is implied and curl
-then only uses the native CA store.
-
-curl built with wolfSSL also supports this option (added in 8.3.0).
diff --git a/docs/cmdline-opts/proxy-ca-native.md b/docs/cmdline-opts/proxy-ca-native.md
new file mode 100644
index 000000000..071d04f93
--- /dev/null
+++ b/docs/cmdline-opts/proxy-ca-native.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-ca-native
+Help: Use CA certificates from the native OS for proxy
+Protocols: TLS
+Category: tls
+Added: 8.2.0
+Multi: boolean
+See-also:
+ - cacert
+ - capath
+ - insecure
+Example:
+ - --ca-native $URL
+---
+
+# `--proxy-ca-native`
+
+Tells curl to use the CA store from the native operating system to verify the
+HTTPS proxy. By default, curl uses a CA store provided in a single file or
+directory, but when using this option it interfaces the operating system's own
+vault.
+
+This option works for curl on Windows when built to use OpenSSL, wolfSSL
+(added in 8.3.0) or GnuTLS (added in 8.5.0). When curl on Windows is built to
+use Schannel, this feature is implied and curl then only uses the native CA
+store.
diff --git a/docs/cmdline-opts/proxy-cacert.d b/docs/cmdline-opts/proxy-cacert.d
deleted file mode 100644
index 45dc3f301..000000000
--- a/docs/cmdline-opts/proxy-cacert.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-cacert
-Help: CA certificate to verify peer against for proxy
-Arg: <file>
-Added: 7.52.0
-See-also: proxy-capath cacert capath proxy
-Category: proxy tls
-Example: --proxy-cacert CA-file.txt -x https://proxy $URL
-Multi: single
----
-Same as --cacert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-cacert.md b/docs/cmdline-opts/proxy-cacert.md
new file mode 100644
index 000000000..b3a038a59
--- /dev/null
+++ b/docs/cmdline-opts/proxy-cacert.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-cacert
+Help: CA certificate to verify peer against for proxy
+Arg: <file>
+Added: 7.52.0
+Category: proxy tls
+Multi: single
+See-also:
+ - proxy-capath
+ - cacert
+ - capath
+ - proxy
+Example:
+ - --proxy-cacert CA-file.txt -x https://proxy $URL
+---
+
+# `--proxy-cacert`
+
+Same as --cacert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-capath.d b/docs/cmdline-opts/proxy-capath.d
deleted file mode 100644
index 309f9408a..000000000
--- a/docs/cmdline-opts/proxy-capath.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-capath
-Help: CA directory to verify peer against for proxy
-Arg: <dir>
-Added: 7.52.0
-See-also: proxy-cacert proxy capath
-Category: proxy tls
-Example: --proxy-capath /local/directory -x https://proxy $URL
-Multi: single
----
-Same as --capath but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-capath.md b/docs/cmdline-opts/proxy-capath.md
new file mode 100644
index 000000000..62a25a0df
--- /dev/null
+++ b/docs/cmdline-opts/proxy-capath.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-capath
+Help: CA directory to verify peer against for proxy
+Arg: <dir>
+Added: 7.52.0
+Category: proxy tls
+Multi: single
+See-also:
+ - proxy-cacert
+ - proxy
+ - capath
+Example:
+ - --proxy-capath /local/directory -x https://proxy $URL
+---
+
+# `--proxy-capath`
+
+Same as --capath but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-cert-type.d b/docs/cmdline-opts/proxy-cert-type.d
deleted file mode 100644
index 4ab38f5a8..000000000
--- a/docs/cmdline-opts/proxy-cert-type.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-cert-type
-Arg: <type>
-Added: 7.52.0
-Help: Client certificate type for HTTPS proxy
-Category: proxy tls
-Example: --proxy-cert-type PEM --proxy-cert file -x https://proxy $URL
-See-also: proxy-cert
-Multi: single
----
-Same as --cert-type but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-cert-type.md b/docs/cmdline-opts/proxy-cert-type.md
new file mode 100644
index 000000000..3f46bb618
--- /dev/null
+++ b/docs/cmdline-opts/proxy-cert-type.md
@@ -0,0 +1,18 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-cert-type
+Arg: <type>
+Added: 7.52.0
+Help: Client certificate type for HTTPS proxy
+Category: proxy tls
+Multi: single
+See-also:
+ - proxy-cert
+Example:
+ - --proxy-cert-type PEM --proxy-cert file -x https://proxy $URL
+---
+
+# `--proxy-cert-type`
+
+Same as --cert-type but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-cert.d b/docs/cmdline-opts/proxy-cert.d
deleted file mode 100644
index 2a869deb0..000000000
--- a/docs/cmdline-opts/proxy-cert.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-cert
-Arg: <cert[:passwd]>
-Help: Set client certificate for proxy
-Added: 7.52.0
-Category: proxy tls
-Example: --proxy-cert file -x https://proxy $URL
-See-also: proxy-cert-type
-Multi: single
----
-Same as --cert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-cert.md b/docs/cmdline-opts/proxy-cert.md
new file mode 100644
index 000000000..3068f3cd1
--- /dev/null
+++ b/docs/cmdline-opts/proxy-cert.md
@@ -0,0 +1,18 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-cert
+Arg: <cert[:passwd]>
+Help: Set client certificate for proxy
+Added: 7.52.0
+Category: proxy tls
+Multi: single
+See-also:
+ - proxy-cert-type
+Example:
+ - --proxy-cert file -x https://proxy $URL
+---
+
+# `--proxy-cert`
+
+Same as --cert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-ciphers.d b/docs/cmdline-opts/proxy-ciphers.d
deleted file mode 100644
index 5879f397e..000000000
--- a/docs/cmdline-opts/proxy-ciphers.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-ciphers
-Arg: <list>
-Help: SSL ciphers to use for proxy
-Added: 7.52.0
-Category: proxy tls
-Example: --proxy-ciphers ECDHE-ECDSA-AES256-CCM8 -x https://proxy $URL
-See-also: ciphers curves proxy
-Multi: single
----
-Same as --ciphers but used in HTTPS proxy context.
-
-Specifies which ciphers to use in the connection to the HTTPS proxy. The list
-of ciphers must specify valid ciphers. Read up on SSL cipher list details on
-this URL:
-
-https://curl.se/docs/ssl-ciphers.html
diff --git a/docs/cmdline-opts/proxy-ciphers.md b/docs/cmdline-opts/proxy-ciphers.md
new file mode 100644
index 000000000..065d44953
--- /dev/null
+++ b/docs/cmdline-opts/proxy-ciphers.md
@@ -0,0 +1,26 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-ciphers
+Arg: <list>
+Help: SSL ciphers to use for proxy
+Added: 7.52.0
+Category: proxy tls
+Multi: single
+See-also:
+ - ciphers
+ - curves
+ - proxy
+Example:
+ - --proxy-ciphers ECDHE-ECDSA-AES256-CCM8 -x https://proxy $URL
+---
+
+# `--proxy-ciphers`
+
+Same as --ciphers but used in HTTPS proxy context.
+
+Specifies which ciphers to use in the connection to the HTTPS proxy. The list
+of ciphers must specify valid ciphers. Read up on SSL cipher list details on
+this URL:
+
+https://curl.se/docs/ssl-ciphers.html
diff --git a/docs/cmdline-opts/proxy-crlfile.d b/docs/cmdline-opts/proxy-crlfile.d
deleted file mode 100644
index 1a8fdf25d..000000000
--- a/docs/cmdline-opts/proxy-crlfile.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-crlfile
-Arg: <file>
-Help: Set a CRL list for proxy
-Added: 7.52.0
-Category: proxy tls
-Example: --proxy-crlfile rejects.txt -x https://proxy $URL
-See-also: crlfile proxy
-Multi: single
----
-Same as --crlfile but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-crlfile.md b/docs/cmdline-opts/proxy-crlfile.md
new file mode 100644
index 000000000..ab47fb0a0
--- /dev/null
+++ b/docs/cmdline-opts/proxy-crlfile.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-crlfile
+Arg: <file>
+Help: Set a CRL list for proxy
+Added: 7.52.0
+Category: proxy tls
+Multi: single
+See-also:
+ - crlfile
+ - proxy
+Example:
+ - --proxy-crlfile rejects.txt -x https://proxy $URL
+---
+
+# `--proxy-crlfile`
+
+Same as --crlfile but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-digest.d b/docs/cmdline-opts/proxy-digest.d
deleted file mode 100644
index c5cb19c48..000000000
--- a/docs/cmdline-opts/proxy-digest.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-digest
-Help: Use Digest authentication on the proxy
-See-also: proxy proxy-anyauth proxy-basic
-Category: proxy tls
-Example: --proxy-digest --proxy-user user:passwd -x proxy $URL
-Added: 7.12.0
-Multi: mutex
----
-Tells curl to use HTTP Digest authentication when communicating with the given
-proxy. Use --digest for enabling HTTP Digest with a remote host.
diff --git a/docs/cmdline-opts/proxy-digest.md b/docs/cmdline-opts/proxy-digest.md
new file mode 100644
index 000000000..052b67b7f
--- /dev/null
+++ b/docs/cmdline-opts/proxy-digest.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-digest
+Help: Use Digest authentication on the proxy
+Category: proxy tls
+Added: 7.12.0
+Multi: mutex
+See-also:
+ - proxy
+ - proxy-anyauth
+ - proxy-basic
+Example:
+ - --proxy-digest --proxy-user user:passwd -x proxy $URL
+---
+
+# `--proxy-digest`
+
+Tells curl to use HTTP Digest authentication when communicating with the given
+proxy. Use --digest for enabling HTTP Digest with a remote host.
diff --git a/docs/cmdline-opts/proxy-header.d b/docs/cmdline-opts/proxy-header.d
deleted file mode 100644
index 06ae3bcba..000000000
--- a/docs/cmdline-opts/proxy-header.d
+++ /dev/null
@@ -1,32 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-header
-Arg: <header/@file>
-Help: Pass custom header(s) to proxy
-Protocols: HTTP
-Added: 7.37.0
-Category: proxy
-Example: --proxy-header "X-First-Name: Joe" -x http://proxy $URL
-Example: --proxy-header "User-Agent: surprise" -x http://proxy $URL
-Example: --proxy-header "Host:" -x http://proxy $URL
-See-also: proxy
-Multi: append
----
-Extra header to include in the request when sending HTTP to a proxy. You may
-specify any number of extra headers. This is the equivalent option to --header
-but is for proxy communication only like in CONNECT requests when you want a
-separate header sent to the proxy to what is sent to the actual remote host.
-
-curl makes sure that each header you add/replace is sent with the proper
-end-of-line marker, you should thus **not** add that as a part of the header
-content: do not add newlines or carriage returns, they only mess things up for
-you.
-
-Headers specified with this option are not included in requests that curl
-knows are not be sent to a proxy.
-
-This option can take an argument in @filename style, which then adds a header
-for each line in the input file (added in 7.55.0). Using @- makes curl read
-the headers from stdin.
-
-This option can be used multiple times to add/replace/remove multiple headers.
diff --git a/docs/cmdline-opts/proxy-header.md b/docs/cmdline-opts/proxy-header.md
new file mode 100644
index 000000000..0361fdff5
--- /dev/null
+++ b/docs/cmdline-opts/proxy-header.md
@@ -0,0 +1,38 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-header
+Arg: <header/@file>
+Help: Pass custom header(s) to proxy
+Protocols: HTTP
+Added: 7.37.0
+Category: proxy
+Multi: append
+See-also:
+ - proxy
+Example:
+ - --proxy-header "X-First-Name: Joe" -x http://proxy $URL
+ - --proxy-header "User-Agent: surprise" -x http://proxy $URL
+ - --proxy-header "Host:" -x http://proxy $URL
+---
+
+# `--proxy-header`
+
+Extra header to include in the request when sending HTTP to a proxy. You may
+specify any number of extra headers. This is the equivalent option to --header
+but is for proxy communication only like in CONNECT requests when you want a
+separate header sent to the proxy to what is sent to the actual remote host.
+
+curl makes sure that each header you add/replace is sent with the proper
+end-of-line marker, you should thus **not** add that as a part of the header
+content: do not add newlines or carriage returns, they only mess things up for
+you.
+
+Headers specified with this option are not included in requests that curl
+knows are not be sent to a proxy.
+
+This option can take an argument in @filename style, which then adds a header
+for each line in the input file (added in 7.55.0). Using @- makes curl read
+the headers from stdin.
+
+This option can be used multiple times to add/replace/remove multiple headers.
diff --git a/docs/cmdline-opts/proxy-http2.d b/docs/cmdline-opts/proxy-http2.d
deleted file mode 100644
index 58f55e74d..000000000
--- a/docs/cmdline-opts/proxy-http2.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-http2
-Tags: Versions HTTP/2
-Protocols: HTTP
-Added: 8.1.0
-Mutexed:
-Requires: HTTP/2
-See-also: proxy
-Help: Use HTTP/2 with HTTPS proxy
-Category: http proxy
-Example: --proxy-http2 -x proxy $URL
-Multi: boolean
----
-Tells curl to try negotiate HTTP version 2 with an HTTPS proxy. The proxy might
-still only offer HTTP/1 and then curl sticks to using that version.
-
-This has no effect for any other kinds of proxies.
diff --git a/docs/cmdline-opts/proxy-http2.md b/docs/cmdline-opts/proxy-http2.md
new file mode 100644
index 000000000..a5745f086
--- /dev/null
+++ b/docs/cmdline-opts/proxy-http2.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-http2
+Tags: Versions HTTP/2
+Protocols: HTTP
+Added: 8.1.0
+Mutexed:
+Requires: HTTP/2
+Help: Use HTTP/2 with HTTPS proxy
+Category: http proxy
+Multi: boolean
+See-also:
+ - proxy
+Example:
+ - --proxy-http2 -x proxy $URL
+---
+
+# `--proxy-http2`
+
+Tells curl to try negotiate HTTP version 2 with an HTTPS proxy. The proxy might
+still only offer HTTP/1 and then curl sticks to using that version.
+
+This has no effect for any other kinds of proxies.
diff --git a/docs/cmdline-opts/proxy-insecure.d b/docs/cmdline-opts/proxy-insecure.d
deleted file mode 100644
index beb8c2531..000000000
--- a/docs/cmdline-opts/proxy-insecure.d
+++ /dev/null
@@ -1,11 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-insecure
-Help: Do HTTPS proxy connections without verifying the proxy
-Added: 7.52.0
-Category: proxy tls
-Example: --proxy-insecure -x https://proxy $URL
-See-also: proxy insecure
-Multi: boolean
----
-Same as --insecure but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-insecure.md b/docs/cmdline-opts/proxy-insecure.md
new file mode 100644
index 000000000..3e174428a
--- /dev/null
+++ b/docs/cmdline-opts/proxy-insecure.md
@@ -0,0 +1,18 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-insecure
+Help: Do HTTPS proxy connections without verifying the proxy
+Added: 7.52.0
+Category: proxy tls
+Multi: boolean
+See-also:
+ - proxy
+ - insecure
+Example:
+ - --proxy-insecure -x https://proxy $URL
+---
+
+# `--proxy-insecure`
+
+Same as --insecure but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-key-type.d b/docs/cmdline-opts/proxy-key-type.d
deleted file mode 100644
index 3fd11f3a3..000000000
--- a/docs/cmdline-opts/proxy-key-type.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-key-type
-Arg: <type>
-Help: Private key file type for proxy
-Added: 7.52.0
-Category: proxy tls
-Example: --proxy-key-type DER --proxy-key here -x https://proxy $URL
-See-also: proxy-key proxy
-Multi: single
----
-Same as --key-type but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-key-type.md b/docs/cmdline-opts/proxy-key-type.md
new file mode 100644
index 000000000..8740935b5
--- /dev/null
+++ b/docs/cmdline-opts/proxy-key-type.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-key-type
+Arg: <type>
+Help: Private key file type for proxy
+Added: 7.52.0
+Category: proxy tls
+Multi: single
+See-also:
+ - proxy-key
+ - proxy
+Example:
+ - --proxy-key-type DER --proxy-key here -x https://proxy $URL
+---
+
+# `--proxy-key-type`
+
+Same as --key-type but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-key.d b/docs/cmdline-opts/proxy-key.d
deleted file mode 100644
index 4bf2748a4..000000000
--- a/docs/cmdline-opts/proxy-key.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-key
-Help: Private key for HTTPS proxy
-Arg: <key>
-Category: proxy tls
-Example: --proxy-key here -x https://proxy $URL
-Added: 7.52.0
-See-also: proxy-key-type proxy
-Multi: single
----
-Same as --key but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-key.md b/docs/cmdline-opts/proxy-key.md
new file mode 100644
index 000000000..cfe507845
--- /dev/null
+++ b/docs/cmdline-opts/proxy-key.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-key
+Help: Private key for HTTPS proxy
+Arg: <key>
+Category: proxy tls
+Added: 7.52.0
+Multi: single
+See-also:
+ - proxy-key-type
+ - proxy
+Example:
+ - --proxy-key here -x https://proxy $URL
+---
+
+# `--proxy-key`
+
+Same as --key but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-negotiate.d b/docs/cmdline-opts/proxy-negotiate.d
deleted file mode 100644
index 89b5c1bde..000000000
--- a/docs/cmdline-opts/proxy-negotiate.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-negotiate
-Help: Use HTTP Negotiate (SPNEGO) authentication on the proxy
-Added: 7.17.1
-See-also: proxy-anyauth proxy-basic
-Category: proxy auth
-Example: --proxy-negotiate --proxy-user user:passwd -x proxy $URL
-Multi: mutex
----
-Tells curl to use HTTP Negotiate (SPNEGO) authentication when communicating
-with the given proxy. Use --negotiate for enabling HTTP Negotiate (SPNEGO)
-with a remote host.
diff --git a/docs/cmdline-opts/proxy-negotiate.md b/docs/cmdline-opts/proxy-negotiate.md
new file mode 100644
index 000000000..98e0bd371
--- /dev/null
+++ b/docs/cmdline-opts/proxy-negotiate.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-negotiate
+Help: Use HTTP Negotiate (SPNEGO) authentication on the proxy
+Added: 7.17.1
+Category: proxy auth
+Multi: mutex
+See-also:
+ - proxy-anyauth
+ - proxy-basic
+Example:
+ - --proxy-negotiate --proxy-user user:passwd -x proxy $URL
+---
+
+# `--proxy-negotiate`
+
+Tells curl to use HTTP Negotiate (SPNEGO) authentication when communicating
+with the given proxy. Use --negotiate for enabling HTTP Negotiate (SPNEGO)
+with a remote host.
diff --git a/docs/cmdline-opts/proxy-ntlm.d b/docs/cmdline-opts/proxy-ntlm.d
deleted file mode 100644
index f8481e5d6..000000000
--- a/docs/cmdline-opts/proxy-ntlm.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-ntlm
-Help: Use NTLM authentication on the proxy
-See-also: proxy-negotiate proxy-anyauth
-Category: proxy auth
-Example: --proxy-ntlm --proxy-user user:passwd -x http://proxy $URL
-Added: 7.10.7
-Multi: mutex
----
-Tells curl to use HTTP NTLM authentication when communicating with the given
-proxy. Use --ntlm for enabling NTLM with a remote host.
diff --git a/docs/cmdline-opts/proxy-ntlm.md b/docs/cmdline-opts/proxy-ntlm.md
new file mode 100644
index 000000000..b3394f074
--- /dev/null
+++ b/docs/cmdline-opts/proxy-ntlm.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-ntlm
+Help: Use NTLM authentication on the proxy
+Category: proxy auth
+Added: 7.10.7
+Multi: mutex
+See-also:
+ - proxy-negotiate
+ - proxy-anyauth
+Example:
+ - --proxy-ntlm --proxy-user user:passwd -x http://proxy $URL
+---
+
+# `--proxy-ntlm`
+
+Tells curl to use HTTP NTLM authentication when communicating with the given
+proxy. Use --ntlm for enabling NTLM with a remote host.
diff --git a/docs/cmdline-opts/proxy-pass.d b/docs/cmdline-opts/proxy-pass.d
deleted file mode 100644
index 307139951..000000000
--- a/docs/cmdline-opts/proxy-pass.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-pass
-Arg: <phrase>
-Help: Pass phrase for the private key for HTTPS proxy
-Added: 7.52.0
-Category: proxy tls auth
-Example: --proxy-pass secret --proxy-key here -x https://proxy $URL
-See-also: proxy proxy-key
-Multi: single
----
-Same as --pass but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-pass.md b/docs/cmdline-opts/proxy-pass.md
new file mode 100644
index 000000000..feba6e083
--- /dev/null
+++ b/docs/cmdline-opts/proxy-pass.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-pass
+Arg: <phrase>
+Help: Pass phrase for the private key for HTTPS proxy
+Added: 7.52.0
+Category: proxy tls auth
+Multi: single
+See-also:
+ - proxy
+ - proxy-key
+Example:
+ - --proxy-pass secret --proxy-key here -x https://proxy $URL
+---
+
+# `--proxy-pass`
+
+Same as --pass but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-pinnedpubkey.d b/docs/cmdline-opts/proxy-pinnedpubkey.d
deleted file mode 100644
index 7bf99d8c5..000000000
--- a/docs/cmdline-opts/proxy-pinnedpubkey.d
+++ /dev/null
@@ -1,22 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-pinnedpubkey
-Arg: <hashes>
-Help: FILE/HASHES public key to verify proxy with
-Protocols: TLS
-Category: proxy tls
-Example: --proxy-pinnedpubkey keyfile $URL
-Example: --proxy-pinnedpubkey 'sha256//ce118b51897f4452dc' $URL
-Added: 7.59.0
-See-also: pinnedpubkey proxy
-Multi: single
----
-Tells curl to use the specified public key file (or hashes) to verify the
-proxy. This can be a path to a file which contains a single public key in PEM
-or DER format, or any number of base64 encoded sha256 hashes preceded by
-'sha256//' and separated by ';'.
-
-When negotiating a TLS or SSL connection, the server sends a certificate
-indicating its identity. A public key is extracted from this certificate and
-if it does not exactly match the public key provided to this option, curl
-aborts the connection before sending or receiving any data.
diff --git a/docs/cmdline-opts/proxy-pinnedpubkey.md b/docs/cmdline-opts/proxy-pinnedpubkey.md
new file mode 100644
index 000000000..edf68cb0c
--- /dev/null
+++ b/docs/cmdline-opts/proxy-pinnedpubkey.md
@@ -0,0 +1,29 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-pinnedpubkey
+Arg: <hashes>
+Help: FILE/HASHES public key to verify proxy with
+Protocols: TLS
+Category: proxy tls
+Added: 7.59.0
+Multi: single
+See-also:
+ - pinnedpubkey
+ - proxy
+Example:
+ - --proxy-pinnedpubkey keyfile $URL
+ - --proxy-pinnedpubkey 'sha256//ce118b51897f4452dc' $URL
+---
+
+# `--proxy-pinnedpubkey`
+
+Tells curl to use the specified public key file (or hashes) to verify the
+proxy. This can be a path to a file which contains a single public key in PEM
+or DER format, or any number of base64 encoded sha256 hashes preceded by
+'sha256//' and separated by ';'.
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. A public key is extracted from this certificate and
+if it does not exactly match the public key provided to this option, curl
+aborts the connection before sending or receiving any data.
diff --git a/docs/cmdline-opts/proxy-service-name.d b/docs/cmdline-opts/proxy-service-name.d
deleted file mode 100644
index 200973fb5..000000000
--- a/docs/cmdline-opts/proxy-service-name.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-service-name
-Arg: <name>
-Help: SPNEGO proxy service name
-Added: 7.43.0
-Category: proxy tls
-Example: --proxy-service-name "shrubbery" -x proxy $URL
-See-also: service-name proxy
-Multi: single
----
-This option allows you to change the service name for proxy negotiation.
diff --git a/docs/cmdline-opts/proxy-service-name.md b/docs/cmdline-opts/proxy-service-name.md
new file mode 100644
index 000000000..f1ee2649d
--- /dev/null
+++ b/docs/cmdline-opts/proxy-service-name.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-service-name
+Arg: <name>
+Help: SPNEGO proxy service name
+Added: 7.43.0
+Category: proxy tls
+Multi: single
+See-also:
+ - service-name
+ - proxy
+Example:
+ - --proxy-service-name "shrubbery" -x proxy $URL
+---
+
+# `--proxy-service-name`
+
+This option allows you to change the service name for proxy negotiation.
diff --git a/docs/cmdline-opts/proxy-ssl-allow-beast.d b/docs/cmdline-opts/proxy-ssl-allow-beast.d
deleted file mode 100644
index 55ff62b46..000000000
--- a/docs/cmdline-opts/proxy-ssl-allow-beast.d
+++ /dev/null
@@ -1,11 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-ssl-allow-beast
-Help: Allow security flaw for interop for HTTPS proxy
-Added: 7.52.0
-Category: proxy tls
-Example: --proxy-ssl-allow-beast -x https://proxy $URL
-See-also: ssl-allow-beast proxy
-Multi: boolean
----
-Same as --ssl-allow-beast but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-ssl-allow-beast.md b/docs/cmdline-opts/proxy-ssl-allow-beast.md
new file mode 100644
index 000000000..f2deedbb5
--- /dev/null
+++ b/docs/cmdline-opts/proxy-ssl-allow-beast.md
@@ -0,0 +1,18 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-ssl-allow-beast
+Help: Allow security flaw for interop for HTTPS proxy
+Added: 7.52.0
+Category: proxy tls
+Multi: boolean
+See-also:
+ - ssl-allow-beast
+ - proxy
+Example:
+ - --proxy-ssl-allow-beast -x https://proxy $URL
+---
+
+# `--proxy-ssl-allow-beast`
+
+Same as --ssl-allow-beast but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-ssl-auto-client-cert.d b/docs/cmdline-opts/proxy-ssl-auto-client-cert.d
deleted file mode 100644
index ea0f0c04d..000000000
--- a/docs/cmdline-opts/proxy-ssl-auto-client-cert.d
+++ /dev/null
@@ -1,11 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-ssl-auto-client-cert
-Help: Use auto client certificate for proxy (Schannel)
-Added: 7.77.0
-Category: proxy tls
-Example: --proxy-ssl-auto-client-cert -x https://proxy $URL
-See-also: ssl-auto-client-cert proxy
-Multi: boolean
----
-Same as --ssl-auto-client-cert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-ssl-auto-client-cert.md b/docs/cmdline-opts/proxy-ssl-auto-client-cert.md
new file mode 100644
index 000000000..f3e77158d
--- /dev/null
+++ b/docs/cmdline-opts/proxy-ssl-auto-client-cert.md
@@ -0,0 +1,18 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-ssl-auto-client-cert
+Help: Use auto client certificate for proxy (Schannel)
+Added: 7.77.0
+Category: proxy tls
+Multi: boolean
+See-also:
+ - ssl-auto-client-cert
+ - proxy
+Example:
+ - --proxy-ssl-auto-client-cert -x https://proxy $URL
+---
+
+# `--proxy-ssl-auto-client-cert`
+
+Same as --ssl-auto-client-cert but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tls13-ciphers.d b/docs/cmdline-opts/proxy-tls13-ciphers.d
deleted file mode 100644
index f18c3d5c0..000000000
--- a/docs/cmdline-opts/proxy-tls13-ciphers.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-tls13-ciphers
-Arg: <ciphersuite list>
-help: TLS 1.3 proxy cipher suites
-Protocols: TLS
-Category: proxy tls
-Example: --proxy-tls13-ciphers TLS_AES_128_GCM_SHA256 -x proxy $URL
-Added: 7.61.0
-See-also: tls13-ciphers curves proxy-ciphers
-Multi: single
----
-Specifies which cipher suites to use in the connection to your HTTPS proxy
-when it negotiates TLS 1.3. The list of ciphers suites must specify valid
-ciphers. Read up on TLS 1.3 cipher suite details on this URL:
-
-https://curl.se/docs/ssl-ciphers.html
-
-This option is currently used only when curl is built to use OpenSSL 1.1.1 or
-later. If you are using a different SSL backend you can try setting TLS 1.3
-cipher suites by using the --proxy-ciphers option.
diff --git a/docs/cmdline-opts/proxy-tls13-ciphers.md b/docs/cmdline-opts/proxy-tls13-ciphers.md
new file mode 100644
index 000000000..c9202ae1a
--- /dev/null
+++ b/docs/cmdline-opts/proxy-tls13-ciphers.md
@@ -0,0 +1,29 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-tls13-ciphers
+Arg: <ciphersuite list>
+help: TLS 1.3 proxy cipher suites
+Protocols: TLS
+Category: proxy tls
+Added: 7.61.0
+Multi: single
+See-also:
+ - tls13-ciphers
+ - curves
+ - proxy-ciphers
+Example:
+ - --proxy-tls13-ciphers TLS_AES_128_GCM_SHA256 -x proxy $URL
+---
+
+# `--proxy-tls13-ciphers`
+
+Specifies which cipher suites to use in the connection to your HTTPS proxy
+when it negotiates TLS 1.3. The list of ciphers suites must specify valid
+ciphers. Read up on TLS 1.3 cipher suite details on this URL:
+
+https://curl.se/docs/ssl-ciphers.html
+
+This option is currently used only when curl is built to use OpenSSL 1.1.1 or
+later. If you are using a different SSL backend you can try setting TLS 1.3
+cipher suites by using the --proxy-ciphers option.
diff --git a/docs/cmdline-opts/proxy-tlsauthtype.d b/docs/cmdline-opts/proxy-tlsauthtype.d
deleted file mode 100644
index f83153e7b..000000000
--- a/docs/cmdline-opts/proxy-tlsauthtype.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-tlsauthtype
-Arg: <type>
-Help: TLS authentication type for HTTPS proxy
-Added: 7.52.0
-Category: proxy tls auth
-Example: --proxy-tlsauthtype SRP -x https://proxy $URL
-See-also: proxy proxy-tlsuser
-Multi: single
----
-Same as --tlsauthtype but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlsauthtype.md b/docs/cmdline-opts/proxy-tlsauthtype.md
new file mode 100644
index 000000000..067e4c598
--- /dev/null
+++ b/docs/cmdline-opts/proxy-tlsauthtype.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-tlsauthtype
+Arg: <type>
+Help: TLS authentication type for HTTPS proxy
+Added: 7.52.0
+Category: proxy tls auth
+Multi: single
+See-also:
+ - proxy
+ - proxy-tlsuser
+Example:
+ - --proxy-tlsauthtype SRP -x https://proxy $URL
+---
+
+# `--proxy-tlsauthtype`
+
+Same as --tlsauthtype but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlspassword.d b/docs/cmdline-opts/proxy-tlspassword.d
deleted file mode 100644
index 7ec01401b..000000000
--- a/docs/cmdline-opts/proxy-tlspassword.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-tlspassword
-Arg: <string>
-Help: TLS password for HTTPS proxy
-Added: 7.52.0
-Category: proxy tls auth
-Example: --proxy-tlspassword passwd -x https://proxy $URL
-See-also: proxy proxy-tlsuser
-Multi: single
----
-Same as --tlspassword but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlspassword.md b/docs/cmdline-opts/proxy-tlspassword.md
new file mode 100644
index 000000000..3c6d06c6a
--- /dev/null
+++ b/docs/cmdline-opts/proxy-tlspassword.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-tlspassword
+Arg: <string>
+Help: TLS password for HTTPS proxy
+Added: 7.52.0
+Category: proxy tls auth
+Multi: single
+See-also:
+ - proxy
+ - proxy-tlsuser
+Example:
+ - --proxy-tlspassword passwd -x https://proxy $URL
+---
+
+# `--proxy-tlspassword`
+
+Same as --tlspassword but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlsuser.d b/docs/cmdline-opts/proxy-tlsuser.d
deleted file mode 100644
index 17be7f7ba..000000000
--- a/docs/cmdline-opts/proxy-tlsuser.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-tlsuser
-Arg: <name>
-Help: TLS username for HTTPS proxy
-Added: 7.52.0
-Category: proxy tls auth
-Example: --proxy-tlsuser smith -x https://proxy $URL
-See-also: proxy proxy-tlspassword
-Multi: single
----
-Same as --tlsuser but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlsuser.md b/docs/cmdline-opts/proxy-tlsuser.md
new file mode 100644
index 000000000..1c626ee75
--- /dev/null
+++ b/docs/cmdline-opts/proxy-tlsuser.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-tlsuser
+Arg: <name>
+Help: TLS username for HTTPS proxy
+Added: 7.52.0
+Category: proxy tls auth
+Multi: single
+See-also:
+ - proxy
+ - proxy-tlspassword
+Example:
+ - --proxy-tlsuser smith -x https://proxy $URL
+---
+
+# `--proxy-tlsuser`
+
+Same as --tlsuser but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlsv1.d b/docs/cmdline-opts/proxy-tlsv1.d
deleted file mode 100644
index c4345023e..000000000
--- a/docs/cmdline-opts/proxy-tlsv1.d
+++ /dev/null
@@ -1,11 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-tlsv1
-Help: Use TLSv1 for HTTPS proxy
-Added: 7.52.0
-Category: proxy tls auth
-Example: --proxy-tlsv1 -x https://proxy $URL
-See-also: proxy
-Multi: mutex
----
-Same as --tlsv1 but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-tlsv1.md b/docs/cmdline-opts/proxy-tlsv1.md
new file mode 100644
index 000000000..b7b09ee47
--- /dev/null
+++ b/docs/cmdline-opts/proxy-tlsv1.md
@@ -0,0 +1,17 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-tlsv1
+Help: Use TLSv1 for HTTPS proxy
+Added: 7.52.0
+Category: proxy tls auth
+Multi: mutex
+See-also:
+ - proxy
+Example:
+ - --proxy-tlsv1 -x https://proxy $URL
+---
+
+# `--proxy-tlsv1`
+
+Same as --tlsv1 but used in HTTPS proxy context.
diff --git a/docs/cmdline-opts/proxy-user.d b/docs/cmdline-opts/proxy-user.d
deleted file mode 100644
index df30de2d9..000000000
--- a/docs/cmdline-opts/proxy-user.d
+++ /dev/null
@@ -1,23 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy-user
-Short: U
-Arg: <user:password>
-Help: Proxy user and password
-Category: proxy auth
-Example: --proxy-user name:pwd -x proxy $URL
-Added: 4.0
-See-also: proxy-pass
-Multi: single
----
-Specify the user name and password to use for proxy authentication.
-
-If you use a Windows SSPI-enabled curl binary and do either Negotiate or NTLM
-authentication then you can tell curl to select the user name and password
-from your environment by specifying a single colon with this option: "-U :".
-
-On systems where it works, curl hides the given option argument from process
-listings. This is not enough to protect credentials from possibly getting seen
-by other users on the same system as they still are visible for a moment
-before cleared. Such sensitive data should be retrieved from a file instead or
-similar and never used in clear text in a command line.
diff --git a/docs/cmdline-opts/proxy-user.md b/docs/cmdline-opts/proxy-user.md
new file mode 100644
index 000000000..3f12369df
--- /dev/null
+++ b/docs/cmdline-opts/proxy-user.md
@@ -0,0 +1,29 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy-user
+Short: U
+Arg: <user:password>
+Help: Proxy user and password
+Category: proxy auth
+Added: 4.0
+Multi: single
+See-also:
+ - proxy-pass
+Example:
+ - --proxy-user name:pwd -x proxy $URL
+---
+
+# `--proxy-user`
+
+Specify the user name and password to use for proxy authentication.
+
+If you use a Windows SSPI-enabled curl binary and do either Negotiate or NTLM
+authentication then you can tell curl to select the user name and password
+from your environment by specifying a single colon with this option: "-U :".
+
+On systems where it works, curl hides the given option argument from process
+listings. This is not enough to protect credentials from possibly getting seen
+by other users on the same system as they still are visible for a moment
+before cleared. Such sensitive data should be retrieved from a file instead or
+similar and never used in clear text in a command line.
diff --git a/docs/cmdline-opts/proxy.d b/docs/cmdline-opts/proxy.d
deleted file mode 100644
index b7d550a11..000000000
--- a/docs/cmdline-opts/proxy.d
+++ /dev/null
@@ -1,51 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy
-Short: x
-Arg: [protocol://]host[:port]
-Help: Use this proxy
-Category: proxy
-Example: --proxy http://proxy.example $URL
-Added: 4.0
-See-also: socks5 proxy-basic
-Multi: single
----
-Use the specified proxy.
-
-The proxy string can be specified with a protocol:// prefix. No protocol
-specified or http:// it is treated as an HTTP proxy. Use socks4://,
-socks4a://, socks5:// or socks5h:// to request a specific SOCKS version to be
-used. (Added in 7.21.7)
-
-Unix domain sockets are supported for socks proxy. Set localhost for the host
-part. e.g. socks5h://localhost/path/to/socket.sock
-
-HTTPS proxy support works set with the https:// protocol prefix for OpenSSL
-and GnuTLS (added in 7.52.0). It also works for BearSSL, mbedTLS, rustls,
-Schannel, Secure Transport and wolfSSL (added in 7.87.0).
-
-Unrecognized and unsupported proxy protocols cause an error (added in 7.52.0).
-Ancient curl versions ignored unknown schemes and used http:// instead.
-
-If the port number is not specified in the proxy string, it is assumed to be
-1080.
-
-This option overrides existing environment variables that set the proxy to
-use. If there is an environment variable setting a proxy, you can set proxy to
-"" to override it.
-
-All operations that are performed over an HTTP proxy are transparently
-converted to HTTP. It means that certain protocol specific operations might
-not be available. This is not the case if you can tunnel through the proxy, as
-one with the --proxytunnel option.
-
-User and password that might be provided in the proxy string are URL decoded
-by curl. This allows you to pass in special characters such as @ by using %40
-or pass in a colon with %3a.
-
-The proxy host can be specified the same way as the proxy environment
-variables, including the protocol prefix (http://) and the embedded user +
-password.
-
-When a proxy is used, the active FTP mode as set with --ftp-port, cannot be
-used.
diff --git a/docs/cmdline-opts/proxy.md b/docs/cmdline-opts/proxy.md
new file mode 100644
index 000000000..51f638c67
--- /dev/null
+++ b/docs/cmdline-opts/proxy.md
@@ -0,0 +1,58 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy
+Short: x
+Arg: [protocol://]host[:port]
+Help: Use this proxy
+Category: proxy
+Added: 4.0
+Multi: single
+See-also:
+ - socks5
+ - proxy-basic
+Example:
+ - --proxy http://proxy.example $URL
+---
+
+# `--proxy`
+
+Use the specified proxy.
+
+The proxy string can be specified with a protocol:// prefix. No protocol
+specified or http:// it is treated as an HTTP proxy. Use socks4://,
+socks4a://, socks5:// or socks5h:// to request a specific SOCKS version to be
+used. (Added in 7.21.7)
+
+Unix domain sockets are supported for socks proxy. Set localhost for the host
+part. e.g. socks5h://localhost/path/to/socket.sock
+
+HTTPS proxy support works set with the https:// protocol prefix for OpenSSL
+and GnuTLS (added in 7.52.0). It also works for BearSSL, mbedTLS, rustls,
+Schannel, Secure Transport and wolfSSL (added in 7.87.0).
+
+Unrecognized and unsupported proxy protocols cause an error (added in 7.52.0).
+Ancient curl versions ignored unknown schemes and used http:// instead.
+
+If the port number is not specified in the proxy string, it is assumed to be
+1080.
+
+This option overrides existing environment variables that set the proxy to
+use. If there is an environment variable setting a proxy, you can set proxy to
+"" to override it.
+
+All operations that are performed over an HTTP proxy are transparently
+converted to HTTP. It means that certain protocol specific operations might
+not be available. This is not the case if you can tunnel through the proxy, as
+one with the --proxytunnel option.
+
+User and password that might be provided in the proxy string are URL decoded
+by curl. This allows you to pass in special characters such as @ by using %40
+or pass in a colon with %3a.
+
+The proxy host can be specified the same way as the proxy environment
+variables, including the protocol prefix (http://) and the embedded user +
+password.
+
+When a proxy is used, the active FTP mode as set with --ftp-port, cannot be
+used.
diff --git a/docs/cmdline-opts/proxy1.0.d b/docs/cmdline-opts/proxy1.0.d
deleted file mode 100644
index 0657a9519..000000000
--- a/docs/cmdline-opts/proxy1.0.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxy1.0
-Arg: <host[:port]>
-Help: Use HTTP/1.0 proxy on given port
-Category: proxy
-Example: --proxy1.0 -x http://proxy $URL
-Added: 7.19.4
-See-also: proxy socks5 preproxy
-Multi: mutex
----
-Use the specified HTTP 1.0 proxy. If the port number is not specified, it is
-assumed at port 1080.
-
-The only difference between this and the HTTP proxy option --proxy, is that
-attempts to use CONNECT through the proxy specifies an HTTP 1.0 protocol
-instead of the default HTTP 1.1.
diff --git a/docs/cmdline-opts/proxy1.0.md b/docs/cmdline-opts/proxy1.0.md
new file mode 100644
index 000000000..d7b7a4381
--- /dev/null
+++ b/docs/cmdline-opts/proxy1.0.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxy1.0
+Arg: <host[:port]>
+Help: Use HTTP/1.0 proxy on given port
+Category: proxy
+Added: 7.19.4
+Multi: mutex
+See-also:
+ - proxy
+ - socks5
+ - preproxy
+Example:
+ - --proxy1.0 -x http://proxy $URL
+---
+
+# `--proxy1.0`
+
+Use the specified HTTP 1.0 proxy. If the port number is not specified, it is
+assumed at port 1080.
+
+The only difference between this and the HTTP proxy option --proxy, is that
+attempts to use CONNECT through the proxy specifies an HTTP 1.0 protocol
+instead of the default HTTP 1.1.
diff --git a/docs/cmdline-opts/proxytunnel.d b/docs/cmdline-opts/proxytunnel.d
deleted file mode 100644
index 51457870b..000000000
--- a/docs/cmdline-opts/proxytunnel.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: proxytunnel
-Short: p
-Help: Operate through an HTTP proxy tunnel (using CONNECT)
-See-also: proxy
-Category: proxy
-Example: --proxytunnel -x http://proxy $URL
-Added: 7.3
-Multi: boolean
----
-When an HTTP proxy is used --proxy, this option makes curl tunnel the traffic
-through the proxy. The tunnel approach is made with the HTTP proxy CONNECT
-request and requires that the proxy allows direct connect to the remote port
-number curl wants to tunnel through to.
-
-To suppress proxy CONNECT response headers when curl is set to output headers
-use --suppress-connect-headers.
diff --git a/docs/cmdline-opts/proxytunnel.md b/docs/cmdline-opts/proxytunnel.md
new file mode 100644
index 000000000..74faa681a
--- /dev/null
+++ b/docs/cmdline-opts/proxytunnel.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: proxytunnel
+Short: p
+Help: Operate through an HTTP proxy tunnel (using CONNECT)
+Category: proxy
+Added: 7.3
+Multi: boolean
+See-also:
+ - proxy
+Example:
+ - --proxytunnel -x http://proxy $URL
+---
+
+# `--proxytunnel`
+
+When an HTTP proxy is used --proxy, this option makes curl tunnel the traffic
+through the proxy. The tunnel approach is made with the HTTP proxy CONNECT
+request and requires that the proxy allows direct connect to the remote port
+number curl wants to tunnel through to.
+
+To suppress proxy CONNECT response headers when curl is set to output headers
+use --suppress-connect-headers.
diff --git a/docs/cmdline-opts/pubkey.d b/docs/cmdline-opts/pubkey.d
deleted file mode 100644
index b2f4b727b..000000000
--- a/docs/cmdline-opts/pubkey.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: pubkey
-Arg: <key>
-Protocols: SFTP SCP
-Help: SSH Public key file name
-Category: sftp scp auth
-Example: --pubkey file.pub sftp://example.com/
-Added: 7.16.2
-See-also: pass
-Multi: single
----
-Public key file name. Allows you to provide your public key in this separate
-file.
-
-curl attempts to automatically extract the public key from the private key
-file, so passing this option is generally not required. Note that this public
-key extraction requires libcurl to be linked against a copy of libssh2 1.2.8
-or higher that is itself linked against OpenSSL. (Added in 7.39.0.)
diff --git a/docs/cmdline-opts/pubkey.md b/docs/cmdline-opts/pubkey.md
new file mode 100644
index 000000000..b849bfe1d
--- /dev/null
+++ b/docs/cmdline-opts/pubkey.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: pubkey
+Arg: <key>
+Protocols: SFTP SCP
+Help: SSH Public key file name
+Category: sftp scp auth
+Added: 7.16.2
+Multi: single
+See-also:
+ - pass
+Example:
+ - --pubkey file.pub sftp://example.com/
+---
+
+# `--pubkey`
+
+Public key file name. Allows you to provide your public key in this separate
+file.
+
+curl attempts to automatically extract the public key from the private key
+file, so passing this option is generally not required. Note that this public
+key extraction requires libcurl to be linked against a copy of libssh2 1.2.8
+or higher that is itself linked against OpenSSL. (Added in 7.39.0.)
diff --git a/docs/cmdline-opts/quote.d b/docs/cmdline-opts/quote.d
deleted file mode 100644
index 5008d4932..000000000
--- a/docs/cmdline-opts/quote.d
+++ /dev/null
@@ -1,87 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: quote
-Arg: <command>
-Short: Q
-Help: Send command(s) to server before transfer
-Protocols: FTP SFTP
-Category: ftp sftp
-Example: --quote "DELE file" ftp://example.com/foo
-Added: 5.3
-See-also: request
-Multi: append
----
-Send an arbitrary command to the remote FTP or SFTP server. Quote commands are
-sent BEFORE the transfer takes place (just after the initial **PWD** command
-in an FTP transfer, to be exact). To make commands take place after a
-successful transfer, prefix them with a dash '-'.
-
-(FTP only) To make commands be sent after curl has changed the working
-directory, just before the file transfer command(s), prefix the command with a
-'+'. This is not performed when a directory listing is performed.
-
-You may specify any number of commands.
-
-By default curl stops at first failure. To make curl continue even if the
-command fails, prefix the command with an asterisk (*). Otherwise, if the
-server returns failure for one of the commands, the entire operation is
-aborted.
-
-You must send syntactically correct FTP commands as RFC 959 defines to FTP
-servers, or one of the commands listed below to SFTP servers.
-
-SFTP is a binary protocol. Unlike for FTP, curl interprets SFTP quote commands
-itself before sending them to the server. File names may be quoted
-shell-style to embed spaces or special characters. Following is the list of
-all supported SFTP quote commands:
-.RS
-.TP
-**"atime date file"**
-The atime command sets the last access time of the file named by the file
-operand. The <date expression> can be all sorts of date strings, see the
-*curl_getdate(3)* man page for date expression details. (Added in 7.73.0)
-.TP
-**"chgrp group file"**
-The chgrp command sets the group ID of the file named by the file operand to
-the group ID specified by the group operand. The group operand is a decimal
-integer group ID.
-.TP
-**"chmod mode file"**
-The chmod command modifies the file mode bits of the specified file. The
-mode operand is an octal integer mode number.
-.TP
-**"chown user file"**
-The chown command sets the owner of the file named by the file operand to the
-user ID specified by the user operand. The user operand is a decimal
-integer user ID.
-.TP
-**"ln source_file target_file"**
-The ln and symlink commands create a symbolic link at the target_file location
-pointing to the source_file location.
-.TP
-**"mkdir directory_name"**
-The mkdir command creates the directory named by the directory_name operand.
-.TP
-**"mtime date file"**
-The mtime command sets the last modification time of the file named by the
-file operand. The <date expression> can be all sorts of date strings, see the
-*curl_getdate(3)* man page for date expression details. (Added in 7.73.0)
-.TP
-**"pwd"**
-The pwd command returns the absolute path name of the current working directory.
-.TP
-**"rename source target"**
-The rename command renames the file or directory named by the source
-operand to the destination path named by the target operand.
-.TP
-**"rm file"**
-The rm command removes the file specified by the file operand.
-.TP
-**"rmdir directory"**
-The rmdir command removes the directory entry specified by the directory
-operand, provided it is empty.
-.TP
-**"symlink source_file target_file"**
-See ln.
-.RE
-.IP
diff --git a/docs/cmdline-opts/quote.md b/docs/cmdline-opts/quote.md
new file mode 100644
index 000000000..3155f4eb2
--- /dev/null
+++ b/docs/cmdline-opts/quote.md
@@ -0,0 +1,90 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: quote
+Arg: <command>
+Short: Q
+Help: Send command(s) to server before transfer
+Protocols: FTP SFTP
+Category: ftp sftp
+Added: 5.3
+Multi: append
+See-also:
+ - request
+Example:
+ - --quote "DELE file" ftp://example.com/foo
+---
+
+# `--quote`
+
+Send an arbitrary command to the remote FTP or SFTP server. Quote commands are
+sent BEFORE the transfer takes place (just after the initial **PWD** command
+in an FTP transfer, to be exact). To make commands take place after a
+successful transfer, prefix them with a dash '-'.
+
+(FTP only) To make commands be sent after curl has changed the working
+directory, just before the file transfer command(s), prefix the command with a
+'+'. This is not performed when a directory listing is performed.
+
+You may specify any number of commands.
+
+By default curl stops at first failure. To make curl continue even if the
+command fails, prefix the command with an asterisk (*). Otherwise, if the
+server returns failure for one of the commands, the entire operation is
+aborted.
+
+You must send syntactically correct FTP commands as RFC 959 defines to FTP
+servers, or one of the commands listed below to SFTP servers.
+
+SFTP is a binary protocol. Unlike for FTP, curl interprets SFTP quote commands
+itself before sending them to the server. File names may be quoted
+shell-style to embed spaces or special characters. Following is the list of
+all supported SFTP quote commands:
+
+## atime date file
+The atime command sets the last access time of the file named by the file
+operand. The <date expression> can be all sorts of date strings, see the
+*curl_getdate(3)* man page for date expression details. (Added in 7.73.0)
+
+## chgrp group file
+The chgrp command sets the group ID of the file named by the file operand to
+the group ID specified by the group operand. The group operand is a decimal
+integer group ID.
+
+## chmod mode file
+The chmod command modifies the file mode bits of the specified file. The
+mode operand is an octal integer mode number.
+
+## chown user file
+The chown command sets the owner of the file named by the file operand to the
+user ID specified by the user operand. The user operand is a decimal
+integer user ID.
+
+## ln source_file target_file
+The ln and symlink commands create a symbolic link at the target_file location
+pointing to the source_file location.
+
+## mkdir directory_name
+The mkdir command creates the directory named by the directory_name operand.
+
+## mtime date file
+The mtime command sets the last modification time of the file named by the
+file operand. The <date expression> can be all sorts of date strings, see the
+*curl_getdate(3)* man page for date expression details. (Added in 7.73.0)
+
+## pwd
+The pwd command returns the absolute path name of the current working directory.
+
+## rename source target
+The rename command renames the file or directory named by the source
+operand to the destination path named by the target operand.
+
+## rm file
+The rm command removes the file specified by the file operand.
+
+## rmdir directory
+The rmdir command removes the directory entry specified by the directory
+operand, provided it is empty.
+
+## symlink source_file target_file
+See ln.
diff --git a/docs/cmdline-opts/random-file.d b/docs/cmdline-opts/random-file.d
deleted file mode 100644
index aa076de7f..000000000
--- a/docs/cmdline-opts/random-file.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: random-file
-Arg: <file>
-Help: File for reading random data from
-Category: misc
-Example: --random-file rubbish $URL
-Added: 7.7
-See-also: egd-file
-Multi: single
----
-Deprecated option. This option is ignored (added in 7.84.0). Prior to that it
-only had an effect on curl if built to use old versions of OpenSSL.
-
-Specify the path name to file containing random data. The data may be used to
-seed the random engine for SSL connections.
diff --git a/docs/cmdline-opts/random-file.md b/docs/cmdline-opts/random-file.md
new file mode 100644
index 000000000..0f564d9d7
--- /dev/null
+++ b/docs/cmdline-opts/random-file.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: random-file
+Arg: <file>
+Help: File for reading random data from
+Category: misc
+Added: 7.7
+Multi: single
+See-also:
+ - egd-file
+Example:
+ - --random-file rubbish $URL
+---
+
+# `--random-file`
+
+Deprecated option. This option is ignored (added in 7.84.0). Prior to that it
+only had an effect on curl if built to use old versions of OpenSSL.
+
+Specify the path name to file containing random data. The data may be used to
+seed the random engine for SSL connections.
diff --git a/docs/cmdline-opts/range.d b/docs/cmdline-opts/range.d
deleted file mode 100644
index eba7220e1..000000000
--- a/docs/cmdline-opts/range.d
+++ /dev/null
@@ -1,50 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: range
-Short: r
-Help: Retrieve only the bytes within RANGE
-Arg: <range>
-Protocols: HTTP FTP SFTP FILE
-Category: http ftp sftp file
-Example: --range 22-44 $URL
-Added: 4.0
-See-also: continue-at append
-Multi: single
----
-Retrieve a byte range (i.e. a partial document) from an HTTP/1.1, FTP or SFTP
-server or a local FILE. Ranges can be specified in a number of ways.
-.RS
-.TP 10
-.B 0-499
-specifies the first 500 bytes
-.TP
-.B 500-999
-specifies the second 500 bytes
-.TP
-.B -500
-specifies the last 500 bytes
-.TP
-.B 9500-
-specifies the bytes from offset 9500 and forward
-.TP
-.B 0-0,-1
-specifies the first and last byte only(*)(HTTP)
-.TP
-.B 100-199,500-599
-specifies two separate 100-byte ranges(*) (HTTP)
-.RE
-.IP
-(*) = NOTE that this causes the server to reply with a multipart response,
-which is returned as-is by curl! Parsing or otherwise transforming this
-response is the responsibility of the caller.
-
-Only digit characters (0-9) are valid in the 'start' and 'stop' fields of the
-'start-stop' range syntax. If a non-digit character is given in the range, the
-server's response is unspecified, depending on the server's configuration.
-
-Many HTTP/1.1 servers do not have this feature enabled, so that when you
-attempt to get a range, curl instead gets the whole document.
-
-FTP and SFTP range downloads only support the simple 'start-stop' syntax
-(optionally with one of the numbers omitted). FTP use depends on the extended
-FTP command SIZE.
diff --git a/docs/cmdline-opts/range.md b/docs/cmdline-opts/range.md
new file mode 100644
index 000000000..abfdf216f
--- /dev/null
+++ b/docs/cmdline-opts/range.md
@@ -0,0 +1,57 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: range
+Short: r
+Help: Retrieve only the bytes within RANGE
+Arg: <range>
+Protocols: HTTP FTP SFTP FILE
+Category: http ftp sftp file
+Added: 4.0
+Multi: single
+See-also:
+ - continue-at
+ - append
+Example:
+ - --range 22-44 $URL
+---
+
+# `--range`
+
+Retrieve a byte range (i.e. a partial document) from an HTTP/1.1, FTP or SFTP
+server or a local FILE. Ranges can be specified in a number of ways.
+
+## 0-499
+specifies the first 500 bytes
+
+## 500-999
+specifies the second 500 bytes
+
+## -500
+specifies the last 500 bytes
+
+## 9500-
+specifies the bytes from offset 9500 and forward
+
+## 0-0,-1
+specifies the first and last byte only(*)(HTTP)
+
+## 100-199,500-599
+specifies two separate 100-byte ranges(*) (HTTP)
+
+##
+
+(*) = NOTE that these make the server reply with a multipart response, which
+is returned as-is by curl! Parsing or otherwise transforming this response is
+the responsibility of the caller.
+
+Only digit characters (0-9) are valid in the 'start' and 'stop' fields of the
+'start-stop' range syntax. If a non-digit character is given in the range, the
+server's response is unspecified, depending on the server's configuration.
+
+Many HTTP/1.1 servers do not have this feature enabled, so that when you
+attempt to get a range, curl instead gets the whole document.
+
+FTP and SFTP range downloads only support the simple 'start-stop' syntax
+(optionally with one of the numbers omitted). FTP use depends on the extended
+FTP command SIZE.
diff --git a/docs/cmdline-opts/rate.d b/docs/cmdline-opts/rate.d
deleted file mode 100644
index d3cbd2849..000000000
--- a/docs/cmdline-opts/rate.d
+++ /dev/null
@@ -1,35 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: rate
-Arg: <max request rate>
-Help: Request rate for serial transfers
-Category: connection
-Example: --rate 2/s $URL ...
-Example: --rate 3/h $URL ...
-Example: --rate 14/m $URL ...
-Added: 7.84.0
-See-also: limit-rate retry-delay
-Multi: single
-Scope: global
----
-Specify the maximum transfer frequency you allow curl to use - in number of
-transfer starts per time unit (sometimes called request rate). Without this
-option, curl starts the next transfer as fast as possible.
-
-If given several URLs and a transfer completes faster than the allowed rate,
-curl waits until the next transfer is started to maintain the requested
-rate. This option has no effect when --parallel is used.
-
-The request rate is provided as "N/U" where N is an integer number and U is a
-time unit. Supported units are 's' (second), 'm' (minute), 'h' (hour) and 'd'
-/(day, as in a 24 hour unit). The default time unit, if no "/U" is provided,
-is number of transfers per hour.
-
-If curl is told to allow 10 requests per minute, it does not start the next
-request until 6 seconds have elapsed since the previous transfer was started.
-
-This function uses millisecond resolution. If the allowed frequency is set
-more than 1000 per second, it instead runs unrestricted.
-
-When retrying transfers, enabled with --retry, the separate retry delay logic
-is used and not this setting.
diff --git a/docs/cmdline-opts/rate.md b/docs/cmdline-opts/rate.md
new file mode 100644
index 000000000..fb2901e7e
--- /dev/null
+++ b/docs/cmdline-opts/rate.md
@@ -0,0 +1,42 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: rate
+Arg: <max request rate>
+Help: Request rate for serial transfers
+Category: connection
+Added: 7.84.0
+Multi: single
+Scope: global
+See-also:
+ - limit-rate
+ - retry-delay
+Example:
+ - --rate 2/s $URL ...
+ - --rate 3/h $URL ...
+ - --rate 14/m $URL ...
+---
+
+# `--rate`
+
+Specify the maximum transfer frequency you allow curl to use - in number of
+transfer starts per time unit (sometimes called request rate). Without this
+option, curl starts the next transfer as fast as possible.
+
+If given several URLs and a transfer completes faster than the allowed rate,
+curl waits until the next transfer is started to maintain the requested
+rate. This option has no effect when --parallel is used.
+
+The request rate is provided as "N/U" where N is an integer number and U is a
+time unit. Supported units are 's' (second), 'm' (minute), 'h' (hour) and 'd'
+/(day, as in a 24 hour unit). The default time unit, if no "/U" is provided,
+is number of transfers per hour.
+
+If curl is told to allow 10 requests per minute, it does not start the next
+request until 6 seconds have elapsed since the previous transfer was started.
+
+This function uses millisecond resolution. If the allowed frequency is set
+more than 1000 per second, it instead runs unrestricted.
+
+When retrying transfers, enabled with --retry, the separate retry delay logic
+is used and not this setting.
diff --git a/docs/cmdline-opts/raw.d b/docs/cmdline-opts/raw.d
deleted file mode 100644
index 0523d62fa..000000000
--- a/docs/cmdline-opts/raw.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: raw
-Help: Do HTTP "raw"; no transfer decoding
-Added: 7.16.2
-Protocols: HTTP
-Category: http
-Example: --raw $URL
-See-also: tr-encoding
-Multi: boolean
----
-When used, it disables all internal HTTP decoding of content or transfer
-encodings and instead makes them passed on unaltered, raw.
diff --git a/docs/cmdline-opts/raw.md b/docs/cmdline-opts/raw.md
new file mode 100644
index 000000000..9871b033e
--- /dev/null
+++ b/docs/cmdline-opts/raw.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: raw
+Help: Do HTTP "raw"; no transfer decoding
+Added: 7.16.2
+Protocols: HTTP
+Category: http
+Multi: boolean
+See-also:
+ - tr-encoding
+Example:
+ - --raw $URL
+---
+
+# `--raw`
+
+When used, it disables all internal HTTP decoding of content or transfer
+encodings and instead makes them passed on unaltered, raw.
diff --git a/docs/cmdline-opts/referer.d b/docs/cmdline-opts/referer.d
deleted file mode 100644
index 0609e8c99..000000000
--- a/docs/cmdline-opts/referer.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: referer
-Short: e
-Arg: <URL>
-Protocols: HTTP
-Help: Referrer URL
-See-also: user-agent header
-Category: http
-Example: --referer "https://fake.example" $URL
-Example: --referer "https://fake.example;auto" -L $URL
-Example: --referer ";auto" -L $URL
-Added: 4.0
-Multi: single
----
-Sends the "Referrer Page" information to the HTTP server. This can also be set
-with the --header flag of course. When used with --location you can append
-";auto" to the --referer URL to make curl automatically set the previous URL
-when it follows a Location: header. The ";auto" string can be used alone,
-even if you do not set an initial --referer.
diff --git a/docs/cmdline-opts/referer.md b/docs/cmdline-opts/referer.md
new file mode 100644
index 000000000..3120280cc
--- /dev/null
+++ b/docs/cmdline-opts/referer.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: referer
+Short: e
+Arg: <URL>
+Protocols: HTTP
+Help: Referrer URL
+Category: http
+Added: 4.0
+Multi: single
+See-also:
+ - user-agent
+ - header
+Example:
+ - --referer "https://fake.example" $URL
+ - --referer "https://fake.example;auto" -L $URL
+ - --referer ";auto" -L $URL
+---
+
+# `--referer`
+
+Sends the "Referrer Page" information to the HTTP server. This can also be set
+with the --header flag of course. When used with --location you can append
+";auto" to the --referer URL to make curl automatically set the previous URL
+when it follows a Location: header. The ";auto" string can be used alone,
+even if you do not set an initial --referer.
diff --git a/docs/cmdline-opts/remote-header-name.d b/docs/cmdline-opts/remote-header-name.d
deleted file mode 100644
index 917fe7abf..000000000
--- a/docs/cmdline-opts/remote-header-name.d
+++ /dev/null
@@ -1,34 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: remote-header-name
-Short: J
-Protocols: HTTP
-Help: Use the header-provided filename
-Category: output
-Example: -OJ https://example.com/file
-Added: 7.20.0
-See-also: remote-name
-Multi: boolean
----
-This option tells the --remote-name option to use the server-specified
-Content-Disposition filename instead of extracting a filename from the URL. If
-the server-provided file name contains a path, that is stripped off before the
-file name is used.
-
-The file is saved in the current directory, or in the directory specified with
---output-dir.
-
-If the server specifies a file name and a file with that name already exists
-in the destination directory, it is not overwritten and an error occurs -
-unless you allow it by using the --clobber option. If the server does not
-specify a file name then this option has no effect.
-
-There is no attempt to decode %-sequences (yet) in the provided file name, so
-this option may provide you with rather unexpected file names.
-
-This feature uses the name from the "filename" field, it does not yet support
-the "filename*" field (filenames with explicit character sets).
-
-**WARNING**: Exercise judicious use of this option, especially on Windows. A
-rogue server could send you the name of a DLL or other file that could be
-loaded automatically by Windows or some third party software.
diff --git a/docs/cmdline-opts/remote-header-name.md b/docs/cmdline-opts/remote-header-name.md
new file mode 100644
index 000000000..c4cf514db
--- /dev/null
+++ b/docs/cmdline-opts/remote-header-name.md
@@ -0,0 +1,40 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: remote-header-name
+Short: J
+Protocols: HTTP
+Help: Use the header-provided filename
+Category: output
+Added: 7.20.0
+Multi: boolean
+See-also:
+ - remote-name
+Example:
+ - -OJ https://example.com/file
+---
+
+# `--remote-header-name`
+
+This option tells the --remote-name option to use the server-specified
+Content-Disposition filename instead of extracting a filename from the URL. If
+the server-provided file name contains a path, that is stripped off before the
+file name is used.
+
+The file is saved in the current directory, or in the directory specified with
+--output-dir.
+
+If the server specifies a file name and a file with that name already exists
+in the destination directory, it is not overwritten and an error occurs -
+unless you allow it by using the --clobber option. If the server does not
+specify a file name then this option has no effect.
+
+There is no attempt to decode %-sequences (yet) in the provided file name, so
+this option may provide you with rather unexpected file names.
+
+This feature uses the name from the "filename" field, it does not yet support
+the "filename*" field (filenames with explicit character sets).
+
+**WARNING**: Exercise judicious use of this option, especially on Windows. A
+rogue server could send you the name of a DLL or other file that could be
+loaded automatically by Windows or some third party software.
diff --git a/docs/cmdline-opts/remote-name-all.d b/docs/cmdline-opts/remote-name-all.d
deleted file mode 100644
index 249c4e265..000000000
--- a/docs/cmdline-opts/remote-name-all.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: remote-name-all
-Help: Use the remote file name for all URLs
-Added: 7.19.0
-Category: output
-Example: --remote-name-all ftp://example.com/file1 ftp://example.com/file2
-See-also: remote-name
-Multi: boolean
----
-This option changes the default action for all given URLs to be dealt with as
-if --remote-name were used for each one. So if you want to disable that for a
-specific URL after --remote-name-all has been used, you must use "-o -" or
---no-remote-name.
diff --git a/docs/cmdline-opts/remote-name-all.md b/docs/cmdline-opts/remote-name-all.md
new file mode 100644
index 000000000..068828628
--- /dev/null
+++ b/docs/cmdline-opts/remote-name-all.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: remote-name-all
+Help: Use the remote file name for all URLs
+Added: 7.19.0
+Category: output
+Multi: boolean
+See-also:
+ - remote-name
+Example:
+ - --remote-name-all ftp://example.com/file1 ftp://example.com/file2
+---
+
+# `--remote-name-all`
+
+This option changes the default action for all given URLs to be dealt with as
+if --remote-name were used for each one. So if you want to disable that for a
+specific URL after --remote-name-all has been used, you must use "-o -" or
+--no-remote-name.
diff --git a/docs/cmdline-opts/remote-name.d b/docs/cmdline-opts/remote-name.d
deleted file mode 100644
index 215cf72de..000000000
--- a/docs/cmdline-opts/remote-name.d
+++ /dev/null
@@ -1,28 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: remote-name
-Short: O
-Help: Write output to a file named as the remote file
-Category: important output
-Example: -O https://example.com/filename
-Added: 4.0
-See-also: remote-name-all output-dir remote-header-name
-Multi: append
----
-Write output to a local file named like the remote file we get. (Only the file
-part of the remote file is used, the path is cut off.)
-
-The file is saved in the current working directory. If you want the file saved
-in a different directory, make sure you change the current working directory
-before invoking curl with this option or use --output-dir.
-
-The remote file name to use for saving is extracted from the given URL,
-nothing else, and if it already exists it is overwritten. If you want the
-server to be able to choose the file name refer to --remote-header-name which
-can be used in addition to this option. If the server chooses a file name and
-that name already exists it is not overwritten.
-
-There is no URL decoding done on the file name. If it has %20 or other URL
-encoded parts of the name, they end up as-is as file name.
-
-You may use this option as many times as the number of URLs you have.
diff --git a/docs/cmdline-opts/remote-name.md b/docs/cmdline-opts/remote-name.md
new file mode 100644
index 000000000..498bc31e7
--- /dev/null
+++ b/docs/cmdline-opts/remote-name.md
@@ -0,0 +1,36 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: remote-name
+Short: O
+Help: Write output to a file named as the remote file
+Category: important output
+Added: 4.0
+Multi: append
+See-also:
+ - remote-name-all
+ - output-dir
+ - remote-header-name
+Example:
+ - -O https://example.com/filename
+---
+
+# `--remote-name`
+
+Write output to a local file named like the remote file we get. (Only the file
+part of the remote file is used, the path is cut off.)
+
+The file is saved in the current working directory. If you want the file saved
+in a different directory, make sure you change the current working directory
+before invoking curl with this option or use --output-dir.
+
+The remote file name to use for saving is extracted from the given URL,
+nothing else, and if it already exists it is overwritten. If you want the
+server to be able to choose the file name refer to --remote-header-name which
+can be used in addition to this option. If the server chooses a file name and
+that name already exists it is not overwritten.
+
+There is no URL decoding done on the file name. If it has %20 or other URL
+encoded parts of the name, they end up as-is as file name.
+
+You may use this option as many times as the number of URLs you have.
diff --git a/docs/cmdline-opts/remote-time.d b/docs/cmdline-opts/remote-time.d
deleted file mode 100644
index 6dfb26c49..000000000
--- a/docs/cmdline-opts/remote-time.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: remote-time
-Short: R
-Help: Set the remote file's time on the local output
-Category: output
-Example: --remote-time -o foo $URL
-Added: 7.9
-See-also: remote-name time-cond
-Multi: boolean
----
-Makes curl attempt to figure out the timestamp of the remote file that is
-getting downloaded, and if that is available make the local file get that same
-timestamp.
diff --git a/docs/cmdline-opts/remote-time.md b/docs/cmdline-opts/remote-time.md
new file mode 100644
index 000000000..b010bc130
--- /dev/null
+++ b/docs/cmdline-opts/remote-time.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: remote-time
+Short: R
+Help: Set the remote file's time on the local output
+Category: output
+Added: 7.9
+Multi: boolean
+See-also:
+ - remote-name
+ - time-cond
+Example:
+ - --remote-time -o foo $URL
+---
+
+# `--remote-time`
+
+Makes curl attempt to figure out the timestamp of the remote file that is
+getting downloaded, and if that is available make the local file get that same
+timestamp.
diff --git a/docs/cmdline-opts/remove-on-error.d b/docs/cmdline-opts/remove-on-error.d
deleted file mode 100644
index 50b7b1b65..000000000
--- a/docs/cmdline-opts/remove-on-error.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: remove-on-error
-Help: Remove output file on errors
-See-also: fail
-Category: curl
-Example: --remove-on-error -o output $URL
-Added: 7.83.0
-Multi: boolean
----
-When curl returns an error when told to save output in a local file, this
-option removes that saved file before exiting. This prevents curl from
-leaving a partial file in the case of an error during transfer.
-
-If the output is not a file, this option has no effect.
diff --git a/docs/cmdline-opts/remove-on-error.md b/docs/cmdline-opts/remove-on-error.md
new file mode 100644
index 000000000..02ce99239
--- /dev/null
+++ b/docs/cmdline-opts/remove-on-error.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: remove-on-error
+Help: Remove output file on errors
+Category: curl
+Added: 7.83.0
+Multi: boolean
+See-also:
+ - fail
+Example:
+ - --remove-on-error -o output $URL
+---
+
+# `--remove-on-error`
+
+When curl returns an error when told to save output in a local file, this
+option removes that saved file before exiting. This prevents curl from
+leaving a partial file in the case of an error during transfer.
+
+If the output is not a regular file, this option has no effect.
diff --git a/docs/cmdline-opts/request-target.d b/docs/cmdline-opts/request-target.d
deleted file mode 100644
index 61ead5f2b..000000000
--- a/docs/cmdline-opts/request-target.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: request-target
-Arg: <path>
-Help: Specify the target for this request
-Protocols: HTTP
-Added: 7.55.0
-Category: http
-Example: --request-target "*" -X OPTIONS $URL
-See-also: request
-Multi: single
----
-Tells curl to use an alternative "target" (path) instead of using the path as
-provided in the URL. Particularly useful when wanting to issue HTTP requests
-without leading slash or other data that does not follow the regular URL
-pattern, like "OPTIONS *".
diff --git a/docs/cmdline-opts/request-target.md b/docs/cmdline-opts/request-target.md
new file mode 100644
index 000000000..5b23630bf
--- /dev/null
+++ b/docs/cmdline-opts/request-target.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: request-target
+Arg: <path>
+Help: Specify the target for this request
+Protocols: HTTP
+Added: 7.55.0
+Category: http
+Multi: single
+See-also:
+ - request
+Example:
+ - --request-target "*" -X OPTIONS $URL
+---
+
+# `--request-target`
+
+Tells curl to use an alternative "target" (path) instead of using the path as
+provided in the URL. Particularly useful when wanting to issue HTTP requests
+without leading slash or other data that does not follow the regular URL
+pattern, like "OPTIONS *".
+
+curl passes on the verbatim string you give it its the request without any
+filter or other safe guards. That includes white space and control characters.
diff --git a/docs/cmdline-opts/request.d b/docs/cmdline-opts/request.d
deleted file mode 100644
index 0020babf9..000000000
--- a/docs/cmdline-opts/request.d
+++ /dev/null
@@ -1,51 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: request
-Short: X
-Arg: <method>
-Help: Specify request method to use
-Category: connection
-Example: -X "DELETE" $URL
-Example: -X NLST ftp://example.com/
-Added: 6.0
-See-also: request-target
-Multi: single
----
-Change the method to use when starting the transfer.
-.RS
-.TP 15
-**HTTP**
-Specifies a custom request method to use when communicating with the HTTP
-server. The specified request method is used instead of the method otherwise
-used (which defaults to *GET*). Read the HTTP 1.1 specification for details
-and explanations. Common additional HTTP requests include *PUT* and *DELETE*,
-but related technologies like WebDAV offers *PROPFIND*, *COPY*, *MOVE* and
-more.
-
-Normally you do not need this option. All sorts of *GET*, *HEAD*, *POST* and
-*PUT* requests are rather invoked by using dedicated command line options.
-
-This option only changes the actual word used in the HTTP request, it does not
-alter the way curl behaves. So for example if you want to make a proper HEAD
-request, using -X HEAD does not suffice. You need to use the --head option.
-
-The method string you set with --request is used for all requests, which
-if you for example use --location may cause unintended side-effects when curl
-does not change request method according to the HTTP 30x response codes - and
-similar.
-.TP
-**FTP**
-Specifies a custom FTP command to use instead of *LIST* when doing file lists
-with FTP.
-.TP
-**POP3**
-Specifies a custom POP3 command to use instead of *LIST* or *RETR*.
-(Added in 7.26.0)
-.TP
-**IMAP**
-Specifies a custom IMAP command to use instead of *LIST*. (Added in 7.30.0)
-.TP
-**SMTP**
-Specifies a custom SMTP command to use instead of *HELP* or **VRFY**. (Added in 7.34.0)
-.RE
-.IP
diff --git a/docs/cmdline-opts/request.md b/docs/cmdline-opts/request.md
new file mode 100644
index 000000000..ccfe99c7c
--- /dev/null
+++ b/docs/cmdline-opts/request.md
@@ -0,0 +1,57 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: request
+Short: X
+Arg: <method>
+Help: Specify request method to use
+Category: connection
+Added: 6.0
+Multi: single
+See-also:
+ - request-target
+Example:
+ - -X "DELETE" $URL
+ - -X NLST ftp://example.com/
+---
+
+# `--request`
+
+Change the method to use when starting the transfer.
+
+curl passes on the verbatim string you give it its the request without any
+filter or other safe guards. That includes white space and control characters.
+
+## HTTP
+Specifies a custom request method to use when communicating with the HTTP
+server. The specified request method is used instead of the method otherwise
+used (which defaults to *GET*). Read the HTTP 1.1 specification for details
+and explanations. Common additional HTTP requests include *PUT* and *DELETE*,
+while related technologies like WebDAV offers *PROPFIND*, *COPY*, *MOVE* and
+more.
+
+Normally you do not need this option. All sorts of *GET*, *HEAD*, *POST* and
+*PUT* requests are rather invoked by using dedicated command line options.
+
+This option only changes the actual word used in the HTTP request, it does not
+alter the way curl behaves. So for example if you want to make a proper HEAD
+request, using -X HEAD does not suffice. You need to use the --head option.
+
+The method string you set with --request is used for all requests, which
+if you for example use --location may cause unintended side-effects when curl
+does not change request method according to the HTTP 30x response codes - and
+similar.
+
+## FTP
+Specifies a custom FTP command to use instead of *LIST* when doing file lists
+with FTP.
+
+## POP3
+Specifies a custom POP3 command to use instead of *LIST* or *RETR*.
+(Added in 7.26.0)
+
+## IMAP
+Specifies a custom IMAP command to use instead of *LIST*. (Added in 7.30.0)
+
+## SMTP
+Specifies a custom SMTP command to use instead of *HELP* or **VRFY**. (Added in 7.34.0)
diff --git a/docs/cmdline-opts/resolve.d b/docs/cmdline-opts/resolve.d
deleted file mode 100644
index 31dd099a2..000000000
--- a/docs/cmdline-opts/resolve.d
+++ /dev/null
@@ -1,41 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: resolve
-Arg: <[+]host:port:addr[,addr]...>
-Help: Resolve the host+port to this address
-Added: 7.21.3
-Category: connection dns
-Example: --resolve example.com:443:127.0.0.1 $URL
-See-also: connect-to alt-svc
-Multi: append
----
-Provide a custom address for a specific host and port pair. Using this, you
-can make the curl requests(s) use a specified address and prevent the
-otherwise normally resolved address to be used. Consider it a sort of
-/etc/hosts alternative provided on the command line. The port number should be
-the number used for the specific protocol the host is used for. It means
-you need several entries if you want to provide address for the same host but
-different ports.
-
-By specifying '*' as host you can tell curl to resolve any host and specific
-port pair to the specified address. Wildcard is resolved last so any --resolve
-with a specific host and port is used first.
-
-The provided address set by this option is used even if --ipv4 or --ipv6 is
-set to make curl use another IP version.
-
-By prefixing the host with a '+' you can make the entry time out after curl's
-default timeout (1 minute). Note that this only makes sense for long running
-parallel transfers with a lot of files. In such cases, if this option is used
-curl tries to resolve the host as it normally would once the timeout has
-expired.
-
-Support for providing the IP address within [brackets] was added in 7.57.0.
-
-Support for providing multiple IP addresses per entry was added in 7.59.0.
-
-Support for resolving with wildcard was added in 7.64.0.
-
-Support for the '+' prefix was was added in 7.75.0.
-
-This option can be used many times to add many host names to resolve.
diff --git a/docs/cmdline-opts/resolve.md b/docs/cmdline-opts/resolve.md
new file mode 100644
index 000000000..c5c5eddd5
--- /dev/null
+++ b/docs/cmdline-opts/resolve.md
@@ -0,0 +1,46 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: resolve
+Arg: <[+]host:port:addr[,addr]...>
+Help: Resolve the host+port to this address
+Added: 7.21.3
+Category: connection dns
+Multi: append
+See-also:
+ - connect-to
+ - alt-svc
+Example:
+ - --resolve example.com:443:127.0.0.1 $URL
+---
+
+# `--resolve`
+
+Provide a custom address for a specific host and port pair. Using this, you
+can make the curl requests(s) use a specified address and prevent the
+otherwise normally resolved address to be used. Consider it a sort of
+/etc/hosts alternative provided on the command line. The port number should be
+the number used for the specific protocol the host is used for. It means
+you need several entries if you want to provide address for the same host but
+different ports.
+
+By specifying '*' as host you can tell curl to resolve any host and specific
+port pair to the specified address. Wildcard is resolved last so any --resolve
+with a specific host and port is used first.
+
+The provided address set by this option is used even if --ipv4 or --ipv6 is
+set to make curl use another IP version.
+
+By prefixing the host with a '+' you can make the entry time out after curl's
+default timeout (1 minute). Note that this only makes sense for long running
+parallel transfers with a lot of files. In such cases, if this option is used
+curl tries to resolve the host as it normally would once the timeout has
+expired.
+
+Support for providing the IP address within [brackets] was added in 7.57.0.
+
+Support for providing multiple IP addresses per entry was added in 7.59.0.
+
+Support for resolving with wildcard was added in 7.64.0.
+
+Support for the '+' prefix was was added in 7.75.0.
diff --git a/docs/cmdline-opts/retry-all-errors.d b/docs/cmdline-opts/retry-all-errors.d
deleted file mode 100644
index 1190d6a3a..000000000
--- a/docs/cmdline-opts/retry-all-errors.d
+++ /dev/null
@@ -1,34 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: retry-all-errors
-Help: Retry all errors (use with --retry)
-Added: 7.71.0
-Category: curl
-Example: --retry 5 --retry-all-errors $URL
-See-also: retry
-Multi: boolean
----
-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 (for example in your **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 you do not parse or record
-output via redirect in combination with this option, since you may receive
-duplicate data.
-
-By default curl does not return error for transfers with an HTTP response code
-that indicates an HTTP error, if the transfer was successful. For example, if
-a server replies 404 Not Found and the reply is fully received then that is
-not an error. When --retry is used then curl retries on some HTTP response
-codes that indicate transient HTTP errors, but that does not include most 4xx
-response codes such as 404. If you want to retry on all response codes that
-indicate HTTP errors (4xx and 5xx) then combine with --fail.
diff --git a/docs/cmdline-opts/retry-all-errors.md b/docs/cmdline-opts/retry-all-errors.md
new file mode 100644
index 000000000..c29911fca
--- /dev/null
+++ b/docs/cmdline-opts/retry-all-errors.md
@@ -0,0 +1,40 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: retry-all-errors
+Help: Retry all errors (use with --retry)
+Added: 7.71.0
+Category: curl
+Multi: boolean
+See-also:
+ - retry
+Example:
+ - --retry 5 --retry-all-errors $URL
+---
+
+# `--retry-all-errors`
+
+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 (for example in your **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 you do not parse or record
+output via redirect in combination with this option, since you may receive
+duplicate data.
+
+By default curl does not return error for transfers with an HTTP response code
+that indicates an HTTP error, if the transfer was successful. For example, if
+a server replies 404 Not Found and the reply is fully received then that is
+not an error. When --retry is used then curl retries on some HTTP response
+codes that indicate transient HTTP errors, but that does not include most 4xx
+response codes such as 404. If you want to retry on all response codes that
+indicate HTTP errors (4xx and 5xx) then combine with --fail.
diff --git a/docs/cmdline-opts/retry-connrefused.d b/docs/cmdline-opts/retry-connrefused.d
deleted file mode 100644
index a7b9643ce..000000000
--- a/docs/cmdline-opts/retry-connrefused.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: retry-connrefused
-Help: Retry on connection refused (use with --retry)
-Added: 7.52.0
-Category: curl
-Example: --retry-connrefused --retry 7 $URL
-See-also: retry retry-all-errors
-Multi: boolean
----
-In addition to the other conditions, consider ECONNREFUSED as a transient
-error too for --retry. This option is used together with --retry.
diff --git a/docs/cmdline-opts/retry-connrefused.md b/docs/cmdline-opts/retry-connrefused.md
new file mode 100644
index 000000000..975dc097a
--- /dev/null
+++ b/docs/cmdline-opts/retry-connrefused.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: retry-connrefused
+Help: Retry on connection refused (use with --retry)
+Added: 7.52.0
+Category: curl
+Multi: boolean
+See-also:
+ - retry
+ - retry-all-errors
+Example:
+ - --retry-connrefused --retry 7 $URL
+---
+
+# `--retry-connrefused`
+
+In addition to the other conditions, consider ECONNREFUSED as a transient
+error too for --retry. This option is used together with --retry.
diff --git a/docs/cmdline-opts/retry-delay.d b/docs/cmdline-opts/retry-delay.d
deleted file mode 100644
index 686a0d8ba..000000000
--- a/docs/cmdline-opts/retry-delay.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: retry-delay
-Arg: <seconds>
-Help: Wait time between retries
-Added: 7.12.3
-Category: curl
-Example: --retry-delay 5 --retry 7 $URL
-See-also: retry
-Multi: single
----
-Make curl sleep this amount of time before each retry when a transfer has
-failed with a transient error (it changes the default backoff time algorithm
-between retries). This option is only interesting if --retry is also
-used. Setting this delay to zero makes curl use the default backoff time.
diff --git a/docs/cmdline-opts/retry-delay.md b/docs/cmdline-opts/retry-delay.md
new file mode 100644
index 000000000..b2a405b63
--- /dev/null
+++ b/docs/cmdline-opts/retry-delay.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: retry-delay
+Arg: <seconds>
+Help: Wait time between retries
+Added: 7.12.3
+Category: curl
+Multi: single
+See-also:
+ - retry
+Example:
+ - --retry-delay 5 --retry 7 $URL
+---
+
+# `--retry-delay`
+
+Make curl sleep this amount of time before each retry when a transfer has
+failed with a transient error (it changes the default backoff time algorithm
+between retries). This option is only interesting if --retry is also
+used. Setting this delay to zero makes curl use the default backoff time.
diff --git a/docs/cmdline-opts/retry-max-time.d b/docs/cmdline-opts/retry-max-time.d
deleted file mode 100644
index de2aff9a8..000000000
--- a/docs/cmdline-opts/retry-max-time.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: retry-max-time
-Arg: <seconds>
-Help: Retry only within this period
-Added: 7.12.3
-Category: curl
-Example: --retry-max-time 30 --retry 10 $URL
-See-also: retry
-Multi: single
----
-The retry timer is reset before the first transfer attempt. Retries are done
-as usual (see --retry) as long as the timer has not reached this given
-limit. Notice that if the timer has not reached the limit, the request is
-made and while performing, it may take longer than this given time period. To
-limit a single request's maximum time, use --max-time. Set this option to zero
-to not timeout retries.
diff --git a/docs/cmdline-opts/retry-max-time.md b/docs/cmdline-opts/retry-max-time.md
new file mode 100644
index 000000000..f7346475b
--- /dev/null
+++ b/docs/cmdline-opts/retry-max-time.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: retry-max-time
+Arg: <seconds>
+Help: Retry only within this period
+Added: 7.12.3
+Category: curl
+Multi: single
+See-also:
+ - retry
+Example:
+ - --retry-max-time 30 --retry 10 $URL
+---
+
+# `--retry-max-time`
+
+The retry timer is reset before the first transfer attempt. Retries are done
+as usual (see --retry) as long as the timer has not reached this given
+limit. Notice that if the timer has not reached the limit, the request is
+made and while performing, it may take longer than this given time period. To
+limit a single request's maximum time, use --max-time. Set this option to zero
+to not timeout retries.
diff --git a/docs/cmdline-opts/retry.d b/docs/cmdline-opts/retry.d
deleted file mode 100644
index d49a0cdfb..000000000
--- a/docs/cmdline-opts/retry.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: retry
-Arg: <num>
-Added: 7.12.3
-Help: Retry request if transient problems occur
-Category: curl
-Example: --retry 7 $URL
-See-also: retry-max-time
-Multi: single
----
-If a transient error is returned when curl tries to perform a transfer, it
-retries this number of times before giving up. Setting the number to 0
-makes curl do no retries (which is the default). Transient error means either:
-a timeout, an FTP 4xx response code or an HTTP 408, 429, 500, 502, 503 or 504
-response code.
-
-When curl is about to retry a transfer, it first waits one second and then for
-all forthcoming retries it doubles the waiting time until it reaches 10
-minutes which then remains delay between the rest of the retries. By using
---retry-delay you disable this exponential backoff algorithm. See also
---retry-max-time to limit the total time allowed for retries.
-
-curl complies with the Retry-After: response header if one was present to know
-when to issue the next retry (added in 7.66.0).
diff --git a/docs/cmdline-opts/retry.md b/docs/cmdline-opts/retry.md
new file mode 100644
index 000000000..1cd595dd2
--- /dev/null
+++ b/docs/cmdline-opts/retry.md
@@ -0,0 +1,31 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: retry
+Arg: <num>
+Added: 7.12.3
+Help: Retry request if transient problems occur
+Category: curl
+Multi: single
+See-also:
+ - retry-max-time
+Example:
+ - --retry 7 $URL
+---
+
+# `--retry`
+
+If a transient error is returned when curl tries to perform a transfer, it
+retries this number of times before giving up. Setting the number to 0
+makes curl do no retries (which is the default). Transient error means either:
+a timeout, an FTP 4xx response code or an HTTP 408, 429, 500, 502, 503 or 504
+response code.
+
+When curl is about to retry a transfer, it first waits one second and then for
+all forthcoming retries it doubles the waiting time until it reaches 10
+minutes which then remains delay between the rest of the retries. By using
+--retry-delay you disable this exponential backoff algorithm. See also
+--retry-max-time to limit the total time allowed for retries.
+
+curl complies with the Retry-After: response header if one was present to know
+when to issue the next retry (added in 7.66.0).
diff --git a/docs/cmdline-opts/sasl-authzid.d b/docs/cmdline-opts/sasl-authzid.d
deleted file mode 100644
index 872818df7..000000000
--- a/docs/cmdline-opts/sasl-authzid.d
+++ /dev/null
@@ -1,19 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: sasl-authzid
-Arg: <identity>
-Help: Identity for SASL PLAIN authentication
-Added: 7.66.0
-Category: auth
-Example: --sasl-authzid zid imap://example.com/
-See-also: login-options
-Multi: single
----
-Use this authorization identity (**authzid**), during SASL PLAIN
-authentication, in addition to the authentication identity (**authcid**) as
-specified by --user.
-
-If the option is not specified, the server derives the **authzid** from the
-**authcid**, but if specified, and depending on the server implementation, it
-may be used to access another user's inbox, that the user has been granted
-access to, or a shared mailbox for example.
diff --git a/docs/cmdline-opts/sasl-authzid.md b/docs/cmdline-opts/sasl-authzid.md
new file mode 100644
index 000000000..4c4282d14
--- /dev/null
+++ b/docs/cmdline-opts/sasl-authzid.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: sasl-authzid
+Arg: <identity>
+Help: Identity for SASL PLAIN authentication
+Added: 7.66.0
+Category: auth
+Multi: single
+See-also:
+ - login-options
+Example:
+ - --sasl-authzid zid imap://example.com/
+---
+
+# `--sasl-authzid`
+
+Use this authorization identity (**authzid**), during SASL PLAIN
+authentication, in addition to the authentication identity (**authcid**) as
+specified by --user.
+
+If the option is not specified, the server derives the **authzid** from the
+**authcid**, but if specified, and depending on the server implementation, it
+may be used to access another user's inbox, that the user has been granted
+access to, or a shared mailbox for example.
diff --git a/docs/cmdline-opts/sasl-ir.d b/docs/cmdline-opts/sasl-ir.d
deleted file mode 100644
index 56f1ae8ad..000000000
--- a/docs/cmdline-opts/sasl-ir.d
+++ /dev/null
@@ -1,11 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: sasl-ir
-Help: Enable initial response in SASL authentication
-Added: 7.31.0
-Category: auth
-Example: --sasl-ir imap://example.com/
-See-also: sasl-authzid
-Multi: boolean
----
-Enable initial response in SASL authentication.
diff --git a/docs/cmdline-opts/sasl-ir.md b/docs/cmdline-opts/sasl-ir.md
new file mode 100644
index 000000000..56732807d
--- /dev/null
+++ b/docs/cmdline-opts/sasl-ir.md
@@ -0,0 +1,17 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: sasl-ir
+Help: Enable initial response in SASL authentication
+Added: 7.31.0
+Category: auth
+Multi: boolean
+See-also:
+ - sasl-authzid
+Example:
+ - --sasl-ir imap://example.com/
+---
+
+# `--sasl-ir`
+
+Enable initial response in SASL authentication.
diff --git a/docs/cmdline-opts/service-name.d b/docs/cmdline-opts/service-name.d
deleted file mode 100644
index 54d7ebf7b..000000000
--- a/docs/cmdline-opts/service-name.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: service-name
-Help: SPNEGO service name
-Arg: <name>
-Added: 7.43.0
-Category: misc
-Example: --service-name sockd/server $URL
-See-also: negotiate proxy-service-name
-Multi: single
----
-This option allows you to change the service name for SPNEGO.
diff --git a/docs/cmdline-opts/service-name.md b/docs/cmdline-opts/service-name.md
new file mode 100644
index 000000000..818dc4e7b
--- /dev/null
+++ b/docs/cmdline-opts/service-name.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: service-name
+Help: SPNEGO service name
+Arg: <name>
+Added: 7.43.0
+Category: misc
+Multi: single
+See-also:
+ - negotiate
+ - proxy-service-name
+Example:
+ - --service-name sockd/server $URL
+---
+
+# `--service-name`
+
+This option allows you to change the service name for SPNEGO.
diff --git a/docs/cmdline-opts/show-error.d b/docs/cmdline-opts/show-error.d
deleted file mode 100644
index f15028745..000000000
--- a/docs/cmdline-opts/show-error.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: show-error
-Short: S
-Help: Show error even when -s is used
-See-also: no-progress-meter
-Category: curl
-Example: --show-error --silent $URL
-Added: 5.9
-Multi: boolean
-Scope: global
----
-When used with --silent, it makes curl show an error message if it fails.
diff --git a/docs/cmdline-opts/show-error.md b/docs/cmdline-opts/show-error.md
new file mode 100644
index 000000000..0517c37bb
--- /dev/null
+++ b/docs/cmdline-opts/show-error.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: show-error
+Short: S
+Help: Show error even when -s is used
+Category: curl
+Added: 5.9
+Multi: boolean
+Scope: global
+See-also:
+ - no-progress-meter
+Example:
+ - --show-error --silent $URL
+---
+
+# `--show-error`
+
+When used with --silent, it makes curl show an error message if it fails.
diff --git a/docs/cmdline-opts/silent.d b/docs/cmdline-opts/silent.d
deleted file mode 100644
index 74bb299cc..000000000
--- a/docs/cmdline-opts/silent.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: silent
-Short: s
-Help: Silent mode
-See-also: verbose stderr no-progress-meter
-Category: important verbose
-Example: -s $URL
-Added: 4.0
-Multi: boolean
----
-Silent or quiet mode. Do not show progress meter or error messages. Makes Curl
-mute. It still outputs the data you ask for, potentially even to the
-terminal/stdout unless you redirect it.
-
-Use --show-error in addition to this option to disable progress meter but
-still show error messages.
diff --git a/docs/cmdline-opts/silent.md b/docs/cmdline-opts/silent.md
new file mode 100644
index 000000000..090af0cb1
--- /dev/null
+++ b/docs/cmdline-opts/silent.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: silent
+Short: s
+Help: Silent mode
+Category: important verbose
+Added: 4.0
+Multi: boolean
+See-also:
+ - verbose
+ - stderr
+ - no-progress-meter
+Example:
+ - -s $URL
+---
+
+# `--silent`
+
+Silent or quiet mode. Do not show progress meter or error messages. Makes Curl
+mute. It still outputs the data you ask for, potentially even to the
+terminal/stdout unless you redirect it.
+
+Use --show-error in addition to this option to disable progress meter but
+still show error messages.
diff --git a/docs/cmdline-opts/socks4.d b/docs/cmdline-opts/socks4.d
deleted file mode 100644
index d8cf719aa..000000000
--- a/docs/cmdline-opts/socks4.d
+++ /dev/null
@@ -1,28 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks4
-Arg: <host[:port]>
-Help: SOCKS4 proxy on given host + port
-Added: 7.15.2
-Category: proxy
-Example: --socks4 hostname:4096 $URL
-See-also: socks4a socks5 socks5-hostname
-Multi: single
----
-Use the specified SOCKS4 proxy. If the port number is not specified, it is
-assumed at port 1080. Using this socket type make curl resolve the host name
-and passing the address on to the proxy.
-
-To specify proxy on a unix domain socket, use localhost for host, e.g.
-socks4://localhost/path/to/socket.sock
-
-This option overrides any previous use of --proxy, as they are mutually
-exclusive.
-
-This option is superfluous since you can specify a socks4 proxy with --proxy
-using a socks4:// protocol prefix. (Added in 7.21.7)
-
---preproxy can be used to specify a SOCKS proxy at the same time proxy is used
-with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
-connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
-HTTPS proxy.
diff --git a/docs/cmdline-opts/socks4.md b/docs/cmdline-opts/socks4.md
new file mode 100644
index 000000000..0971f2b53
--- /dev/null
+++ b/docs/cmdline-opts/socks4.md
@@ -0,0 +1,36 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks4
+Arg: <host[:port]>
+Help: SOCKS4 proxy on given host + port
+Added: 7.15.2
+Category: proxy
+Multi: single
+See-also:
+ - socks4a
+ - socks5
+ - socks5-hostname
+Example:
+ - --socks4 hostname:4096 $URL
+---
+
+# `--socks4`
+
+Use the specified SOCKS4 proxy. If the port number is not specified, it is
+assumed at port 1080. Using this socket type make curl resolve the host name
+and passing the address on to the proxy.
+
+To specify proxy on a unix domain socket, use localhost for host, e.g.
+`socks4://localhost/path/to/socket.sock`
+
+This option overrides any previous use of --proxy, as they are mutually
+exclusive.
+
+This option is superfluous since you can specify a socks4 proxy with --proxy
+using a socks4:// protocol prefix. (Added in 7.21.7)
+
+--preproxy can be used to specify a SOCKS proxy at the same time proxy is used
+with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
+connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
+HTTPS proxy.
diff --git a/docs/cmdline-opts/socks4a.d b/docs/cmdline-opts/socks4a.d
deleted file mode 100644
index cbb62724c..000000000
--- a/docs/cmdline-opts/socks4a.d
+++ /dev/null
@@ -1,27 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks4a
-Arg: <host[:port]>
-Help: SOCKS4a proxy on given host + port
-Added: 7.18.0
-Category: proxy
-Example: --socks4a hostname:4096 $URL
-See-also: socks4 socks5 socks5-hostname
-Multi: single
----
-Use the specified SOCKS4a proxy. If the port number is not specified, it is
-assumed at port 1080. This asks the proxy to resolve the host name.
-
-To specify proxy on a unix domain socket, use localhost for host, e.g.
-socks4a://localhost/path/to/socket.sock
-
-This option overrides any previous use of --proxy, as they are mutually
-exclusive.
-
-This option is superfluous since you can specify a socks4a proxy with --proxy
-using a socks4a:// protocol prefix. (Added in 7.21.7)
-
---preproxy can be used to specify a SOCKS proxy at the same time --proxy is
-used with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
-connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
-HTTPS proxy.
diff --git a/docs/cmdline-opts/socks4a.md b/docs/cmdline-opts/socks4a.md
new file mode 100644
index 000000000..00e5a9617
--- /dev/null
+++ b/docs/cmdline-opts/socks4a.md
@@ -0,0 +1,35 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks4a
+Arg: <host[:port]>
+Help: SOCKS4a proxy on given host + port
+Added: 7.18.0
+Category: proxy
+Multi: single
+See-also:
+ - socks4
+ - socks5
+ - socks5-hostname
+Example:
+ - --socks4a hostname:4096 $URL
+---
+
+# `--socks4a`
+
+Use the specified SOCKS4a proxy. If the port number is not specified, it is
+assumed at port 1080. This asks the proxy to resolve the host name.
+
+To specify proxy on a unix domain socket, use localhost for host, e.g.
+`socks4a://localhost/path/to/socket.sock`
+
+This option overrides any previous use of --proxy, as they are mutually
+exclusive.
+
+This option is superfluous since you can specify a socks4a proxy with --proxy
+using a socks4a:// protocol prefix. (Added in 7.21.7)
+
+--preproxy can be used to specify a SOCKS proxy at the same time --proxy is
+used with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
+connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
+HTTPS proxy.
diff --git a/docs/cmdline-opts/socks5-basic.d b/docs/cmdline-opts/socks5-basic.d
deleted file mode 100644
index a16831be1..000000000
--- a/docs/cmdline-opts/socks5-basic.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks5-basic
-Help: Enable username/password auth for SOCKS5 proxies
-Added: 7.55.0
-Category: proxy auth
-Example: --socks5-basic --socks5 hostname:4096 $URL
-See-also: socks5
-Multi: mutex
----
-Tells curl to use username/password authentication when connecting to a SOCKS5
-proxy. The username/password authentication is enabled by default. Use
---socks5-gssapi to force GSS-API authentication to SOCKS5 proxies.
diff --git a/docs/cmdline-opts/socks5-basic.md b/docs/cmdline-opts/socks5-basic.md
new file mode 100644
index 000000000..bfadea6b4
--- /dev/null
+++ b/docs/cmdline-opts/socks5-basic.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks5-basic
+Help: Enable username/password auth for SOCKS5 proxies
+Added: 7.55.0
+Category: proxy auth
+Multi: mutex
+See-also:
+ - socks5
+Example:
+ - --socks5-basic --socks5 hostname:4096 $URL
+---
+
+# `--socks5-basic`
+
+Tells curl to use username/password authentication when connecting to a SOCKS5
+proxy. The username/password authentication is enabled by default. Use
+--socks5-gssapi to force GSS-API authentication to SOCKS5 proxies.
diff --git a/docs/cmdline-opts/socks5-gssapi-nec.d b/docs/cmdline-opts/socks5-gssapi-nec.d
deleted file mode 100644
index 957655a09..000000000
--- a/docs/cmdline-opts/socks5-gssapi-nec.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks5-gssapi-nec
-Help: Compatibility with NEC SOCKS5 server
-Added: 7.19.4
-Category: proxy auth
-Example: --socks5-gssapi-nec --socks5 hostname:4096 $URL
-See-also: socks5
-Multi: boolean
----
-As part of the GSS-API negotiation a protection mode is negotiated. RFC 1961
-says in section 4.3/4.4 it should be protected, but the NEC reference
-implementation does not. The option --socks5-gssapi-nec allows the
-unprotected exchange of the protection mode negotiation.
diff --git a/docs/cmdline-opts/socks5-gssapi-nec.md b/docs/cmdline-opts/socks5-gssapi-nec.md
new file mode 100644
index 000000000..eef6b2de9
--- /dev/null
+++ b/docs/cmdline-opts/socks5-gssapi-nec.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks5-gssapi-nec
+Help: Compatibility with NEC SOCKS5 server
+Added: 7.19.4
+Category: proxy auth
+Multi: boolean
+See-also:
+ - socks5
+Example:
+ - --socks5-gssapi-nec --socks5 hostname:4096 $URL
+---
+
+# `--socks5-gssapi-nec`
+
+As part of the GSS-API negotiation a protection mode is negotiated. RFC 1961
+says in section 4.3/4.4 it should be protected, but the NEC reference
+implementation does not. The option --socks5-gssapi-nec allows the
+unprotected exchange of the protection mode negotiation.
diff --git a/docs/cmdline-opts/socks5-gssapi-service.d b/docs/cmdline-opts/socks5-gssapi-service.d
deleted file mode 100644
index 66c2f33a5..000000000
--- a/docs/cmdline-opts/socks5-gssapi-service.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks5-gssapi-service
-Arg: <name>
-Help: SOCKS5 proxy service name for GSS-API
-Added: 7.19.4
-Category: proxy auth
-Example: --socks5-gssapi-service sockd --socks5 hostname:4096 $URL
-See-also: socks5
-Multi: single
----
-The default service name for a socks server is **rcmd/server-fqdn**. This option
-allows you to change it.
diff --git a/docs/cmdline-opts/socks5-gssapi-service.md b/docs/cmdline-opts/socks5-gssapi-service.md
new file mode 100644
index 000000000..c2ab2d932
--- /dev/null
+++ b/docs/cmdline-opts/socks5-gssapi-service.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks5-gssapi-service
+Arg: <name>
+Help: SOCKS5 proxy service name for GSS-API
+Added: 7.19.4
+Category: proxy auth
+Multi: single
+See-also:
+ - socks5
+Example:
+ - --socks5-gssapi-service sockd --socks5 hostname:4096 $URL
+---
+
+# `--socks5-gssapi-service`
+
+The default service name for a socks server is **rcmd/server-fqdn**. This option
+allows you to change it.
diff --git a/docs/cmdline-opts/socks5-gssapi.d b/docs/cmdline-opts/socks5-gssapi.d
deleted file mode 100644
index cec684f42..000000000
--- a/docs/cmdline-opts/socks5-gssapi.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks5-gssapi
-Help: Enable GSS-API auth for SOCKS5 proxies
-Added: 7.55.0
-Category: proxy auth
-Example: --socks5-gssapi --socks5 hostname:4096 $URL
-See-also: socks5
-Multi: boolean
----
-Tells curl to use GSS-API authentication when connecting to a SOCKS5 proxy.
-The GSS-API authentication is enabled by default (if curl is compiled with
-GSS-API support). Use --socks5-basic to force username/password authentication
-to SOCKS5 proxies.
diff --git a/docs/cmdline-opts/socks5-gssapi.md b/docs/cmdline-opts/socks5-gssapi.md
new file mode 100644
index 000000000..43ec56aa2
--- /dev/null
+++ b/docs/cmdline-opts/socks5-gssapi.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks5-gssapi
+Help: Enable GSS-API auth for SOCKS5 proxies
+Added: 7.55.0
+Category: proxy auth
+Multi: boolean
+See-also:
+ - socks5
+Example:
+ - --socks5-gssapi --socks5 hostname:4096 $URL
+---
+
+# `--socks5-gssapi`
+
+Tells curl to use GSS-API authentication when connecting to a SOCKS5 proxy.
+The GSS-API authentication is enabled by default (if curl is compiled with
+GSS-API support). Use --socks5-basic to force username/password authentication
+to SOCKS5 proxies.
diff --git a/docs/cmdline-opts/socks5-hostname.d b/docs/cmdline-opts/socks5-hostname.d
deleted file mode 100644
index ee49ca642..000000000
--- a/docs/cmdline-opts/socks5-hostname.d
+++ /dev/null
@@ -1,27 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks5-hostname
-Arg: <host[:port]>
-Help: SOCKS5 proxy, pass host name to proxy
-Added: 7.18.0
-Category: proxy
-Example: --socks5-hostname proxy.example:7000 $URL
-See-also: socks5 socks4a
-Multi: single
----
-Use the specified SOCKS5 proxy (and let the proxy resolve the host name). If
-the port number is not specified, it is assumed at port 1080.
-
-To specify proxy on a unix domain socket, use localhost for host, e.g.
-socks5h://localhost/path/to/socket.sock
-
-This option overrides any previous use of --proxy, as they are mutually
-exclusive.
-
-This option is superfluous since you can specify a socks5 hostname proxy with
---proxy using a socks5h:// protocol prefix. (Added in 7.21.7)
-
---preproxy can be used to specify a SOCKS proxy at the same time --proxy is
-used with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
-connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
-HTTPS proxy.
diff --git a/docs/cmdline-opts/socks5-hostname.md b/docs/cmdline-opts/socks5-hostname.md
new file mode 100644
index 000000000..d38e501ee
--- /dev/null
+++ b/docs/cmdline-opts/socks5-hostname.md
@@ -0,0 +1,34 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks5-hostname
+Arg: <host[:port]>
+Help: SOCKS5 proxy, pass host name to proxy
+Added: 7.18.0
+Category: proxy
+Multi: single
+See-also:
+ - socks5
+ - socks4a
+Example:
+ - --socks5-hostname proxy.example:7000 $URL
+---
+
+# `--socks5-hostname`
+
+Use the specified SOCKS5 proxy (and let the proxy resolve the host name). If
+the port number is not specified, it is assumed at port 1080.
+
+To specify proxy on a unix domain socket, use localhost for host, e.g.
+`socks5h://localhost/path/to/socket.sock`
+
+This option overrides any previous use of --proxy, as they are mutually
+exclusive.
+
+This option is superfluous since you can specify a socks5 hostname proxy with
+--proxy using a socks5h:// protocol prefix. (Added in 7.21.7)
+
+--preproxy can be used to specify a SOCKS proxy at the same time --proxy is
+used with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
+connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
+HTTPS proxy.
diff --git a/docs/cmdline-opts/socks5.d b/docs/cmdline-opts/socks5.d
deleted file mode 100644
index 0e52166ea..000000000
--- a/docs/cmdline-opts/socks5.d
+++ /dev/null
@@ -1,29 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: socks5
-Arg: <host[:port]>
-Help: SOCKS5 proxy on given host + port
-Added: 7.18.0
-Category: proxy
-Example: --socks5 proxy.example:7000 $URL
-See-also: socks5-hostname socks4a
-Multi: single
----
-Use the specified SOCKS5 proxy - but resolve the host name locally. If the
-port number is not specified, it is assumed at port 1080.
-
-To specify proxy on a unix domain socket, use localhost for host, e.g.
-socks5://localhost/path/to/socket.sock
-
-This option overrides any previous use of --proxy, as they are mutually
-exclusive.
-
-This option is superfluous since you can specify a socks5 proxy with --proxy
-using a socks5:// protocol prefix. (Added in 7.21.7)
-
---preproxy can be used to specify a SOCKS proxy at the same time --proxy is
-used with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
-connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
-HTTPS proxy.
-
-This option (as well as --socks4) does not work with IPV6, FTPS or LDAP.
diff --git a/docs/cmdline-opts/socks5.md b/docs/cmdline-opts/socks5.md
new file mode 100644
index 000000000..a1e185360
--- /dev/null
+++ b/docs/cmdline-opts/socks5.md
@@ -0,0 +1,36 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: socks5
+Arg: <host[:port]>
+Help: SOCKS5 proxy on given host + port
+Added: 7.18.0
+Category: proxy
+Multi: single
+See-also:
+ - socks5-hostname
+ - socks4a
+Example:
+ - --socks5 proxy.example:7000 $URL
+---
+
+# `--socks5`
+
+Use the specified SOCKS5 proxy - but resolve the host name locally. If the
+port number is not specified, it is assumed at port 1080.
+
+To specify proxy on a unix domain socket, use localhost for host, e.g.
+`socks5://localhost/path/to/socket.sock`
+
+This option overrides any previous use of --proxy, as they are mutually
+exclusive.
+
+This option is superfluous since you can specify a socks5 proxy with --proxy
+using a socks5:// protocol prefix. (Added in 7.21.7)
+
+--preproxy can be used to specify a SOCKS proxy at the same time --proxy is
+used with an HTTP/HTTPS proxy (added in 7.52.0). In such a case, curl first
+connects to the SOCKS proxy and then connects (through SOCKS) to the HTTP or
+HTTPS proxy.
+
+This option (as well as --socks4) does not work with IPV6, FTPS or LDAP.
diff --git a/docs/cmdline-opts/speed-limit.d b/docs/cmdline-opts/speed-limit.d
deleted file mode 100644
index dc9778db9..000000000
--- a/docs/cmdline-opts/speed-limit.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: speed-limit
-Short: Y
-Arg: <speed>
-Help: Stop transfers slower than this
-Category: connection
-Example: --speed-limit 300 --speed-time 10 $URL
-Added: 4.7
-See-also: speed-time limit-rate max-time
-Multi: single
----
-If a transfer is slower than this given speed (in bytes per second) for
-speed-time seconds it gets aborted. speed-time is set with --speed-time and is
-30 if not set.
diff --git a/docs/cmdline-opts/speed-limit.md b/docs/cmdline-opts/speed-limit.md
new file mode 100644
index 000000000..b95d6e7d4
--- /dev/null
+++ b/docs/cmdline-opts/speed-limit.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: speed-limit
+Short: Y
+Arg: <speed>
+Help: Stop transfers slower than this
+Category: connection
+Added: 4.7
+Multi: single
+See-also:
+ - speed-time
+ - limit-rate
+ - max-time
+Example:
+ - --speed-limit 300 --speed-time 10 $URL
+---
+
+# `--speed-limit`
+
+If a transfer is slower than this set speed (in bytes per second) for a given
+number of seconds, it gets aborted. The time period is set with --speed-time
+and is 30 seconds by default.
diff --git a/docs/cmdline-opts/speed-time.d b/docs/cmdline-opts/speed-time.d
deleted file mode 100644
index 4a8860660..000000000
--- a/docs/cmdline-opts/speed-time.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: speed-time
-Short: y
-Arg: <seconds>
-Help: Trigger 'speed-limit' abort after this time
-Category: connection
-Example: --speed-limit 300 --speed-time 10 $URL
-Added: 4.7
-See-also: speed-limit limit-rate
-Multi: single
----
-If a transfer runs slower than speed-limit bytes per second during a
-speed-time period, the transfer is aborted. If speed-time is used, the default
-speed-limit is 1 unless set with --speed-limit.
-
-This option controls transfers (in both directions) but does not affect slow
-connects etc. If this is a concern for you, try the --connect-timeout option.
diff --git a/docs/cmdline-opts/speed-time.md b/docs/cmdline-opts/speed-time.md
new file mode 100644
index 000000000..ef8759ee5
--- /dev/null
+++ b/docs/cmdline-opts/speed-time.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: speed-time
+Short: y
+Arg: <seconds>
+Help: Trigger 'speed-limit' abort after this time
+Category: connection
+Added: 4.7
+Multi: single
+See-also:
+ - speed-limit
+ - limit-rate
+Example:
+ - --speed-limit 300 --speed-time 10 $URL
+---
+
+# `--speed-time`
+
+If a transfer runs slower than speed-limit bytes per second during a
+speed-time period, the transfer is aborted. If speed-time is used, the default
+speed-limit is 1 unless set with --speed-limit.
+
+This option controls transfers (in both directions) but does not affect slow
+connects etc. If this is a concern for you, try the --connect-timeout option.
diff --git a/docs/cmdline-opts/ssl-allow-beast.d b/docs/cmdline-opts/ssl-allow-beast.d
deleted file mode 100644
index 2547675d6..000000000
--- a/docs/cmdline-opts/ssl-allow-beast.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ssl-allow-beast
-Help: Allow security flaw to improve interop
-Added: 7.25.0
-Category: tls
-Example: --ssl-allow-beast $URL
-See-also: proxy-ssl-allow-beast insecure
-Multi: boolean
----
-This option tells curl to not work around a security flaw in the SSL3 and
-TLS1.0 protocols known as BEAST. If this option is not used, the SSL layer
-may use workarounds known to cause interoperability problems with some older
-SSL implementations.
-
-**WARNING**: this option loosens the SSL security, and by using this flag you
-ask for exactly that.
diff --git a/docs/cmdline-opts/ssl-allow-beast.md b/docs/cmdline-opts/ssl-allow-beast.md
new file mode 100644
index 000000000..6c144e765
--- /dev/null
+++ b/docs/cmdline-opts/ssl-allow-beast.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ssl-allow-beast
+Help: Allow security flaw to improve interop
+Protocols: TLS
+Added: 7.25.0
+Category: tls
+Multi: boolean
+See-also:
+ - proxy-ssl-allow-beast
+ - insecure
+Example:
+ - --ssl-allow-beast $URL
+---
+
+# `--ssl-allow-beast`
+
+This option tells curl to not work around a security flaw in the SSL3 and
+TLS1.0 protocols known as BEAST. If this option is not used, the SSL layer may
+use workarounds known to cause interoperability problems with some older SSL
+implementations.
+
+**WARNING**: this option loosens the SSL security, and by using this flag you
+ask for exactly that.
diff --git a/docs/cmdline-opts/ssl-auto-client-cert.d b/docs/cmdline-opts/ssl-auto-client-cert.d
deleted file mode 100644
index 5328adea7..000000000
--- a/docs/cmdline-opts/ssl-auto-client-cert.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ssl-auto-client-cert
-Help: Use auto client certificate (Schannel)
-Added: 7.77.0
-See-also: proxy-ssl-auto-client-cert
-Category: tls
-Example: --ssl-auto-client-cert $URL
-Multi: boolean
----
-(Schannel) Tell libcurl to automatically locate and use a client certificate
-for authentication, when requested by the server. Since the server can request
-any certificate that supports client authentication in the OS certificate
-store it could be a privacy violation and unexpected.
diff --git a/docs/cmdline-opts/ssl-auto-client-cert.md b/docs/cmdline-opts/ssl-auto-client-cert.md
new file mode 100644
index 000000000..8ed6fed22
--- /dev/null
+++ b/docs/cmdline-opts/ssl-auto-client-cert.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ssl-auto-client-cert
+Help: Use auto client certificate (Schannel)
+Added: 7.77.0
+Category: tls
+Protocols: TLS
+Multi: boolean
+See-also:
+ - proxy-ssl-auto-client-cert
+Example:
+ - --ssl-auto-client-cert $URL
+---
+
+# `--ssl-auto-client-cert`
+
+(Schannel) Tell libcurl to automatically locate and use a client certificate
+for authentication, when requested by the server. Since the server can request
+any certificate that supports client authentication in the OS certificate
+store it could be a privacy violation and unexpected.
diff --git a/docs/cmdline-opts/ssl-no-revoke.d b/docs/cmdline-opts/ssl-no-revoke.d
deleted file mode 100644
index 37e91d9c2..000000000
--- a/docs/cmdline-opts/ssl-no-revoke.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ssl-no-revoke
-Help: Disable cert revocation checks (Schannel)
-Added: 7.44.0
-Category: tls
-Example: --ssl-no-revoke $URL
-See-also: crlfile
-Multi: boolean
----
-(Schannel) This option tells curl to disable certificate revocation checks.
-WARNING: this option loosens the SSL security, and by using this flag you ask
-for exactly that.
diff --git a/docs/cmdline-opts/ssl-no-revoke.md b/docs/cmdline-opts/ssl-no-revoke.md
new file mode 100644
index 000000000..3f1400cd4
--- /dev/null
+++ b/docs/cmdline-opts/ssl-no-revoke.md
@@ -0,0 +1,20 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ssl-no-revoke
+Help: Disable cert revocation checks (Schannel)
+Added: 7.44.0
+Protocols: TLS
+Category: tls
+Multi: boolean
+See-also:
+ - crlfile
+Example:
+ - --ssl-no-revoke $URL
+---
+
+# `--ssl-no-revoke`
+
+(Schannel) This option tells curl to disable certificate revocation checks.
+WARNING: this option loosens the SSL security, and by using this flag you ask
+for exactly that.
diff --git a/docs/cmdline-opts/ssl-reqd.d b/docs/cmdline-opts/ssl-reqd.d
deleted file mode 100644
index 8a5b8577e..000000000
--- a/docs/cmdline-opts/ssl-reqd.d
+++ /dev/null
@@ -1,23 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ssl-reqd
-Help: Require SSL/TLS
-Protocols: FTP IMAP POP3 SMTP LDAP
-Added: 7.20.0
-Category: tls
-Example: --ssl-reqd ftp://example.com
-See-also: ssl insecure
-Multi: boolean
----
-Require SSL/TLS for the connection. Terminates the connection if the transfer
-cannot be upgraded to use SSL/TLS.
-
-This option is handled in LDAP (added in 7.81.0). It is fully supported by the
-OpenLDAP backend and rejected by the generic ldap backend if explicit TLS is
-required.
-
-This option is unnecessary if you use a URL scheme that in itself implies
-immediate and implicit use of TLS, like for FTPS, IMAPS, POP3S, SMTPS and
-LDAPS. Such a transfer always fails if the TLS handshake does not work.
-
-This option was formerly known as --ftp-ssl-reqd.
diff --git a/docs/cmdline-opts/ssl-reqd.md b/docs/cmdline-opts/ssl-reqd.md
new file mode 100644
index 000000000..eeabc0645
--- /dev/null
+++ b/docs/cmdline-opts/ssl-reqd.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ssl-reqd
+Help: Require SSL/TLS
+Protocols: FTP IMAP POP3 SMTP LDAP
+Added: 7.20.0
+Category: tls
+Multi: boolean
+See-also:
+ - ssl
+ - insecure
+Example:
+ - --ssl-reqd ftp://example.com
+---
+
+# `--ssl-reqd`
+
+Require SSL/TLS for the connection. Terminates the connection if the transfer
+cannot be upgraded to use SSL/TLS.
+
+This option is handled in LDAP (added in 7.81.0). It is fully supported by the
+OpenLDAP backend and rejected by the generic ldap backend if explicit TLS is
+required.
+
+This option is unnecessary if you use a URL scheme that in itself implies
+immediate and implicit use of TLS, like for FTPS, IMAPS, POP3S, SMTPS and
+LDAPS. Such a transfer always fails if the TLS handshake does not work.
+
+This option was formerly known as --ftp-ssl-reqd.
diff --git a/docs/cmdline-opts/ssl-revoke-best-effort.d b/docs/cmdline-opts/ssl-revoke-best-effort.d
deleted file mode 100644
index cb26d0b9a..000000000
--- a/docs/cmdline-opts/ssl-revoke-best-effort.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ssl-revoke-best-effort
-Help: Ignore missing/offline cert CRL dist points (Schannel)
-Added: 7.70.0
-Category: tls
-Example: --ssl-revoke-best-effort $URL
-See-also: crlfile insecure
-Multi: boolean
----
-(Schannel) This option tells curl to ignore certificate revocation checks when
-they failed due to missing/offline distribution points for the revocation check
-lists.
diff --git a/docs/cmdline-opts/ssl-revoke-best-effort.md b/docs/cmdline-opts/ssl-revoke-best-effort.md
new file mode 100644
index 000000000..77fb87674
--- /dev/null
+++ b/docs/cmdline-opts/ssl-revoke-best-effort.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ssl-revoke-best-effort
+Help: Ignore missing/offline cert CRL dist points (Schannel)
+Added: 7.70.0
+Protocols: TLS
+Category: tls
+Multi: boolean
+See-also:
+ - crlfile
+ - insecure
+Example:
+ - --ssl-revoke-best-effort $URL
+---
+
+# `--ssl-revoke-best-effort`
+
+(Schannel) This option tells curl to ignore certificate revocation checks when
+they failed due to missing/offline distribution points for the revocation check
+lists.
diff --git a/docs/cmdline-opts/ssl.d b/docs/cmdline-opts/ssl.d
deleted file mode 100644
index b8fd22a9c..000000000
--- a/docs/cmdline-opts/ssl.d
+++ /dev/null
@@ -1,26 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: ssl
-Help: Try SSL/TLS
-Protocols: FTP IMAP POP3 SMTP LDAP
-Added: 7.20.0
-Category: tls
-Example: --ssl pop3://example.com/
-See-also: ssl-reqd insecure ciphers
-Multi: boolean
----
-Warning: this is considered an insecure option. Consider using --ssl-reqd
-instead to be sure curl upgrades to a secure connection.
-
-Try to use SSL/TLS for the connection. Reverts to a non-secure connection if
-the server does not support SSL/TLS. See also --ftp-ssl-control and --ssl-reqd
-for different levels of encryption required.
-
-This option is handled in LDAP (added in 7.81.0). It is fully supported by the
-OpenLDAP backend and ignored by the generic ldap backend.
-
-Please note that a server may close the connection if the negotiation does
-not succeed.
-
-This option was formerly known as --ftp-ssl (added in 7.11.0). That option
-name can still be used but might be removed in a future version.
diff --git a/docs/cmdline-opts/ssl.md b/docs/cmdline-opts/ssl.md
new file mode 100644
index 000000000..9a78ae3a2
--- /dev/null
+++ b/docs/cmdline-opts/ssl.md
@@ -0,0 +1,34 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: ssl
+Help: Try SSL/TLS
+Protocols: FTP IMAP POP3 SMTP LDAP
+Added: 7.20.0
+Category: tls
+Multi: boolean
+See-also:
+ - ssl-reqd
+ - insecure
+ - ciphers
+Example:
+ - --ssl pop3://example.com/
+---
+
+# `--ssl`
+
+Warning: this is considered an insecure option. Consider using --ssl-reqd
+instead to be sure curl upgrades to a secure connection.
+
+Try to use SSL/TLS for the connection. Reverts to a non-secure connection if
+the server does not support SSL/TLS. See also --ftp-ssl-control and --ssl-reqd
+for different levels of encryption required.
+
+This option is handled in LDAP (added in 7.81.0). It is fully supported by the
+OpenLDAP backend and ignored by the generic ldap backend.
+
+Please note that a server may close the connection if the negotiation does
+not succeed.
+
+This option was formerly known as --ftp-ssl (added in 7.11.0). That option
+name can still be used but might be removed in a future version.
diff --git a/docs/cmdline-opts/sslv2.d b/docs/cmdline-opts/sslv2.d
deleted file mode 100644
index 3ecf109a0..000000000
--- a/docs/cmdline-opts/sslv2.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: 2
-Long: sslv2
-Tags: Versions
-Protocols: SSL
-Added: 5.9
-Mutexed: sslv3 tlsv1 tlsv1.1 tlsv1.2
-Requires: TLS
-See-also: http1.1 http2
-Help: Use SSLv2
-Category: tls
-Example: --sslv2 $URL
-Multi: mutex
----
-This option previously asked curl to use SSLv2, but is now ignored
-(added in 7.77.0). SSLv2 is widely considered insecure (see RFC 6176).
diff --git a/docs/cmdline-opts/sslv2.md b/docs/cmdline-opts/sslv2.md
new file mode 100644
index 000000000..05fe938ba
--- /dev/null
+++ b/docs/cmdline-opts/sslv2.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: 2
+Long: sslv2
+Tags: Versions
+Protocols: SSL
+Added: 5.9
+Mutexed: sslv3 tlsv1 tlsv1.1 tlsv1.2
+Requires: TLS
+Help: Use SSLv2
+Category: tls
+Multi: mutex
+See-also:
+ - http1.1
+ - http2
+Example:
+ - --sslv2 $URL
+---
+
+# `--sslv2`
+
+This option previously asked curl to use SSLv2, but is now ignored
+(added in 7.77.0). SSLv2 is widely considered insecure (see RFC 6176).
diff --git a/docs/cmdline-opts/sslv3.d b/docs/cmdline-opts/sslv3.d
deleted file mode 100644
index 409afc610..000000000
--- a/docs/cmdline-opts/sslv3.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: 3
-Long: sslv3
-Tags: Versions
-Protocols: SSL
-Added: 5.9
-Mutexed: sslv2 tlsv1 tlsv1.1 tlsv1.2
-Requires: TLS
-See-also: http1.1 http2
-Help: Use SSLv3
-Category: tls
-Example: --sslv3 $URL
-Multi: mutex
----
-This option previously asked curl to use SSLv3, but is now ignored
-(added in 7.77.0). SSLv3 is widely considered insecure (see RFC 7568).
diff --git a/docs/cmdline-opts/sslv3.md b/docs/cmdline-opts/sslv3.md
new file mode 100644
index 000000000..343f628a5
--- /dev/null
+++ b/docs/cmdline-opts/sslv3.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: 3
+Long: sslv3
+Tags: Versions
+Protocols: SSL
+Added: 5.9
+Mutexed: sslv2 tlsv1 tlsv1.1 tlsv1.2
+Requires: TLS
+Help: Use SSLv3
+Category: tls
+Multi: mutex
+See-also:
+ - http1.1
+ - http2
+Example:
+ - --sslv3 $URL
+---
+
+# `--sslv3`
+
+This option previously asked curl to use SSLv3, but is now ignored
+(added in 7.77.0). SSLv3 is widely considered insecure (see RFC 7568).
diff --git a/docs/cmdline-opts/stderr.d b/docs/cmdline-opts/stderr.d
deleted file mode 100644
index a80bf43d1..000000000
--- a/docs/cmdline-opts/stderr.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: stderr
-Arg: <file>
-Help: Where to redirect stderr
-See-also: verbose silent
-Category: verbose
-Example: --stderr output.txt $URL
-Added: 6.2
-Multi: single
-Scope: global
----
-Redirect all writes to stderr to the specified file instead. If the file name
-is a plain '-', it is instead written to stdout.
diff --git a/docs/cmdline-opts/stderr.md b/docs/cmdline-opts/stderr.md
new file mode 100644
index 000000000..6c93dc8a3
--- /dev/null
+++ b/docs/cmdline-opts/stderr.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: stderr
+Arg: <file>
+Help: Where to redirect stderr
+Category: verbose
+Added: 6.2
+Multi: single
+Scope: global
+See-also:
+ - verbose
+ - silent
+Example:
+ - --stderr output.txt $URL
+---
+
+# `--stderr`
+
+Redirect all writes to stderr to the specified file instead. If the file name
+is a plain '-', it is instead written to stdout.
diff --git a/docs/cmdline-opts/styled-output.d b/docs/cmdline-opts/styled-output.d
deleted file mode 100644
index 70e9da4e8..000000000
--- a/docs/cmdline-opts/styled-output.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: styled-output
-Help: Enable styled output for HTTP headers
-Added: 7.61.0
-Category: verbose
-Example: --styled-output -I $URL
-See-also: head verbose
-Multi: boolean
-Scope: global
----
-Enables the automatic use of bold font styles when writing HTTP headers to the
-terminal. Use --no-styled-output to switch them off.
-
-Styled output requires a terminal that supports bold fonts. This feature is
-not present on curl for Windows due to lack of this capability.
diff --git a/docs/cmdline-opts/styled-output.md b/docs/cmdline-opts/styled-output.md
new file mode 100644
index 000000000..1df472aed
--- /dev/null
+++ b/docs/cmdline-opts/styled-output.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: styled-output
+Help: Enable styled output for HTTP headers
+Added: 7.61.0
+Category: verbose
+Multi: boolean
+Scope: global
+See-also:
+ - head
+ - verbose
+Example:
+ - --styled-output -I $URL
+---
+
+# `--styled-output`
+
+Enables the automatic use of bold font styles when writing HTTP headers to the
+terminal. Use --no-styled-output to switch them off.
+
+Styled output requires a terminal that supports bold fonts. This feature is
+not present on curl for Windows due to lack of this capability.
diff --git a/docs/cmdline-opts/suppress-connect-headers.d b/docs/cmdline-opts/suppress-connect-headers.d
deleted file mode 100644
index ed38f36de..000000000
--- a/docs/cmdline-opts/suppress-connect-headers.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: suppress-connect-headers
-Help: Suppress proxy CONNECT response headers
-See-also: dump-header include proxytunnel
-Category: proxy
-Example: --suppress-connect-headers --include -x proxy $URL
-Added: 7.54.0
-Multi: boolean
----
-When --proxytunnel is used and a CONNECT request is made do not output proxy
-CONNECT response headers. This option is meant to be used with --dump-header or
---include which are used to show protocol headers in the output. It has no
-effect on debug options such as --verbose or --trace, or any statistics.
diff --git a/docs/cmdline-opts/suppress-connect-headers.md b/docs/cmdline-opts/suppress-connect-headers.md
new file mode 100644
index 000000000..9e2eefea4
--- /dev/null
+++ b/docs/cmdline-opts/suppress-connect-headers.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: suppress-connect-headers
+Help: Suppress proxy CONNECT response headers
+Category: proxy
+Added: 7.54.0
+Multi: boolean
+See-also:
+ - dump-header
+ - include
+ - proxytunnel
+Example:
+ - --suppress-connect-headers --include -x proxy $URL
+---
+
+# `--suppress-connect-headers`
+
+When --proxytunnel is used and a CONNECT request is made do not output proxy
+CONNECT response headers. This option is meant to be used with --dump-header or
+--include which are used to show protocol headers in the output. It has no
+effect on debug options such as --verbose or --trace, or any statistics.
diff --git a/docs/cmdline-opts/tcp-fastopen.d b/docs/cmdline-opts/tcp-fastopen.d
deleted file mode 100644
index bcf1edbff..000000000
--- a/docs/cmdline-opts/tcp-fastopen.d
+++ /dev/null
@@ -1,14 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tcp-fastopen
-Added: 7.49.0
-Help: Use TCP Fast Open
-Category: connection
-Example: --tcp-fastopen $URL
-See-also: false-start
-Multi: boolean
----
-
-Enable use of TCP Fast Open (RFC 7413). TCP Fast Open is a TCP extension that
-allows data to get sent earlier over the connection (before the final
-handshake ACK) if the client and server have been connected previously.
diff --git a/docs/cmdline-opts/tcp-fastopen.md b/docs/cmdline-opts/tcp-fastopen.md
new file mode 100644
index 000000000..9a7c2b0a0
--- /dev/null
+++ b/docs/cmdline-opts/tcp-fastopen.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tcp-fastopen
+Added: 7.49.0
+Help: Use TCP Fast Open
+Category: connection
+Multi: boolean
+See-also:
+ - false-start
+Example:
+ - --tcp-fastopen $URL
+---
+
+# `--tcp-fastopen`
+
+Enable use of TCP Fast Open (RFC 7413). TCP Fast Open is a TCP extension that
+allows data to get sent earlier over the connection (before the final
+handshake ACK) if the client and server have been connected previously.
diff --git a/docs/cmdline-opts/tcp-nodelay.d b/docs/cmdline-opts/tcp-nodelay.d
deleted file mode 100644
index 2bf51cb5f..000000000
--- a/docs/cmdline-opts/tcp-nodelay.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tcp-nodelay
-Help: Use the TCP_NODELAY option
-Added: 7.11.2
-Category: connection
-Example: --tcp-nodelay $URL
-See-also: no-buffer
-Multi: boolean
----
-Turn on the TCP_NODELAY option. See the *curl_easy_setopt(3)* man page for
-details about this option.
-
-curl sets this option by default and you need to explicitly switch it off if
-you do not want it on (added in 7.50.2).
diff --git a/docs/cmdline-opts/tcp-nodelay.md b/docs/cmdline-opts/tcp-nodelay.md
new file mode 100644
index 000000000..9a6df8d62
--- /dev/null
+++ b/docs/cmdline-opts/tcp-nodelay.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tcp-nodelay
+Help: Use the TCP_NODELAY option
+Added: 7.11.2
+Category: connection
+Multi: boolean
+See-also:
+ - no-buffer
+Example:
+ - --tcp-nodelay $URL
+---
+
+# `--tcp-nodelay`
+
+Turn on the TCP_NODELAY option. See the *curl_easy_setopt(3)* man page for
+details about this option.
+
+curl sets this option by default and you need to explicitly switch it off if
+you do not want it on (added in 7.50.2).
diff --git a/docs/cmdline-opts/telnet-option.d b/docs/cmdline-opts/telnet-option.d
deleted file mode 100644
index 651ce4203..000000000
--- a/docs/cmdline-opts/telnet-option.d
+++ /dev/null
@@ -1,23 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: telnet-option
-Short: t
-Arg: <opt=val>
-Help: Set telnet option
-Category: telnet
-Example: -t TTYPE=vt100 telnet://example.com/
-Added: 7.7
-See-also: config
-Multi: append
----
-Pass options to the telnet protocol. Supported options are:
-
-.RS
-.TP 15
-**TTYPE**=<term> Sets the terminal type.
-.TP
-**XDISPLOC**=<X display> Sets the X display location.
-.TP
-**NEW_ENV**=<var,val> Sets an environment variable.
-.RE
-.IP
diff --git a/docs/cmdline-opts/telnet-option.md b/docs/cmdline-opts/telnet-option.md
new file mode 100644
index 000000000..a332b1a5c
--- /dev/null
+++ b/docs/cmdline-opts/telnet-option.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: telnet-option
+Short: t
+Arg: <opt=val>
+Help: Set telnet option
+Category: telnet
+Added: 7.7
+Multi: append
+See-also:
+ - config
+Example:
+ - -t TTYPE=vt100 telnet://example.com/
+---
+
+# `--telnet-option`
+
+Pass options to the telnet protocol. Supported options are:
+
+## `TTYPE=<term>`
+Sets the terminal type.
+
+## `XDISPLOC=<X display>`
+Sets the X display location.
+
+## `NEW_ENV=<var,val>`
+Sets an environment variable.
diff --git a/docs/cmdline-opts/tftp-blksize.d b/docs/cmdline-opts/tftp-blksize.d
deleted file mode 100644
index 76c7ee4b1..000000000
--- a/docs/cmdline-opts/tftp-blksize.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tftp-blksize
-Arg: <value>
-Help: Set TFTP BLKSIZE option
-Protocols: TFTP
-Added: 7.20.0
-Category: tftp
-Example: --tftp-blksize 1024 tftp://example.com/file
-See-also: tftp-no-options
-Multi: single
----
-Set the TFTP **BLKSIZE** option (must be >512). This is the block size that
-curl tries to use when transferring data to or from a TFTP server. By
-default 512 bytes are used.
diff --git a/docs/cmdline-opts/tftp-blksize.md b/docs/cmdline-opts/tftp-blksize.md
new file mode 100644
index 000000000..b059d4b40
--- /dev/null
+++ b/docs/cmdline-opts/tftp-blksize.md
@@ -0,0 +1,21 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tftp-blksize
+Arg: <value>
+Help: Set TFTP BLKSIZE option
+Protocols: TFTP
+Added: 7.20.0
+Category: tftp
+Multi: single
+See-also:
+ - tftp-no-options
+Example:
+ - --tftp-blksize 1024 tftp://example.com/file
+---
+
+# `--tftp-blksize`
+
+Set the TFTP **BLKSIZE** option (must be >512). This is the block size that
+curl tries to use when transferring data to or from a TFTP server. By
+default 512 bytes are used.
diff --git a/docs/cmdline-opts/tftp-no-options.d b/docs/cmdline-opts/tftp-no-options.d
deleted file mode 100644
index 43b1c00c4..000000000
--- a/docs/cmdline-opts/tftp-no-options.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tftp-no-options
-Help: Do not send any TFTP options
-Protocols: TFTP
-Added: 7.48.0
-Category: tftp
-Example: --tftp-no-options tftp://192.168.0.1/
-See-also: tftp-blksize
-Multi: boolean
----
-Tells curl not to send TFTP options requests.
-
-This option improves interop with some legacy servers that do not acknowledge
-or properly implement TFTP options. When this option is used --tftp-blksize is
-ignored.
diff --git a/docs/cmdline-opts/tftp-no-options.md b/docs/cmdline-opts/tftp-no-options.md
new file mode 100644
index 000000000..518816c29
--- /dev/null
+++ b/docs/cmdline-opts/tftp-no-options.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tftp-no-options
+Help: Do not send any TFTP options
+Protocols: TFTP
+Added: 7.48.0
+Category: tftp
+Multi: boolean
+See-also:
+ - tftp-blksize
+Example:
+ - --tftp-no-options tftp://192.168.0.1/
+---
+
+# `--tftp-no-options`
+
+Tells curl not to send TFTP options requests.
+
+This option improves interop with some legacy servers that do not acknowledge
+or properly implement TFTP options. When this option is used --tftp-blksize is
+ignored.
diff --git a/docs/cmdline-opts/time-cond.d b/docs/cmdline-opts/time-cond.d
deleted file mode 100644
index c21ed2853..000000000
--- a/docs/cmdline-opts/time-cond.d
+++ /dev/null
@@ -1,27 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: time-cond
-Short: z
-Arg: <time>
-Help: Transfer based on a time condition
-Protocols: HTTP FTP
-Category: http ftp
-Example: -z "Wed 01 Sep 2021 12:18:00" $URL
-Example: -z "-Wed 01 Sep 2021 12:18:00" $URL
-Example: -z file $URL
-Added: 5.8
-See-also: etag-compare remote-time
-Multi: single
----
-Request a file that has been modified later than the given time and date, or
-one that has been modified before that time. The <date expression> can be all
-sorts of date strings or if it does not match any internal ones, it is taken as
-a filename and tries to get the modification date (mtime) from <file>
-instead. See the *curl_getdate(3)* man pages for date expression details.
-
-Start the date expression with a dash (-) to make it request for a document
-that is older than the given date/time, default is a document that is newer
-than the specified date/time.
-
-If provided a non-existing file, curl outputs a warning about that fact and
-proceeds to do the transfer without a time condition.
diff --git a/docs/cmdline-opts/time-cond.md b/docs/cmdline-opts/time-cond.md
new file mode 100644
index 000000000..5b1c91eb0
--- /dev/null
+++ b/docs/cmdline-opts/time-cond.md
@@ -0,0 +1,34 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: time-cond
+Short: z
+Arg: <time>
+Help: Transfer based on a time condition
+Protocols: HTTP FTP
+Category: http ftp
+Added: 5.8
+Multi: single
+See-also:
+ - etag-compare
+ - remote-time
+Example:
+ - -z "Wed 01 Sep 2021 12:18:00" $URL
+ - -z "-Wed 01 Sep 2021 12:18:00" $URL
+ - -z file $URL
+---
+
+# `--time-cond`
+
+Request a file that has been modified later than the given time and date, or
+one that has been modified before that time. The <date expression> can be all
+sorts of date strings or if it does not match any internal ones, it is taken as
+a filename and tries to get the modification date (mtime) from <file>
+instead. See the *curl_getdate(3)* man pages for date expression details.
+
+Start the date expression with a dash (-) to make it request for a document
+that is older than the given date/time, default is a document that is newer
+than the specified date/time.
+
+If provided a non-existing file, curl outputs a warning about that fact and
+proceeds to do the transfer without a time condition.
diff --git a/docs/cmdline-opts/tls-max.d b/docs/cmdline-opts/tls-max.d
deleted file mode 100644
index 2d52c1039..000000000
--- a/docs/cmdline-opts/tls-max.d
+++ /dev/null
@@ -1,34 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tls-max
-Arg: <VERSION>
-Tags: Versions
-Protocols: TLS
-Added: 7.54.0
-Requires: TLS
-See-also: tlsv1.0 tlsv1.1 tlsv1.2 tlsv1.3
-Help: Set maximum allowed TLS version
-Category: tls
-Example: --tls-max 1.2 $URL
-Example: --tls-max 1.3 --tlsv1.2 $URL
-Multi: single
----
-VERSION defines maximum supported TLS version. The minimum acceptable version
-is set by tlsv1.0, tlsv1.1, tlsv1.2 or tlsv1.3.
-
-If the connection is done without TLS, this option has no effect. This
-includes QUIC-using (HTTP/3) transfers.
-
-.RS
-.IP "default"
-Use up to recommended TLS version.
-.IP "1.0"
-Use up to TLSv1.0.
-.IP "1.1"
-Use up to TLSv1.1.
-.IP "1.2"
-Use up to TLSv1.2.
-.IP "1.3"
-Use up to TLSv1.3.
-.RE
-.IP
diff --git a/docs/cmdline-opts/tls-max.md b/docs/cmdline-opts/tls-max.md
new file mode 100644
index 000000000..a815d21d6
--- /dev/null
+++ b/docs/cmdline-opts/tls-max.md
@@ -0,0 +1,44 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tls-max
+Arg: <VERSION>
+Tags: Versions
+Protocols: TLS
+Added: 7.54.0
+Requires: TLS
+Help: Set maximum allowed TLS version
+Category: tls
+Multi: single
+See-also:
+ - tlsv1.0
+ - tlsv1.1
+ - tlsv1.2
+ - tlsv1.3
+Example:
+ - --tls-max 1.2 $URL
+ - --tls-max 1.3 --tlsv1.2 $URL
+---
+
+# `--tls-max`
+
+VERSION defines maximum supported TLS version. The minimum acceptable version
+is set by tlsv1.0, tlsv1.1, tlsv1.2 or tlsv1.3.
+
+If the connection is done without TLS, this option has no effect. This
+includes QUIC-using (HTTP/3) transfers.
+
+## default
+Use up to recommended TLS version.
+
+## 1.0
+Use up to TLSv1.0.
+
+## 1.1
+Use up to TLSv1.1.
+
+## 1.2
+Use up to TLSv1.2.
+
+## 1.3
+Use up to TLSv1.3.
diff --git a/docs/cmdline-opts/tls13-ciphers.d b/docs/cmdline-opts/tls13-ciphers.d
deleted file mode 100644
index 34c607dd1..000000000
--- a/docs/cmdline-opts/tls13-ciphers.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tls13-ciphers
-Arg: <ciphersuite list>
-help: TLS 1.3 cipher suites to use
-Protocols: TLS
-Category: tls
-Example: --tls13-ciphers TLS_AES_128_GCM_SHA256 $URL
-Added: 7.61.0
-See-also: ciphers curves proxy-tls13-ciphers
-Multi: single
----
-Specifies which cipher suites to use in the connection if it negotiates TLS
-1.3. The list of ciphers suites must specify valid ciphers. Read up on TLS 1.3
-cipher suite details on this URL:
-
-https://curl.se/docs/ssl-ciphers.html
-
-This option is currently used only when curl is built to use OpenSSL 1.1.1 or
-later, or Schannel. If you are using a different SSL backend you can try
-setting TLS 1.3 cipher suites by using the --ciphers option.
diff --git a/docs/cmdline-opts/tls13-ciphers.md b/docs/cmdline-opts/tls13-ciphers.md
new file mode 100644
index 000000000..2f68a6195
--- /dev/null
+++ b/docs/cmdline-opts/tls13-ciphers.md
@@ -0,0 +1,29 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tls13-ciphers
+Arg: <ciphersuite list>
+help: TLS 1.3 cipher suites to use
+Protocols: TLS
+Category: tls
+Added: 7.61.0
+Multi: single
+See-also:
+ - ciphers
+ - curves
+ - proxy-tls13-ciphers
+Example:
+ - --tls13-ciphers TLS_AES_128_GCM_SHA256 $URL
+---
+
+# `--tls13-ciphers`
+
+Specifies which cipher suites to use in the connection if it negotiates TLS
+1.3. The list of ciphers suites must specify valid ciphers. Read up on TLS 1.3
+cipher suite details on this URL:
+
+https://curl.se/docs/ssl-ciphers.html
+
+This option is currently used only when curl is built to use OpenSSL 1.1.1 or
+later, or Schannel. If you are using a different SSL backend you can try
+setting TLS 1.3 cipher suites by using the --ciphers option.
diff --git a/docs/cmdline-opts/tlsauthtype.d b/docs/cmdline-opts/tlsauthtype.d
deleted file mode 100644
index 7d3f7e5aa..000000000
--- a/docs/cmdline-opts/tlsauthtype.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tlsauthtype
-Arg: <type>
-Help: TLS authentication type
-Added: 7.21.4
-Category: tls auth
-Example: --tlsauthtype SRP $URL
-See-also: tlsuser
-Multi: single
----
-Set TLS authentication type. Currently, the only supported option is "SRP",
-for TLS-SRP (RFC 5054). If --tlsuser and --tlspassword are specified but
---tlsauthtype is not, then this option defaults to "SRP". This option works
-only if the underlying libcurl is built with TLS-SRP support, which requires
-OpenSSL or GnuTLS with TLS-SRP support.
diff --git a/docs/cmdline-opts/tlsauthtype.md b/docs/cmdline-opts/tlsauthtype.md
new file mode 100644
index 000000000..dd2684814
--- /dev/null
+++ b/docs/cmdline-opts/tlsauthtype.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tlsauthtype
+Arg: <type>
+Help: TLS authentication type
+Protocols: TLS
+Added: 7.21.4
+Category: tls auth
+Multi: single
+See-also:
+ - tlsuser
+Example:
+ - --tlsauthtype SRP $URL
+---
+
+# `--tlsauthtype`
+
+Set TLS authentication type. Currently, the only supported option is "SRP",
+for TLS-SRP (RFC 5054). If --tlsuser and --tlspassword are specified but
+--tlsauthtype is not, then this option defaults to "SRP". This option works
+only if the underlying libcurl is built with TLS-SRP support, which requires
+OpenSSL or GnuTLS with TLS-SRP support.
diff --git a/docs/cmdline-opts/tlspassword.d b/docs/cmdline-opts/tlspassword.d
deleted file mode 100644
index 0513191ae..000000000
--- a/docs/cmdline-opts/tlspassword.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tlspassword
-Arg: <string>
-Help: TLS password
-Added: 7.21.4
-Category: tls auth
-Example: --tlspassword pwd --tlsuser user $URL
-See-also: tlsuser
-Multi: single
----
-Set password for use with the TLS authentication method specified with
---tlsauthtype. Requires that --tlsuser also be set.
-
-This option does not work with TLS 1.3.
diff --git a/docs/cmdline-opts/tlspassword.md b/docs/cmdline-opts/tlspassword.md
new file mode 100644
index 000000000..4b1817994
--- /dev/null
+++ b/docs/cmdline-opts/tlspassword.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tlspassword
+Arg: <string>
+Help: TLS password
+Added: 7.21.4
+Protocols: TLS
+Category: tls auth
+Multi: single
+See-also:
+ - tlsuser
+Example:
+ - --tlspassword pwd --tlsuser user $URL
+---
+
+# `--tlspassword`
+
+Set password for use with the TLS authentication method specified with
+--tlsauthtype. Requires that --tlsuser also be set.
+
+This option does not work with TLS 1.3.
diff --git a/docs/cmdline-opts/tlsuser.d b/docs/cmdline-opts/tlsuser.d
deleted file mode 100644
index f87532a7c..000000000
--- a/docs/cmdline-opts/tlsuser.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tlsuser
-Arg: <name>
-Help: TLS user name
-Added: 7.21.4
-Category: tls auth
-Example: --tlspassword pwd --tlsuser user $URL
-See-also: tlspassword
-Multi: single
----
-Set username for use with the TLS authentication method specified with
---tlsauthtype. Requires that --tlspassword also is set.
-
-This option does not work with TLS 1.3.
diff --git a/docs/cmdline-opts/tlsuser.md b/docs/cmdline-opts/tlsuser.md
new file mode 100644
index 000000000..5ffbb6705
--- /dev/null
+++ b/docs/cmdline-opts/tlsuser.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tlsuser
+Arg: <name>
+Help: TLS user name
+Added: 7.21.4
+Protocols: TLS
+Category: tls auth
+Multi: single
+See-also:
+ - tlspassword
+Example:
+ - --tlspassword pwd --tlsuser user $URL
+---
+
+# `--tlsuser`
+
+Set username for use with the TLS authentication method specified with
+--tlsauthtype. Requires that --tlspassword also is set.
+
+This option does not work with TLS 1.3.
diff --git a/docs/cmdline-opts/tlsv1.0.d b/docs/cmdline-opts/tlsv1.0.d
deleted file mode 100644
index 493c0c653..000000000
--- a/docs/cmdline-opts/tlsv1.0.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tlsv1.0
-Help: Use TLSv1.0 or greater
-Protocols: TLS
-Added: 7.34.0
-Category: tls
-Example: --tlsv1.0 $URL
-See-also: tlsv1.3
-Multi: mutex
----
-Forces curl to use TLS version 1.0 or later when connecting to a remote TLS server.
-
-In old versions of curl this option was documented to allow _only_ TLS 1.0.
-That behavior was inconsistent depending on the TLS library. Use --tls-max if
-you want to set a maximum TLS version.
diff --git a/docs/cmdline-opts/tlsv1.0.md b/docs/cmdline-opts/tlsv1.0.md
new file mode 100644
index 000000000..01aa0aea0
--- /dev/null
+++ b/docs/cmdline-opts/tlsv1.0.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tlsv1.0
+Help: Use TLSv1.0 or greater
+Protocols: TLS
+Added: 7.34.0
+Category: tls
+Multi: mutex
+See-also:
+ - tlsv1.3
+Example:
+ - --tlsv1.0 $URL
+---
+
+# `--tlsv1.0`
+
+Forces curl to use TLS version 1.0 or later when connecting to a remote TLS server.
+
+In old versions of curl this option was documented to allow _only_ TLS 1.0.
+That behavior was inconsistent depending on the TLS library. Use --tls-max if
+you want to set a maximum TLS version.
diff --git a/docs/cmdline-opts/tlsv1.1.d b/docs/cmdline-opts/tlsv1.1.d
deleted file mode 100644
index f8ecdf67a..000000000
--- a/docs/cmdline-opts/tlsv1.1.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tlsv1.1
-Help: Use TLSv1.1 or greater
-Protocols: TLS
-Added: 7.34.0
-Category: tls
-Example: --tlsv1.1 $URL
-See-also: tlsv1.3 tls-max
-Multi: mutex
----
-Forces curl to use TLS version 1.1 or later when connecting to a remote TLS server.
-
-In old versions of curl this option was documented to allow _only_ TLS 1.1.
-That behavior was inconsistent depending on the TLS library. Use --tls-max if
-you want to set a maximum TLS version.
diff --git a/docs/cmdline-opts/tlsv1.1.md b/docs/cmdline-opts/tlsv1.1.md
new file mode 100644
index 000000000..b0d17838c
--- /dev/null
+++ b/docs/cmdline-opts/tlsv1.1.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tlsv1.1
+Help: Use TLSv1.1 or greater
+Protocols: TLS
+Added: 7.34.0
+Category: tls
+Multi: mutex
+See-also:
+ - tlsv1.3
+ - tls-max
+Example:
+ - --tlsv1.1 $URL
+---
+
+# `--tlsv1.1`
+
+Forces curl to use TLS version 1.1 or later when connecting to a remote TLS server.
+
+In old versions of curl this option was documented to allow _only_ TLS 1.1.
+That behavior was inconsistent depending on the TLS library. Use --tls-max if
+you want to set a maximum TLS version.
diff --git a/docs/cmdline-opts/tlsv1.2.d b/docs/cmdline-opts/tlsv1.2.d
deleted file mode 100644
index a9953604e..000000000
--- a/docs/cmdline-opts/tlsv1.2.d
+++ /dev/null
@@ -1,16 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tlsv1.2
-Help: Use TLSv1.2 or greater
-Protocols: TLS
-Added: 7.34.0
-Category: tls
-Example: --tlsv1.2 $URL
-See-also: tlsv1.3 tls-max
-Multi: mutex
----
-Forces curl to use TLS version 1.2 or later when connecting to a remote TLS server.
-
-In old versions of curl this option was documented to allow _only_ TLS 1.2.
-That behavior was inconsistent depending on the TLS library. Use --tls-max if
-you want to set a maximum TLS version.
diff --git a/docs/cmdline-opts/tlsv1.2.md b/docs/cmdline-opts/tlsv1.2.md
new file mode 100644
index 000000000..b39c9abca
--- /dev/null
+++ b/docs/cmdline-opts/tlsv1.2.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tlsv1.2
+Help: Use TLSv1.2 or greater
+Protocols: TLS
+Added: 7.34.0
+Category: tls
+Multi: mutex
+See-also:
+ - tlsv1.3
+ - tls-max
+Example:
+ - --tlsv1.2 $URL
+---
+
+# `--tlsv1.2`
+
+Forces curl to use TLS version 1.2 or later when connecting to a remote TLS server.
+
+In old versions of curl this option was documented to allow _only_ TLS 1.2.
+That behavior was inconsistent depending on the TLS library. Use --tls-max if
+you want to set a maximum TLS version.
diff --git a/docs/cmdline-opts/tlsv1.3.d b/docs/cmdline-opts/tlsv1.3.d
deleted file mode 100644
index 5690aa113..000000000
--- a/docs/cmdline-opts/tlsv1.3.d
+++ /dev/null
@@ -1,18 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tlsv1.3
-Help: Use TLSv1.3 or greater
-Protocols: TLS
-Added: 7.52.0
-Category: tls
-Example: --tlsv1.3 $URL
-See-also: tlsv1.2 tls-max
-Multi: mutex
----
-Forces curl to use TLS version 1.3 or later when connecting to a remote TLS
-server.
-
-If the connection is done without TLS, this option has no effect. This
-includes QUIC-using (HTTP/3) transfers.
-
-Note that TLS 1.3 is not supported by all TLS backends.
diff --git a/docs/cmdline-opts/tlsv1.3.md b/docs/cmdline-opts/tlsv1.3.md
new file mode 100644
index 000000000..537b372a1
--- /dev/null
+++ b/docs/cmdline-opts/tlsv1.3.md
@@ -0,0 +1,25 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tlsv1.3
+Help: Use TLSv1.3 or greater
+Protocols: TLS
+Added: 7.52.0
+Category: tls
+Multi: mutex
+See-also:
+ - tlsv1.2
+ - tls-max
+Example:
+ - --tlsv1.3 $URL
+---
+
+# `--tlsv1.3`
+
+Forces curl to use TLS version 1.3 or later when connecting to a remote TLS
+server.
+
+If the connection is done without TLS, this option has no effect. This
+includes QUIC-using (HTTP/3) transfers.
+
+Note that TLS 1.3 is not supported by all TLS backends.
diff --git a/docs/cmdline-opts/tlsv1.d b/docs/cmdline-opts/tlsv1.d
deleted file mode 100644
index 16aee71a3..000000000
--- a/docs/cmdline-opts/tlsv1.d
+++ /dev/null
@@ -1,17 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: 1
-Long: tlsv1
-Tags: Versions
-Protocols: TLS
-Added: 7.9.2
-Mutexed: tlsv1.1 tlsv1.2 tlsv1.3
-Requires: TLS
-See-also: http1.1 http2
-Help: Use TLSv1.0 or greater
-Category: tls
-Example: --tlsv1 $URL
-Multi: mutex
----
-Tells curl to use at least TLS version 1.x when negotiating with a remote TLS
-server. That means TLS version 1.0 or higher
diff --git a/docs/cmdline-opts/tlsv1.md b/docs/cmdline-opts/tlsv1.md
new file mode 100644
index 000000000..bed9db096
--- /dev/null
+++ b/docs/cmdline-opts/tlsv1.md
@@ -0,0 +1,24 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: 1
+Long: tlsv1
+Tags: Versions
+Protocols: TLS
+Added: 7.9.2
+Mutexed: tlsv1.1 tlsv1.2 tlsv1.3
+Requires: TLS
+Help: Use TLSv1.0 or greater
+Category: tls
+Multi: mutex
+See-also:
+ - http1.1
+ - http2
+Example:
+ - --tlsv1 $URL
+---
+
+# `--tlsv1`
+
+Tells curl to use at least TLS version 1.x when negotiating with a remote TLS
+server. That means TLS version 1.0 or higher
diff --git a/docs/cmdline-opts/tr-encoding.d b/docs/cmdline-opts/tr-encoding.d
deleted file mode 100644
index 053e18ca1..000000000
--- a/docs/cmdline-opts/tr-encoding.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: tr-encoding
-Added: 7.21.6
-Help: Request compressed transfer encoding
-Protocols: HTTP
-Category: http
-Example: --tr-encoding $URL
-See-also: compressed
-Multi: boolean
----
-Request a compressed Transfer-Encoding response using one of the algorithms
-curl supports, and uncompress the data while receiving it.
diff --git a/docs/cmdline-opts/tr-encoding.md b/docs/cmdline-opts/tr-encoding.md
new file mode 100644
index 000000000..cdd8f02d6
--- /dev/null
+++ b/docs/cmdline-opts/tr-encoding.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: tr-encoding
+Added: 7.21.6
+Help: Request compressed transfer encoding
+Protocols: HTTP
+Category: http
+Multi: boolean
+See-also:
+ - compressed
+Example:
+ - --tr-encoding $URL
+---
+
+# `--tr-encoding`
+
+Request a compressed Transfer-Encoding response using one of the algorithms
+curl supports, and uncompress the data while receiving it.
diff --git a/docs/cmdline-opts/trace-ascii.d b/docs/cmdline-opts/trace-ascii.d
deleted file mode 100644
index 2aebc2863..000000000
--- a/docs/cmdline-opts/trace-ascii.d
+++ /dev/null
@@ -1,24 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: trace-ascii
-Arg: <file>
-Help: Like --trace, but without hex output
-Mutexed: trace verbose
-Category: verbose
-Example: --trace-ascii log.txt $URL
-Added: 7.9.7
-See-also: verbose trace
-Multi: single
-Scope: global
----
-Enables a full trace dump of all incoming and outgoing data, including
-descriptive information, to the given output file. Use "-" as filename to have
-the output sent to stdout.
-
-This is similar to --trace, but leaves out the hex part and only shows the
-ASCII part of the dump. It makes smaller output that might be easier to read
-for untrained humans.
-
-Note that verbose output of curl activities and network traffic might contain
-sensitive data, including user names, credentials or secret data content. Be
-aware and be careful when sharing trace logs with others.
diff --git a/docs/cmdline-opts/trace-ascii.md b/docs/cmdline-opts/trace-ascii.md
new file mode 100644
index 000000000..209c7bd97
--- /dev/null
+++ b/docs/cmdline-opts/trace-ascii.md
@@ -0,0 +1,31 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: trace-ascii
+Arg: <file>
+Help: Like --trace, but without hex output
+Mutexed: trace verbose
+Category: verbose
+Added: 7.9.7
+Multi: single
+Scope: global
+See-also:
+ - verbose
+ - trace
+Example:
+ - --trace-ascii log.txt $URL
+---
+
+# `--trace-ascii`
+
+Enables a full trace dump of all incoming and outgoing data, including
+descriptive information, to the given output file. Use "-" as filename to have
+the output sent to stdout.
+
+This is similar to --trace, but leaves out the hex part and only shows the
+ASCII part of the dump. It makes smaller output that might be easier to read
+for untrained humans.
+
+Note that verbose output of curl activities and network traffic might contain
+sensitive data, including user names, credentials or secret data content. Be
+aware and be careful when sharing trace logs with others.
diff --git a/docs/cmdline-opts/trace-config.d b/docs/cmdline-opts/trace-config.d
deleted file mode 100644
index a731c9dc9..000000000
--- a/docs/cmdline-opts/trace-config.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: trace-config
-Arg: <string>
-Help: Details to log in trace/verbose output
-Mutexed: trace verbose
-Category: verbose
-Example: --trace-config ids,http/2 $URL
-Added: 8.3.0
-See-also: verbose trace
-Multi: append
-Scope: global
----
-Set configuration for trace output. A comma-separated list of components where
-detailed output can be made available from. Names are case-insensitive.
-Specify 'all' to enable all trace components.
-
-In addition to trace component names, specify "ids" and "time" to
-avoid extra --trace-ids or --trace-time parameters.
-
-See the *curl_global_trace(3)* man page for more details.
diff --git a/docs/cmdline-opts/trace-config.md b/docs/cmdline-opts/trace-config.md
new file mode 100644
index 000000000..0bc9da101
--- /dev/null
+++ b/docs/cmdline-opts/trace-config.md
@@ -0,0 +1,28 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: trace-config
+Arg: <string>
+Help: Details to log in trace/verbose output
+Mutexed: trace verbose
+Category: verbose
+Added: 8.3.0
+Multi: append
+Scope: global
+See-also:
+ - verbose
+ - trace
+Example:
+ - --trace-config ids,http/2 $URL
+---
+
+# `--trace-config`
+
+Set configuration for trace output. A comma-separated list of components where
+detailed output can be made available from. Names are case-insensitive.
+Specify 'all' to enable all trace components.
+
+In addition to trace component names, specify "ids" and "time" to
+avoid extra --trace-ids or --trace-time parameters.
+
+See the *curl_global_trace(3)* man page for more details.
diff --git a/docs/cmdline-opts/trace-ids.d b/docs/cmdline-opts/trace-ids.d
deleted file mode 100644
index 7b8ce6f70..000000000
--- a/docs/cmdline-opts/trace-ids.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: trace-ids
-Help: Add transfer and connection identifiers to trace/verbose output
-Added: 8.2.0
-Category: verbose
-Example: --trace-ids --trace-ascii output $URL
-See-also: trace verbose
-Multi: boolean
-Scope: global
----
-Prepends the transfer and connection identifiers to each trace or verbose line that curl displays.
diff --git a/docs/cmdline-opts/trace-ids.md b/docs/cmdline-opts/trace-ids.md
new file mode 100644
index 000000000..43774d372
--- /dev/null
+++ b/docs/cmdline-opts/trace-ids.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: trace-ids
+Help: Add transfer and connection identifiers to trace/verbose output
+Added: 8.2.0
+Category: verbose
+Multi: boolean
+Scope: global
+See-also:
+ - trace
+ - verbose
+Example:
+ - --trace-ids --trace-ascii output $URL
+---
+
+# `--trace-ids`
+
+Prepends the transfer and connection identifiers to each trace or verbose line that curl displays.
diff --git a/docs/cmdline-opts/trace-time.d b/docs/cmdline-opts/trace-time.d
deleted file mode 100644
index f40ee02d7..000000000
--- a/docs/cmdline-opts/trace-time.d
+++ /dev/null
@@ -1,12 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: trace-time
-Help: Add time stamps to trace/verbose output
-Added: 7.14.0
-Category: verbose
-Example: --trace-time --trace-ascii output $URL
-See-also: trace verbose
-Multi: boolean
-Scope: global
----
-Prepends a time stamp to each trace or verbose line that curl displays.
diff --git a/docs/cmdline-opts/trace-time.md b/docs/cmdline-opts/trace-time.md
new file mode 100644
index 000000000..79206ba9e
--- /dev/null
+++ b/docs/cmdline-opts/trace-time.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: trace-time
+Help: Add time stamps to trace/verbose output
+Added: 7.14.0
+Category: verbose
+Multi: boolean
+Scope: global
+See-also:
+ - trace
+ - verbose
+Example:
+ - --trace-time --trace-ascii output $URL
+---
+
+# `--trace-time`
+
+Prepends a time stamp to each trace or verbose line that curl displays.
diff --git a/docs/cmdline-opts/trace.d b/docs/cmdline-opts/trace.d
deleted file mode 100644
index 35b2248e9..000000000
--- a/docs/cmdline-opts/trace.d
+++ /dev/null
@@ -1,21 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: trace
-Arg: <file>
-Help: Write a debug trace to FILE
-Mutexed: verbose trace-ascii
-Category: verbose
-Example: --trace log.txt $URL
-Added: 7.9.7
-See-also: trace-ascii trace-config trace-ids trace-time
-Multi: single
-Scope: global
----
-Enables a full trace dump of all incoming and outgoing data, including
-descriptive information, to the given output file. Use "-" as filename to have
-the output sent to stdout. Use "%" as filename to have the output sent to
-stderr.
-
-Note that verbose output of curl activities and network traffic might contain
-sensitive data, including user names, credentials or secret data content. Be
-aware and be careful when sharing trace logs with others.
diff --git a/docs/cmdline-opts/trace.md b/docs/cmdline-opts/trace.md
new file mode 100644
index 000000000..90bb28f4f
--- /dev/null
+++ b/docs/cmdline-opts/trace.md
@@ -0,0 +1,30 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: trace
+Arg: <file>
+Help: Write a debug trace to FILE
+Mutexed: verbose trace-ascii
+Category: verbose
+Added: 7.9.7
+Multi: single
+Scope: global
+See-also:
+ - trace-ascii
+ - trace-config
+ - trace-ids
+ - trace-time
+Example:
+ - --trace log.txt $URL
+---
+
+# `--trace`
+
+Enables a full trace dump of all incoming and outgoing data, including
+descriptive information, to the given output file. Use "-" as filename to have
+the output sent to stdout. Use "%" as filename to have the output sent to
+stderr.
+
+Note that verbose output of curl activities and network traffic might contain
+sensitive data, including user names, credentials or secret data content. Be
+aware and be careful when sharing trace logs with others.
diff --git a/docs/cmdline-opts/unix-socket.d b/docs/cmdline-opts/unix-socket.d
deleted file mode 100644
index 5ea56ebf1..000000000
--- a/docs/cmdline-opts/unix-socket.d
+++ /dev/null
@@ -1,13 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: unix-socket
-Arg: <path>
-Help: Connect through this Unix domain socket
-Added: 7.40.0
-Protocols: HTTP
-Category: connection
-See-also: abstract-unix-socket
-Example: --unix-socket socket-path $URL
-Multi: single
----
-Connect through this Unix domain socket, instead of using the network.
diff --git a/docs/cmdline-opts/unix-socket.md b/docs/cmdline-opts/unix-socket.md
new file mode 100644
index 000000000..582f32dc5
--- /dev/null
+++ b/docs/cmdline-opts/unix-socket.md
@@ -0,0 +1,19 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: unix-socket
+Arg: <path>
+Help: Connect through this Unix domain socket
+Added: 7.40.0
+Protocols: HTTP
+Category: connection
+Multi: single
+See-also:
+ - abstract-unix-socket
+Example:
+ - --unix-socket socket-path $URL
+---
+
+# `--unix-socket`
+
+Connect through this Unix domain socket, instead of using the network.
diff --git a/docs/cmdline-opts/upload-file.d b/docs/cmdline-opts/upload-file.d
deleted file mode 100644
index 8e0091d18..000000000
--- a/docs/cmdline-opts/upload-file.d
+++ /dev/null
@@ -1,43 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: upload-file
-Short: T
-Arg: <file>
-Help: Transfer local FILE to destination
-Category: important upload
-Example: -T file $URL
-Example: -T "img[1-1000].png" ftp://ftp.example.com/
-Example: --upload-file "{file1,file2}" $URL
-Added: 4.0
-See-also: get head request data
-Multi: append
----
-This transfers the specified local file to the remote URL.
-
-If there is no file part in the specified URL, curl appends the local file
-name to the end of the URL before the operation starts. You must use a
-trailing slash (/) on the last directory to prove to curl that there is no
-file name or curl thinks that your last directory name is the remote file name
-to use.
-
-When putting the local file name at the end of the URL, curl ignores what is
-on the left side of any slash (/) or backslash (\\) used in the file name and
-only appends what is on the right side of the rightmost such character.
-
-Use the file name "-" (a single dash) to use stdin instead of a given file.
-Alternately, the file name "." (a single period) may be specified instead of
-"-" to use stdin in non-blocking mode to allow reading server output while
-stdin is being uploaded.
-
-If this option is used with a HTTP(S) URL, the PUT method is used.
-
-You can specify one --upload-file for each URL on the command line. Each
---upload-file + URL pair specifies what to upload and to where. curl also
-supports "globbing" of the --upload-file argument, meaning that you can upload
-multiple files to a single URL by using the same URL globbing style supported
-in the URL.
-
-When uploading to an SMTP server: the uploaded data is assumed to be RFC 5322
-formatted. It has to feature the necessary set of headers and mail body
-formatted correctly by the user as curl does not transcode nor encode it
-further in any way.
diff --git a/docs/cmdline-opts/upload-file.md b/docs/cmdline-opts/upload-file.md
new file mode 100644
index 000000000..05ba2c97d
--- /dev/null
+++ b/docs/cmdline-opts/upload-file.md
@@ -0,0 +1,52 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: upload-file
+Short: T
+Arg: <file>
+Help: Transfer local FILE to destination
+Category: important upload
+Added: 4.0
+Multi: append
+See-also:
+ - get
+ - head
+ - request
+ - data
+Example:
+ - -T file $URL
+ - -T "img[1-1000].png" ftp://ftp.example.com/
+ - --upload-file "{file1,file2}" $URL
+---
+
+# `--upload-file`
+
+This transfers the specified local file to the remote URL.
+
+If there is no file part in the specified URL, curl appends the local file
+name to the end of the URL before the operation starts. You must use a
+trailing slash (/) on the last directory to prove to curl that there is no
+file name or curl thinks that your last directory name is the remote file name
+to use.
+
+When putting the local file name at the end of the URL, curl ignores what is
+on the left side of any slash (/) or backslash (\) used in the file name and
+only appends what is on the right side of the rightmost such character.
+
+Use the file name "-" (a single dash) to use stdin instead of a given file.
+Alternately, the file name "." (a single period) may be specified instead of
+"-" to use stdin in non-blocking mode to allow reading server output while
+stdin is being uploaded.
+
+If this option is used with a HTTP(S) URL, the PUT method is used.
+
+You can specify one --upload-file for each URL on the command line. Each
+--upload-file + URL pair specifies what to upload and to where. curl also
+supports "globbing" of the --upload-file argument, meaning that you can upload
+multiple files to a single URL by using the same URL globbing style supported
+in the URL.
+
+When uploading to an SMTP server: the uploaded data is assumed to be RFC 5322
+formatted. It has to feature the necessary set of headers and mail body
+formatted correctly by the user as curl does not transcode nor encode it
+further in any way.
diff --git a/docs/cmdline-opts/url-query.d b/docs/cmdline-opts/url-query.d
deleted file mode 100644
index 29b31e338..000000000
--- a/docs/cmdline-opts/url-query.d
+++ /dev/null
@@ -1,25 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: url-query
-Arg: <data>
-Help: Add a URL query part
-Protocols: all
-See-also: data-urlencode get
-Added: 7.87.0
-Category: http post upload
-Example: --url-query name=val $URL
-Example: --url-query =encodethis http://example.net/foo
-Example: --url-query name@file $URL
-Example: --url-query @fileonly $URL
-Example: --url-query "+name=%20foo" $URL
-Multi: append
----
-This option adds a piece of data, usually a name + value pair, to the end of
-the URL query part. The syntax is identical to that used for --data-urlencode
-with one extension:
-
-If the argument starts with a '+' (plus), the rest of the string is provided
-as-is unencoded.
-
-The query part of a URL is the one following the question mark on the right
-end.
diff --git a/docs/cmdline-opts/url-query.md b/docs/cmdline-opts/url-query.md
new file mode 100644
index 000000000..15e585773
--- /dev/null
+++ b/docs/cmdline-opts/url-query.md
@@ -0,0 +1,32 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: url-query
+Arg: <data>
+Help: Add a URL query part
+Protocols: all
+Added: 7.87.0
+Category: http post upload
+Multi: append
+See-also:
+ - data-urlencode
+ - get
+Example:
+ - --url-query name=val $URL
+ - --url-query =encodethis http://example.net/foo
+ - --url-query name@file $URL
+ - --url-query @fileonly $URL
+ - --url-query "+name=%20foo" $URL
+---
+
+# `--url-query`
+
+This option adds a piece of data, usually a name + value pair, to the end of
+the URL query part. The syntax is identical to that used for --data-urlencode
+with one extension:
+
+If the argument starts with a '+' (plus), the rest of the string is provided
+as-is unencoded.
+
+The query part of a URL is the one following the question mark on the right
+end.
diff --git a/docs/cmdline-opts/url.d b/docs/cmdline-opts/url.d
deleted file mode 100644
index fa0421e08..000000000
--- a/docs/cmdline-opts/url.d
+++ /dev/null
@@ -1,26 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: url
-Arg: <url>
-Help: URL to work with
-Category: curl
-Example: --url $URL
-Added: 7.5
-See-also: next config
-Multi: append
----
-Specify a URL to fetch. This option is mostly handy when you want to specify
-URL(s) in a config file.
-
-If the given URL is missing a scheme name (such as "http://" or "ftp://" etc)
-then curl makes a guess based on the host. If the outermost subdomain name
-matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that protocol is used,
-otherwise HTTP is used. Guessing can be avoided by providing a full URL
-including the scheme, or disabled by setting a default protocol (added in
-7.45.0), see --proto-default for details.
-
-To control where this URL is written, use the --output or the --remote-name
-options.
-
-**WARNING**: On Windows, particular file:// accesses can be converted to
-network accesses by the operating system. Beware!
diff --git a/docs/cmdline-opts/url.md b/docs/cmdline-opts/url.md
new file mode 100644
index 000000000..0adfa743b
--- /dev/null
+++ b/docs/cmdline-opts/url.md
@@ -0,0 +1,33 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: url
+Arg: <url>
+Help: URL to work with
+Category: curl
+Added: 7.5
+Multi: append
+See-also:
+ - next
+ - config
+Example:
+ - --url $URL
+---
+
+# `--url`
+
+Specify a URL to fetch. This option is mostly handy when you want to specify
+URL(s) in a config file.
+
+If the given URL is missing a scheme name (such as "http://" or "ftp://" etc)
+then curl makes a guess based on the host. If the outermost subdomain name
+matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that protocol is used,
+otherwise HTTP is used. Guessing can be avoided by providing a full URL
+including the scheme, or disabled by setting a default protocol (added in
+7.45.0), see --proto-default for details.
+
+To control where this URL is written, use the --output or the --remote-name
+options.
+
+**WARNING**: On Windows, particular file:// accesses can be converted to
+network accesses by the operating system. Beware!
diff --git a/docs/cmdline-opts/use-ascii.d b/docs/cmdline-opts/use-ascii.d
deleted file mode 100644
index 772992c17..000000000
--- a/docs/cmdline-opts/use-ascii.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: B
-Long: use-ascii
-Help: Use ASCII/text transfer
-Protocols: FTP LDAP
-Category: misc
-Example: -B ftp://example.com/README
-Added: 5.0
-See-also: crlf data-ascii
-Multi: boolean
----
-Enable ASCII transfer. For FTP, this can also be enforced by using a URL that
-ends with ";type=A". This option causes data sent to stdout to be in text mode
-for win32 systems.
diff --git a/docs/cmdline-opts/use-ascii.md b/docs/cmdline-opts/use-ascii.md
new file mode 100644
index 000000000..4e2574a78
--- /dev/null
+++ b/docs/cmdline-opts/use-ascii.md
@@ -0,0 +1,22 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: B
+Long: use-ascii
+Help: Use ASCII/text transfer
+Protocols: FTP LDAP
+Category: misc
+Added: 5.0
+Multi: boolean
+See-also:
+ - crlf
+ - data-ascii
+Example:
+ - -B ftp://example.com/README
+---
+
+# `--use-ascii`
+
+Enable ASCII transfer. For FTP, this can also be enforced by using a URL that
+ends with ";type=A". This option causes data sent to stdout to be in text mode
+for win32 systems.
diff --git a/docs/cmdline-opts/user-agent.d b/docs/cmdline-opts/user-agent.d
deleted file mode 100644
index 1681b7e8b..000000000
--- a/docs/cmdline-opts/user-agent.d
+++ /dev/null
@@ -1,20 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: A
-Long: user-agent
-Arg: <name>
-Help: Send User-Agent <name> to server
-Protocols: HTTP
-Category: important http
-Example: -A "Agent 007" $URL
-Added: 4.5.1
-See-also: header proxy-header
-Multi: single
----
-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 removes the header
-completely from the request. If you prefer a blank header, you can set it to a
-single space (" ").
diff --git a/docs/cmdline-opts/user-agent.md b/docs/cmdline-opts/user-agent.md
new file mode 100644
index 000000000..29b475857
--- /dev/null
+++ b/docs/cmdline-opts/user-agent.md
@@ -0,0 +1,27 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: A
+Long: user-agent
+Arg: <name>
+Help: Send User-Agent <name> to server
+Protocols: HTTP
+Category: important http
+Added: 4.5.1
+Multi: single
+See-also:
+ - header
+ - proxy-header
+Example:
+ - -A "Agent 007" $URL
+---
+
+# `--user-agent`
+
+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 removes the header
+completely from the request. If you prefer a blank header, you can set it to a
+single space (" ").
diff --git a/docs/cmdline-opts/user.d b/docs/cmdline-opts/user.d
deleted file mode 100644
index f776ab7ae..000000000
--- a/docs/cmdline-opts/user.d
+++ /dev/null
@@ -1,44 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: user
-Short: u
-Arg: <user:password>
-Help: Server user and password
-Category: important auth
-Example: -u user:secret $URL
-Added: 4.0
-See-also: netrc config
-Multi: single
----
-Specify the user name and password to use for server authentication. Overrides
---netrc and --netrc-optional.
-
-If you simply specify the user name, curl prompts for a password.
-
-The user name and passwords are split up on the first colon, which makes it
-impossible to use a colon in the user name with this option. The password can,
-still.
-
-On systems where it works, curl hides the given option argument from process
-listings. This is not enough to protect credentials from possibly getting seen
-by other users on the same system as they still are visible for a brief moment
-before cleared. Such sensitive data should be retrieved from a file instead or
-similar and never used in clear text in a command line.
-
-When using Kerberos V5 with a Windows based server you should include the
-Windows domain name in the user name, in order for the server to successfully
-obtain a Kerberos Ticket. If you do not, then the initial authentication
-handshake may fail.
-
-When using NTLM, the user name can be specified simply as the user name,
-without the domain, if there is a single domain and forest in your setup
-for example.
-
-To specify the domain name use either Down-Level Logon Name or UPN (User
-Principal Name) formats. For example, EXAMPLE\\user and user@example.com
-respectively.
-
-If you use a Windows SSPI-enabled curl binary and perform Kerberos V5,
-Negotiate, NTLM or Digest authentication then you can tell curl to select
-the user name and password from your environment by specifying a single colon
-with this option: "-u :".
diff --git a/docs/cmdline-opts/user.md b/docs/cmdline-opts/user.md
new file mode 100644
index 000000000..ee4610c0a
--- /dev/null
+++ b/docs/cmdline-opts/user.md
@@ -0,0 +1,51 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: user
+Short: u
+Arg: <user:password>
+Help: Server user and password
+Category: important auth
+Added: 4.0
+Multi: single
+See-also:
+ - netrc
+ - config
+Example:
+ - -u user:secret $URL
+---
+
+# `--user`
+
+Specify the user name and password to use for server authentication. Overrides
+--netrc and --netrc-optional.
+
+If you simply specify the user name, curl prompts for a password.
+
+The user name and passwords are split up on the first colon, which makes it
+impossible to use a colon in the user name with this option. The password can,
+still.
+
+On systems where it works, curl hides the given option argument from process
+listings. This is not enough to protect credentials from possibly getting seen
+by other users on the same system as they still are visible for a moment
+before cleared. Such sensitive data should be retrieved from a file instead or
+similar and never used in clear text in a command line.
+
+When using Kerberos V5 with a Windows based server you should include the
+Windows domain name in the user name, in order for the server to successfully
+obtain a Kerberos Ticket. If you do not, then the initial authentication
+handshake may fail.
+
+When using NTLM, the user name can be specified simply as the user name,
+without the domain, if there is a single domain and forest in your setup
+for example.
+
+To specify the domain name use either Down-Level Logon Name or UPN (User
+Principal Name) formats. For example, EXAMPLE\user and user@example.com
+respectively.
+
+If you use a Windows SSPI-enabled curl binary and perform Kerberos V5,
+Negotiate, NTLM or Digest authentication then you can tell curl to select
+the user name and password from your environment by specifying a single colon
+with this option: "-u :".
diff --git a/docs/cmdline-opts/variable.d b/docs/cmdline-opts/variable.d
deleted file mode 100644
index d7d773eda..000000000
--- a/docs/cmdline-opts/variable.d
+++ /dev/null
@@ -1,55 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: variable
-Arg: <[%]name=text/@file>
-Help: Set variable
-Category: curl
-Example: --variable name=smith $URL
-Added: 8.3.0
-See-also: config
-Multi: append
----
-Set a variable with "name=content" or "name@file" (where "file" can be stdin
-if set to a single dash (-)). The name is a case sensitive identifier that
-must consist of no other letters than a-z, A-Z, 0-9 or underscore. The
-specified content is then associated with this identifier.
-
-Setting the same variable name again overwrites the old contents with the new.
-
-The contents of a variable can be referenced in a later command line option
-when that option name is prefixed with "--expand-", and the name is used as
-"{{name}}" (without the quotes).
-
---variable can import environment variables into the name space. Opt to either
-require the environment variable to be set or provide a default value for the
-variable in case it is not already set.
-
---variable %name imports the variable called 'name' but exits with an error if
-that environment variable is not already set. To provide a default value if
-the environment variable is not set, use --variable %name=content or
---variable %name@content. Note that on some systems - but not all -
-environment variables are case insensitive.
-
-When expanding variables, curl supports a set of functions that can make the
-variable contents more convenient to use. You apply a function to a variable
-expansion by adding a colon and then list the desired functions in a
-comma-separated list that is evaluated in a left-to-right order. Variable
-content holding null bytes that are not encoded when expanded, causes an
-error.
-
-Available functions:
-.RS
-.TP 15
-**trim**
-removes all leading and trailing white space.
-.TP
-**json**
-outputs the content using JSON string quoting rules.
-.TP
-**url**
-shows the content URL (percent) encoded.
-.TP
-**b64**
-expands the variable base64 encoded
-.RE
-.IP
diff --git a/docs/cmdline-opts/variable.md b/docs/cmdline-opts/variable.md
new file mode 100644
index 000000000..14b895c7f
--- /dev/null
+++ b/docs/cmdline-opts/variable.md
@@ -0,0 +1,58 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: variable
+Arg: <[%]name=text/@file>
+Help: Set variable
+Category: curl
+Added: 8.3.0
+Multi: append
+See-also:
+ - config
+Example:
+ - --variable name=smith $URL
+---
+
+# `--variable`
+
+Set a variable with "name=content" or "name@file" (where "file" can be stdin
+if set to a single dash (-)). The name is a case sensitive identifier that
+must consist of no other letters than a-z, A-Z, 0-9 or underscore. The
+specified content is then associated with this identifier.
+
+Setting the same variable name again overwrites the old contents with the new.
+
+The contents of a variable can be referenced in a later command line option
+when that option name is prefixed with "--expand-", and the name is used as
+"{{name}}" (without the quotes).
+
+--variable can import environment variables into the name space. Opt to either
+require the environment variable to be set or provide a default value for the
+variable in case it is not already set.
+
+--variable %name imports the variable called 'name' but exits with an error if
+that environment variable is not already set. To provide a default value if
+the environment variable is not set, use --variable %name=content or
+--variable %name@content. Note that on some systems - but not all -
+environment variables are case insensitive.
+
+When expanding variables, curl supports a set of functions that can make the
+variable contents more convenient to use. You apply a function to a variable
+expansion by adding a colon and then list the desired functions in a
+comma-separated list that is evaluated in a left-to-right order. Variable
+content holding null bytes that are not encoded when expanded, causes an
+error.
+
+Available functions:
+
+## trim
+removes all leading and trailing white space.
+
+## json
+outputs the content using JSON string quoting rules.
+
+## url
+shows the content URL (percent) encoded.
+
+## b64
+expands the variable base64 encoded
diff --git a/docs/cmdline-opts/verbose.d b/docs/cmdline-opts/verbose.d
deleted file mode 100644
index c5661f86a..000000000
--- a/docs/cmdline-opts/verbose.d
+++ /dev/null
@@ -1,28 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Short: v
-Long: verbose
-Mutexed: trace trace-ascii
-Help: Make the operation more talkative
-See-also: include silent trace trace-ascii
-Category: important verbose
-Example: --verbose $URL
-Added: 4.0
-Multi: boolean
-Scope: global
----
-Makes curl verbose during the operation. Useful for debugging and seeing
-what's going on "under the hood". A line starting with '>' means "header data"
-sent by curl, '<' means "header data" received by curl that is hidden in
-normal cases, and a line starting with '*' means additional info provided by
-curl.
-
-If you only want HTTP headers in the output, --include or --dump-header might
-be more suitable options.
-
-If you think this option still does not give you enough details, consider using
---trace or --trace-ascii instead.
-
-Note that verbose output of curl activities and network traffic might contain
-sensitive data, including user names, credentials or secret data content. Be
-aware and be careful when sharing trace logs with others.
diff --git a/docs/cmdline-opts/verbose.md b/docs/cmdline-opts/verbose.md
new file mode 100644
index 000000000..21ecf6a9c
--- /dev/null
+++ b/docs/cmdline-opts/verbose.md
@@ -0,0 +1,37 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Short: v
+Long: verbose
+Mutexed: trace trace-ascii
+Help: Make the operation more talkative
+Category: important verbose
+Added: 4.0
+Multi: boolean
+Scope: global
+See-also:
+ - include
+ - silent
+ - trace
+ - trace-ascii
+Example:
+ - --verbose $URL
+---
+
+# `--verbose`
+
+Makes curl verbose during the operation. Useful for debugging and seeing
+what's going on "under the hood". A line starting with '>' means "header data"
+sent by curl, '<' means "header data" received by curl that is hidden in
+normal cases, and a line starting with '*' means additional info provided by
+curl.
+
+If you only want HTTP headers in the output, --include or --dump-header might
+be more suitable options.
+
+If you think this option still does not give you enough details, consider using
+--trace or --trace-ascii instead.
+
+Note that verbose output of curl activities and network traffic might contain
+sensitive data, including user names, credentials or secret data content. Be
+aware and be careful when sharing trace logs with others.
diff --git a/docs/cmdline-opts/version.d b/docs/cmdline-opts/version.d
deleted file mode 100644
index 8d231ce0c..000000000
--- a/docs/cmdline-opts/version.d
+++ /dev/null
@@ -1,88 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: version
-Short: V
-Help: Show version number and quit
-Category: important curl
-Example: --version
-Added: 4.0
-See-also: help manual
-Multi: custom
----
-Displays information about curl and the libcurl version it uses.
-
-The first line includes the full version of curl, libcurl and other 3rd party
-libraries linked with the executable.
-
-The second line (starts with "Release-Date:") shows the release date.
-
-The third line (starts with "Protocols:") shows all protocols that libcurl
-reports to support.
-
-The fourth 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 "gsasl"
-The built-in SASL authentication includes extensions to support SCRAM because
-libcurl was built with libgsasl.
-.IP "GSS-API"
-GSS-API is supported.
-.IP "HSTS"
-HSTS support is present.
-.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 "Kerberos"
-Kerberos V5 authentication is supported.
-.IP "Largefile"
-This curl supports transfers of large files, files larger than 2GB.
-.IP "libz"
-Automatic decompression (via gzip, deflate) of compressed files over HTTP is
-supported.
-.IP "MultiSSL"
-This curl supports multiple TLS backends.
-.IP "NTLM"
-NTLM authentication is supported.
-.IP "NTLM_WB"
-NTLM delegation to winbind helper 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 "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 "TrackMemory"
-Debug memory tracking is supported.
-.IP "Unicode"
-Unicode support on Windows.
-.IP "UnixSockets"
-Unix sockets support is provided.
-.IP "zstd"
-Automatic decompression (via zstd) of compressed files over HTTP is supported.
-.RE
-.IP
diff --git a/docs/cmdline-opts/version.md b/docs/cmdline-opts/version.md
new file mode 100644
index 000000000..0fe8d7419
--- /dev/null
+++ b/docs/cmdline-opts/version.md
@@ -0,0 +1,120 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: version
+Short: V
+Help: Show version number and quit
+Category: important curl
+Added: 4.0
+Multi: custom
+See-also:
+ - help
+ - manual
+Example:
+ - --version
+---
+
+# `--version`
+
+Displays information about curl and the libcurl version it uses.
+
+The first line includes the full version of curl, libcurl and other 3rd party
+libraries linked with the executable.
+
+The second line (starts with `Release-Date:`) shows the release date.
+
+The third line (starts with `Protocols:`) shows all protocols that libcurl
+reports to support.
+
+The fourth line (starts with `Features:`) shows specific features libcurl
+reports to offer. Available features include:
+
+## `alt-svc`
+Support for the Alt-Svc: header is provided.
+
+## `AsynchDNS`
+This curl uses asynchronous name resolves. Asynchronous name resolves can be
+done using either the c-ares or the threaded resolver backends.
+
+## `brotli`
+Support for automatic brotli compression over HTTP(S).
+
+## `CharConv`
+curl was built with support for character set conversions (like EBCDIC)
+
+## `Debug`
+This curl uses a libcurl built with Debug. This enables more error-tracking
+and memory debugging etc. For curl-developers only!
+
+## `gsasl`
+The built-in SASL authentication includes extensions to support SCRAM because
+libcurl was built with libgsasl.
+
+## `GSS-API`
+GSS-API is supported.
+
+## `HSTS`
+HSTS support is present.
+
+## `HTTP2`
+HTTP/2 support has been built-in.
+
+## `HTTP3`
+HTTP/3 support has been built-in.
+
+## `HTTPS-proxy`
+This curl is built to support HTTPS proxy.
+
+## `IDN`
+This curl supports IDN - international domain names.
+
+## `IPv6`
+You can use IPv6 with this.
+
+## `Kerberos`
+Kerberos V5 authentication is supported.
+
+## `Largefile`
+This curl supports transfers of large files, files larger than 2GB.
+
+## `libz`
+Automatic decompression (via gzip, deflate) of compressed files over HTTP is
+supported.
+
+## `MultiSSL`
+This curl supports multiple TLS backends.
+
+## `NTLM`
+NTLM authentication is supported.
+
+## `NTLM_WB`
+NTLM delegation to winbind helper is supported.
+
+## `PSL`
+PSL is short for Public Suffix List and means that this curl has been built
+with knowledge about "public suffixes".
+
+## `SPNEGO`
+SPNEGO authentication is supported.
+
+## `SSL`
+SSL versions of various protocols are supported, such as HTTPS, FTPS, POP3S
+and so on.
+
+## `SSPI`
+SSPI is supported.
+
+## `TLS-SRP`
+SRP (Secure Remote Password) authentication is supported for TLS.
+
+## `TrackMemory`
+Debug memory tracking is supported.
+
+## `Unicode`
+Unicode support on Windows.
+
+## `UnixSockets`
+Unix sockets support is provided.
+
+## `zstd`
+Automatic decompression (via zstd) of compressed files over HTTP is supported.
diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d
deleted file mode 100644
index b2ac2ec06..000000000
--- a/docs/cmdline-opts/write-out.d
+++ /dev/null
@@ -1,292 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: write-out
-Short: w
-Arg: <format>
-Help: Use output FORMAT after completion
-Category: verbose
-Example: -w '%{response_code}\\n' $URL
-Added: 6.5
-See-also: verbose head
-Multi: single
----
-Make curl display information on stdout after a completed transfer. The format
-is a string that may contain plain text mixed with any number of
-variables. The format can be specified as a literal "string", or you can have
-curl read the format from a file with "@filename" and to tell curl to read the
-format from stdin you write "@-".
-
-The variables present in the output format are substituted by the value or
-text that curl thinks fit, as described below. All variables are specified as
-%{variable_name} and to output a normal % you just write them as %%. You can
-output a newline by using \\n, a carriage return with \\r and a tab space with
-\\t.
-
-The output is by default written to standard output, but can be changed with
-%{stderr} and %output{}.
-
-Output HTTP headers from the most recent request by using *%header{name}*
-where *name* is the case insensitive name of the header (without the trailing
-colon). The header contents are exactly as sent over the network, with leading
-and trailing whitespace trimmed (added in 7.84.0).
-
-Select a specific target destination file to write the output to, by using
-*%output{name}* (added in curl 8.3.0) where *name* is the full file name. The
-output following that instruction is then written to that file. More than one
-*%output{}* instruction can be specified in the same write-out argument. If
-the file name cannot be created, curl leaves the output destination to the one
-used prior to the *%output{}* instruction. Use *%output{>>name}* to append
-data to an existing file.
-
-**NOTE:**
-In Windows the %-symbol is a special symbol used to expand environment
-variables. In batch files all occurrences of % must be doubled when using this
-option to properly escape. If this option is used at the command prompt then
-the % cannot be escaped and unintended expansion is possible.
-
-The variables available are:
-.RS
-.TP 15
-**certs**
-Output the certificate chain with details. Supported only by the OpenSSL,
-GnuTLS, Schannel and Secure Transport backends. (Added in 7.88.0)
-.TP
-**content_type**
-The Content-Type of the requested document, if there was any.
-.TP
-**errormsg**
-The error message. (Added in 7.75.0)
-.TP
-**exitcode**
-The numerical exit code of the transfer. (Added in 7.75.0)
-.TP
-**filename_effective**
-The ultimate filename that curl writes out to. This is only meaningful if curl
-is told to write to a file with the --remote-name or --output
-option. It's most useful in combination with the --remote-header-name
-option. (Added in 7.26.0)
-.TP
-**ftp_entry_path**
-The initial path curl ended up in when logging on to the remote FTP
-server. (Added in 7.15.4)
-.TP
-**header_json**
-A JSON object with all HTTP response headers from the recent transfer. Values
-are provided as arrays, since in the case of multiple headers there can be
-multiple values. (Added in 7.83.0)
-
-The header names provided in lowercase, listed in order of appearance over the
-wire. Except for duplicated headers. They are grouped on the first occurrence
-of that header, each value is presented in the JSON array.
-.TP
-**http_code**
-The numerical response code that was found in the last retrieved HTTP(S) or
-FTP(s) transfer.
-.TP
-**http_connect**
-The numerical code that was found in the last response (from a proxy) to a
-curl CONNECT request. (Added in 7.12.4)
-.TP
-**http_version**
-The http version that was effectively used. (Added in 7.50.0)
-.TP
-**json**
-A JSON object with all available keys.
-.TP
-**local_ip**
-The IP address of the local end of the most recently done connection - can be
-either IPv4 or IPv6. (Added in 7.29.0)
-.TP
-**local_port**
-The local port number of the most recently done connection. (Added in 7.29.0)
-.TP
-**method**
-The http method used in the most recent HTTP request. (Added in 7.72.0)
-.TP
-**num_certs**
-Number of server certificates received in the TLS handshake. Supported only by
-the OpenSSL, GnuTLS, Schannel and Secure Transport backends.
-(Added in 7.88.0)
-.TP
-**num_connects**
-Number of new connects made in the recent transfer. (Added in 7.12.3)
-.TP
-**num_headers**
-The number of response headers in the most recent request (restarted at each
-redirect). Note that the status line IS NOT a header. (Added in 7.73.0)
-.TP
-**num_redirects**
-Number of redirects that were followed in the request. (Added in 7.12.3)
-.TP
-**onerror**
-The rest of the output is only shown if the transfer returned a non-zero error.
-(Added in 7.75.0)
-.TP
-**proxy_ssl_verify_result**
-The result of the HTTPS proxy's SSL peer certificate verification that was
-requested. 0 means the verification was successful. (Added in 7.52.0)
-.TP
-**redirect_url**
-When an HTTP request was made without --location to follow redirects (or when
---max-redirs is met), this variable shows the actual URL a redirect
-*would* have gone to. (Added in 7.18.2)
-.TP
-**referer**
-The Referer: header, if there was any. (Added in 7.76.0)
-.TP
-**remote_ip**
-The remote IP address of the most recently done connection - can be either
-IPv4 or IPv6. (Added in 7.29.0)
-.TP
-**remote_port**
-The remote port number of the most recently done connection. (Added in 7.29.0)
-.TP
-**response_code**
-The numerical response code that was found in the last transfer (formerly
-known as "http_code"). (Added in 7.18.2)
-.TP
-**scheme**
-The URL scheme (sometimes called protocol) that was effectively used. (Added in 7.52.0)
-.TP
-**size_download**
-The total amount of bytes that were downloaded. This is the size of the
-body/data that was transferred, excluding headers.
-.TP
-**size_header**
-The total amount of bytes of the downloaded headers.
-.TP
-**size_request**
-The total amount of bytes that were sent in the HTTP request.
-.TP
-**size_upload**
-The total amount of bytes that were uploaded. This is the size of the
-body/data that was transferred, excluding headers.
-.TP
-**speed_download**
-The average download speed that curl measured for the complete download. Bytes
-per second.
-.TP
-**speed_upload**
-The average upload speed that curl measured for the complete upload. Bytes per
-second.
-.TP
-**ssl_verify_result**
-The result of the SSL peer certificate verification that was requested. 0
-means the verification was successful. (Added in 7.19.0)
-.TP
-**stderr**
-From this point on, the --write-out output is written to standard
-error. (Added in 7.63.0)
-.TP
-**stdout**
-From this point on, the --write-out output is written to standard output.
-This is the default, but can be used to switch back after switching to stderr.
-(Added in 7.63.0)
-.TP
-**time_appconnect**
-The time, in seconds, it took from the start until the SSL/SSH/etc
-connect/handshake to the remote host was completed. (Added in 7.19.0)
-.TP
-**time_connect**
-The time, in seconds, it took from the start until the TCP connect to the
-remote host (or proxy) was completed.
-.TP
-**time_namelookup**
-The time, in seconds, it took from the start until the name resolving was
-completed.
-.TP
-**time_pretransfer**
-The time, in seconds, it took from the start until the file transfer was just
-about to begin. This includes all pre-transfer commands and negotiations that
-are specific to the particular protocol(s) involved.
-.TP
-**time_redirect**
-The time, in seconds, it took for all redirection steps including name lookup,
-connect, pretransfer and transfer before the final transaction was
-started. time_redirect shows the complete execution time for multiple
-redirections. (Added in 7.12.3)
-.TP
-**time_starttransfer**
-The time, in seconds, it took from the start until the first byte is received.
-This includes time_pretransfer and also the time the server needed to calculate
-the result.
-.TP
-**time_total**
-The total time, in seconds, that the full operation lasted.
-.TP
-**url**
-The URL that was fetched. (Added in 7.75.0)
-.TP
-**url.scheme**
-The scheme part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.user**
-The user part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.password**
-The password part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.options**
-The options part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.host**
-The host part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.port**
-The port number of the URL that was fetched. If no port number was specified,
-but the URL scheme is known, that scheme's default port number is
-shown. (Added in 8.1.0)
-.TP
-**url.path**
-The path part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.query**
-The query part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.fragment**
-The fragment part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**url.zoneid**
-The zone id part of the URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.scheme**
-The scheme part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.user**
-The user part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.password**
-The password part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.options**
-The options part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.host**
-The host part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.port**
-The port number of the effective (last) URL that was fetched. If no port
-number was specified, but the URL scheme is known, that scheme's default port
-number is shown. (Added in 8.1.0)
-.TP
-**urle.path**
-The path part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.query**
-The query part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.fragment**
-The fragment part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urle.zoneid**
-The zone id part of the effective (last) URL that was fetched. (Added in 8.1.0)
-.TP
-**urlnum**
-The URL index number of this transfer, 0-indexed. Unglobbed URLs share the
-same index number as the origin globbed URL. (Added in 7.75.0)
-.TP
-**url_effective**
-The URL that was fetched last. This is most meaningful if you have told curl
-to follow location: headers.
-.RE
-.IP
diff --git a/docs/cmdline-opts/write-out.md b/docs/cmdline-opts/write-out.md
new file mode 100644
index 000000000..53d40e84a
--- /dev/null
+++ b/docs/cmdline-opts/write-out.md
@@ -0,0 +1,296 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: write-out
+Short: w
+Arg: <format>
+Help: Use output FORMAT after completion
+Category: verbose
+Added: 6.5
+Multi: single
+See-also:
+ - verbose
+ - head
+Example:
+ - -w '%{response_code}\n' $URL
+---
+
+# `--write-out`
+
+Make curl display information on stdout after a completed transfer. The format
+is a string that may contain plain text mixed with any number of
+variables. The format can be specified as a literal "string", or you can have
+curl read the format from a file with "@filename" and to tell curl to read the
+format from stdin you write "@-".
+
+The variables present in the output format are substituted by the value or
+text that curl thinks fit, as described below. All variables are specified as
+%{variable_name} and to output a normal % you just write them as %%. You can
+output a newline by using \n, a carriage return with \r and a tab space with
+\t.
+
+The output is by default written to standard output, but can be changed with
+%{stderr} and %output{}.
+
+Output HTTP headers from the most recent request by using *%header{name}*
+where *name* is the case insensitive name of the header (without the trailing
+colon). The header contents are exactly as sent over the network, with leading
+and trailing whitespace trimmed (added in 7.84.0).
+
+Select a specific target destination file to write the output to, by using
+*%output{name}* (added in curl 8.3.0) where *name* is the full file name. The
+output following that instruction is then written to that file. More than one
+*%output{}* instruction can be specified in the same write-out argument. If
+the file name cannot be created, curl leaves the output destination to the one
+used prior to the *%output{}* instruction. Use *%output{>>name}* to append
+data to an existing file.
+
+**NOTE:**
+In Windows the %-symbol is a special symbol used to expand environment
+variables. In batch files all occurrences of % must be doubled when using this
+option to properly escape. If this option is used at the command prompt then
+the % cannot be escaped and unintended expansion is possible.
+
+The variables available are:
+
+## `certs`
+Output the certificate chain with details. Supported only by the OpenSSL,
+GnuTLS, Schannel and Secure Transport backends. (Added in 7.88.0)
+
+## `content_type`
+The Content-Type of the requested document, if there was any.
+
+## `errormsg`
+The error message. (Added in 7.75.0)
+
+## `exitcode`
+The numerical exit code of the transfer. (Added in 7.75.0)
+
+## `filename_effective`
+The ultimate filename that curl writes out to. This is only meaningful if curl
+is told to write to a file with the --remote-name or --output
+option. It's most useful in combination with the --remote-header-name
+option. (Added in 7.26.0)
+
+## `ftp_entry_path`
+The initial path curl ended up in when logging on to the remote FTP
+server. (Added in 7.15.4)
+
+## `header_json`
+A JSON object with all HTTP response headers from the recent transfer. Values
+are provided as arrays, since in the case of multiple headers there can be
+multiple values. (Added in 7.83.0)
+
+The header names provided in lowercase, listed in order of appearance over the
+wire. Except for duplicated headers. They are grouped on the first occurrence
+of that header, each value is presented in the JSON array.
+
+## `http_code`
+The numerical response code that was found in the last retrieved HTTP(S) or
+FTP(s) transfer.
+
+## `http_connect`
+The numerical code that was found in the last response (from a proxy) to a
+curl CONNECT request. (Added in 7.12.4)
+
+## `http_version`
+The http version that was effectively used. (Added in 7.50.0)
+
+## `json`
+A JSON object with all available keys. (Added in 7.70.0)
+
+## `local_ip`
+The IP address of the local end of the most recently done connection - can be
+either IPv4 or IPv6. (Added in 7.29.0)
+
+## `local_port`
+The local port number of the most recently done connection. (Added in 7.29.0)
+
+## `method`
+The http method used in the most recent HTTP request. (Added in 7.72.0)
+
+## `num_certs`
+Number of server certificates received in the TLS handshake. Supported only by
+the OpenSSL, GnuTLS, Schannel and Secure Transport backends.
+(Added in 7.88.0)
+
+## `num_connects`
+Number of new connects made in the recent transfer. (Added in 7.12.3)
+
+## `num_headers`
+The number of response headers in the most recent request (restarted at each
+redirect). Note that the status line IS NOT a header. (Added in 7.73.0)
+
+## `num_redirects`
+Number of redirects that were followed in the request. (Added in 7.12.3)
+
+## `onerror`
+The rest of the output is only shown if the transfer returned a non-zero error.
+(Added in 7.75.0)
+
+## `proxy_ssl_verify_result`
+The result of the HTTPS proxy's SSL peer certificate verification that was
+requested. 0 means the verification was successful. (Added in 7.52.0)
+
+## `redirect_url`
+When an HTTP request was made without --location to follow redirects (or when
+--max-redirs is met), this variable shows the actual URL a redirect
+*would* have gone to. (Added in 7.18.2)
+
+## `referer`
+The Referer: header, if there was any. (Added in 7.76.0)
+
+## `remote_ip`
+The remote IP address of the most recently done connection - can be either
+IPv4 or IPv6. (Added in 7.29.0)
+
+## `remote_port`
+The remote port number of the most recently done connection. (Added in 7.29.0)
+
+## `response_code`
+The numerical response code that was found in the last transfer (formerly
+known as "http_code"). (Added in 7.18.2)
+
+## `scheme`
+The URL scheme (sometimes called protocol) that was effectively used. (Added in 7.52.0)
+
+## `size_download`
+The total amount of bytes that were downloaded. This is the size of the
+body/data that was transferred, excluding headers.
+
+## `size_header`
+The total amount of bytes of the downloaded headers.
+
+## `size_request`
+The total amount of bytes that were sent in the HTTP request.
+
+## `size_upload`
+The total amount of bytes that were uploaded. This is the size of the
+body/data that was transferred, excluding headers.
+
+## `speed_download`
+The average download speed that curl measured for the complete download. Bytes
+per second.
+
+## `speed_upload`
+The average upload speed that curl measured for the complete upload. Bytes per
+second.
+
+## `ssl_verify_result`
+The result of the SSL peer certificate verification that was requested. 0
+means the verification was successful. (Added in 7.19.0)
+
+## `stderr`
+From this point on, the --write-out output is written to standard
+error. (Added in 7.63.0)
+
+## `stdout`
+From this point on, the --write-out output is written to standard output.
+This is the default, but can be used to switch back after switching to stderr.
+(Added in 7.63.0)
+
+## `time_appconnect`
+The time, in seconds, it took from the start until the SSL/SSH/etc
+connect/handshake to the remote host was completed. (Added in 7.19.0)
+
+## `time_connect`
+The time, in seconds, it took from the start until the TCP connect to the
+remote host (or proxy) was completed.
+
+## `time_namelookup`
+The time, in seconds, it took from the start until the name resolving was
+completed.
+
+## `time_pretransfer`
+The time, in seconds, it took from the start until the file transfer was just
+about to begin. This includes all pre-transfer commands and negotiations that
+are specific to the particular protocol(s) involved.
+
+## `time_redirect`
+The time, in seconds, it took for all redirection steps including name lookup,
+connect, pretransfer and transfer before the final transaction was
+started. `time_redirect` shows the complete execution time for multiple
+redirections. (Added in 7.12.3)
+
+## `time_starttransfer`
+The time, in seconds, it took from the start until the first byte is received.
+This includes time_pretransfer and also the time the server needed to calculate
+the result.
+
+## `time_total`
+The total time, in seconds, that the full operation lasted.
+
+## `url`
+The URL that was fetched. (Added in 7.75.0)
+
+## `url.scheme`
+The scheme part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.user`
+The user part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.password`
+The password part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.options`
+The options part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.host`
+The host part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.port`
+The port number of the URL that was fetched. If no port number was specified
+and the URL scheme is known, that scheme's default port number is
+shown. (Added in 8.1.0)
+
+## `url.path`
+The path part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.query`
+The query part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.fragment`
+The fragment part of the URL that was fetched. (Added in 8.1.0)
+
+## `url.zoneid`
+The zone id part of the URL that was fetched. (Added in 8.1.0)
+
+## `urle.scheme`
+The scheme part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.user`
+The user part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.password`
+The password part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.options`
+The options part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.host`
+The host part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.port`
+The port number of the effective (last) URL that was fetched. If no port
+number was specified, but the URL scheme is known, that scheme's default port
+number is shown. (Added in 8.1.0)
+
+## `urle.path`
+The path part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.query`
+The query part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.fragment`
+The fragment part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urle.zoneid`
+The zone id part of the effective (last) URL that was fetched. (Added in 8.1.0)
+
+## `urlnum`
+The URL index number of this transfer, 0-indexed. Unglobbed URLs share the
+same index number as the origin globbed URL. (Added in 7.75.0)
+
+## `url_effective`
+The URL that was fetched last. This is most meaningful if you have told curl
+to follow location: headers.
diff --git a/docs/cmdline-opts/xattr.d b/docs/cmdline-opts/xattr.d
deleted file mode 100644
index 31bdb2d72..000000000
--- a/docs/cmdline-opts/xattr.d
+++ /dev/null
@@ -1,15 +0,0 @@
-c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
-SPDX-License-Identifier: curl
-Long: xattr
-Help: Store metadata in extended file attributes
-Category: misc
-Example: --xattr -o storage $URL
-Added: 7.21.3
-See-also: remote-time write-out verbose
-Multi: boolean
----
-When saving output to a file, this option tells curl to store certain file
-metadata in extended file attributes. Currently, the URL is stored in the
-xdg.origin.url attribute and, for HTTP, the content type is stored in
-the mime_type attribute. If the file system does not support extended
-attributes, a warning is issued.
diff --git a/docs/cmdline-opts/xattr.md b/docs/cmdline-opts/xattr.md
new file mode 100644
index 000000000..a09819ced
--- /dev/null
+++ b/docs/cmdline-opts/xattr.md
@@ -0,0 +1,23 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Long: xattr
+Help: Store metadata in extended file attributes
+Category: misc
+Added: 7.21.3
+Multi: boolean
+See-also:
+ - remote-time
+ - write-out
+ - verbose
+Example:
+ - --xattr -o storage $URL
+---
+
+# `--xattr`
+
+When saving output to a file, this option tells curl to store certain file
+metadata in extended file attributes. Currently, the URL is stored in the
+`xdg.origin.url` attribute and, for HTTP, the content type is stored in the
+`mime_type` attribute. If the file system does not support extended
+attributes, a warning is issued.
diff --git a/docs/curl-config.1 b/docs/curl-config.1
deleted file mode 100644
index 65cd2c971..000000000
--- a/docs/curl-config.1
+++ /dev/null
@@ -1,105 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl-config 1 "25 Oct 2007" curl-config curl-config
-.SH NAME
-curl-config \- Get information about a libcurl installation
-.SH SYNOPSIS
-.B curl-config [options]
-.SH DESCRIPTION
-.B curl-config
-displays information about the curl and libcurl installation.
-.SH OPTIONS
-.IP "--ca"
-Displays the built-in path to the CA cert bundle this libcurl uses.
-.IP "--cc"
-Displays the compiler used to build libcurl.
-.IP "--cflags"
-Set of compiler options (CFLAGS) to use when compiling files that use
-libcurl. Currently that is only the include path to the curl include files.
-.IP "--checkfor [version]"
-Specify the oldest possible libcurl version string you want, and this
-script will return 0 if the current installation is new enough or it
-returns 1 and outputs a text saying that the current version is not new
-enough. (Added in 7.15.4)
-.IP "--configure"
-Displays the arguments given to configure when building curl.
-.IP "--feature"
-Lists what particular main features the installed libcurl was built with. At
-the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume
-any particular order. The keywords will be separated by newlines. There may be
-none, one, or several keywords in the list.
-.IP "--help"
-Displays the available options.
-.IP "--libs"
-Shows the complete set of libs and other linker options you will need in order
-to link your application with libcurl.
-.IP "--prefix"
-This is the prefix used when libcurl was installed. Libcurl is then installed
-in $prefix/lib and its header files are installed in $prefix/include and so
-on. The prefix is set with "configure --prefix".
-.IP "--protocols"
-Lists what particular protocols the installed libcurl was built to support. At
-the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE,
-TELNET, LDAP, DICT and many more. Do not assume any particular order. The
-protocols will be listed using uppercase and are separated by newlines. There
-may be none, one, or several protocols in the list. (Added in 7.13.0)
-.IP "--ssl-backends"
-Lists the SSL backends that were enabled when libcurl was built. It might be
-no, one or several names. If more than one name, they will appear
-comma-separated. (Added in 7.58.0)
-.IP "--static-libs"
-Shows the complete set of libs and other linker options you will need in order
-to link your application with libcurl statically. (Added in 7.17.1)
-.IP "--version"
-Outputs version information about the installed libcurl.
-.IP "--vernum"
-Outputs version information about the installed libcurl, in numerical mode.
-This outputs the version number, in hexadecimal, with 8 bits for each part:
-major, minor, and patch. So that libcurl 7.7.4 would appear as 070704 and libcurl
-12.13.14 would appear as 0c0d0e... Note that the initial zero might be
-omitted. (This option was broken in the 7.15.0 release.)
-.SH "EXAMPLES"
-What linker options do I need when I link with libcurl?
-.nf
- $ curl-config --libs
-.fi
-What compiler options do I need when I compile using libcurl functions?
-.nf
- $ curl-config --cflags
-.fi
-How do I know if libcurl was built with SSL support?
-.nf
- $ curl-config --feature | grep SSL
-.fi
-What's the installed libcurl version?
-.nf
- $ curl-config --version
-.fi
-How do I build a single file with a one-line command?
-.nf
- $ `curl-config --cc --cflags` -o example example.c `curl-config --libs`
-.fi
-.SH "SEE ALSO"
-.BR curl (1)
diff --git a/docs/curl-config.md b/docs/curl-config.md
new file mode 100644
index 000000000..efb92aa80
--- /dev/null
+++ b/docs/curl-config.md
@@ -0,0 +1,124 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl-config
+Section: 1
+Source: curl-config
+See-also:
+ - curl (1)
+---
+
+# NAME
+
+curl-config - Get information about a libcurl installation
+
+# SYNOPSIS
+
+**curl-config [options]**
+
+# DESCRIPTION
+
+**curl-config**
+displays information about the curl and libcurl installation.
+
+# OPTIONS
+
+## --ca
+
+Displays the built-in path to the CA cert bundle this libcurl uses.
+
+## --cc
+
+Displays the compiler used to build libcurl.
+
+## --cflags
+
+Set of compiler options (CFLAGS) to use when compiling files that use
+libcurl. Currently that is only the include path to the curl include files.
+
+## --checkfor [version]
+
+Specify the oldest possible libcurl version string you want, and this
+script will return 0 if the current installation is new enough or it
+returns 1 and outputs a text saying that the current version is not new
+enough. (Added in 7.15.4)
+
+## --configure
+
+Displays the arguments given to configure when building curl.
+
+## --feature
+
+Lists what particular main features the installed libcurl was built with. At
+the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume
+any particular order. The keywords will be separated by newlines. There may be
+none, one, or several keywords in the list.
+
+## --help
+
+Displays the available options.
+
+## --libs
+
+Shows the complete set of libs and other linker options you will need in order
+to link your application with libcurl.
+
+## --prefix
+
+This is the prefix used when libcurl was installed. Libcurl is then installed
+in $prefix/lib and its header files are installed in $prefix/include and so
+on. The prefix is set with "configure --prefix".
+
+## --protocols
+
+Lists what particular protocols the installed libcurl was built to support. At
+the time of writing, this list may include HTTP, HTTPS, FTP, FTPS, FILE,
+TELNET, LDAP, DICT and many more. Do not assume any particular order. The
+protocols will be listed using uppercase and are separated by newlines. There
+may be none, one, or several protocols in the list. (Added in 7.13.0)
+
+## --ssl-backends
+
+Lists the SSL backends that were enabled when libcurl was built. It might be
+no, one or several names. If more than one name, they will appear
+comma-separated. (Added in 7.58.0)
+
+## --static-libs
+
+Shows the complete set of libs and other linker options you will need in order
+to link your application with libcurl statically. (Added in 7.17.1)
+
+## --version
+
+Outputs version information about the installed libcurl.
+
+## --vernum
+
+Outputs version information about the installed libcurl, in numerical mode.
+This shows the version number, in hexadecimal, using 8 bits for each part:
+major, minor, and patch numbers. This makes libcurl 7.7.4 appear as 070704 and
+libcurl 12.13.14 appear as 0c0d0e... Note that the initial zero might be
+omitted. (This option was broken in the 7.15.0 release.)
+
+# EXAMPLES
+
+What linker options do I need when I link with libcurl?
+~~~
+ $ curl-config --libs
+~~~
+What compiler options do I need when I compile using libcurl functions?
+~~~
+ $ curl-config --cflags
+~~~
+How do I know if libcurl was built with SSL support?
+~~~
+ $ curl-config --feature | grep SSL
+~~~
+What's the installed libcurl version?
+~~~
+ $ curl-config --version
+~~~
+How do I build a single file with a one-line command?
+~~~
+ $ `curl-config --cc --cflags` -o example source.c `curl-config --libs`
+~~~
diff --git a/docs/examples/10-at-a-time.c b/docs/examples/10-at-a-time.c
index b54a4410c..a622410fd 100644
--- a/docs/examples/10-at-a-time.c
+++ b/docs/examples/10-at-a-time.c
@@ -29,7 +29,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#ifndef WIN32
+#ifndef _WIN32
# include <unistd.h>
#endif
#include <curl/curl.h>
@@ -95,7 +95,7 @@ static size_t write_cb(char *data, size_t n, size_t l, void *userp)
return n*l;
}
-static void add_transfer(CURLM *cm, int i, int *left)
+static void add_transfer(CURLM *cm, unsigned int i, int *left)
{
CURL *eh = curl_easy_init();
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, write_cb);
diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc
index 60a006ca9..71dac0bf4 100644
--- a/docs/examples/Makefile.inc
+++ b/docs/examples/Makefile.inc
@@ -25,6 +25,7 @@
# These are all libcurl example programs to be test compiled
check_PROGRAMS = \
10-at-a-time \
+ address-scope \
altsvc \
anyauthput \
certinfo \
@@ -76,7 +77,10 @@ check_PROGRAMS = \
imap-ssl \
imap-store \
imap-tls \
+ interface \
ipv6 \
+ keepalive \
+ localport \
maxconnects \
multi-app \
multi-debugcallback \
@@ -85,6 +89,7 @@ check_PROGRAMS = \
multi-legacy \
multi-post \
multi-single \
+ netrc \
parseurl \
persistent \
pop3-authzid \
@@ -104,7 +109,9 @@ check_PROGRAMS = \
postit2-formadd \
progressfunc \
protofeats \
+ range \
resolve \
+ rtsp-options \
sendrecv \
sepheaders \
sftpget \
diff --git a/docs/examples/Makefile.mk b/docs/examples/Makefile.mk
index 599acee0b..5a5372dd3 100644
--- a/docs/examples/Makefile.mk
+++ b/docs/examples/Makefile.mk
@@ -26,10 +26,6 @@
PROOT := ../..
-ifeq ($(findstring -static,$(CFG)),)
- DYN := 1
-endif
-
### Common
include $(PROOT)/lib/Makefile.mk
@@ -40,35 +36,17 @@ CPPFLAGS += -DCURL_NO_OLDIES
LDFLAGS += -L$(PROOT)/lib
LIBS := -lcurl $(LIBS)
-ifdef DYN
- curl_DEPENDENCIES += $(PROOT)/lib/libcurl.dll.a
-else
- curl_DEPENDENCIES := $(PROOT)/lib/libcurl.a
- ifdef WIN32
- CPPFLAGS += -DCURL_STATICLIB
- LDFLAGS += -static
- endif
-endif
-
-ifdef WIN32
- LIBS += -lws2_32
-endif
-
### Sources and targets
# Provides check_PROGRAMS
include Makefile.inc
-ifdef WIN32
-check_PROGRAMS += synctime
-endif
-
TARGETS := $(patsubst %,%$(BIN_EXT),$(strip $(check_PROGRAMS)))
TOCLEAN := $(TARGETS)
### Rules
-%$(BIN_EXT): %.c $(curl_DEPENDENCIES)
- $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(CURL_LDFLAGS_BIN) $< -o $@ $(LIBS)
+%$(BIN_EXT): %.c $(PROOT)/lib/libcurl.a
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LIBS)
all: $(TARGETS)
diff --git a/docs/examples/address-scope.c b/docs/examples/address-scope.c
new file mode 100644
index 000000000..dc305a072
--- /dev/null
+++ b/docs/examples/address-scope.c
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * HTTP GET to an IPv6 address with specific scope
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+#ifndef _WIN32
+#include <net/if.h>
+#endif
+
+int main(void)
+{
+#ifndef _WIN32
+ /* Windows users need to find how to use if_nametoindex() */
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ long my_scope_id;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ my_scope_id = if_nametoindex("eth0");
+ curl_easy_setopt(curl, CURLOPT_ADDRESS_SCOPE, my_scope_id);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+#endif
+ return 0;
+}
diff --git a/docs/examples/anyauthput.c b/docs/examples/anyauthput.c
index 8b979515a..156e8d152 100644
--- a/docs/examples/anyauthput.c
+++ b/docs/examples/anyauthput.c
@@ -33,7 +33,7 @@
#include <curl/curl.h>
-#ifdef WIN32
+#ifdef _WIN32
# define FILENO(fp) _fileno(fp)
#else
# define FILENO(fp) fileno(fp)
@@ -69,17 +69,15 @@ static int my_seek(void *userp, curl_off_t offset, int origin)
/* read callback function, fread() look alike */
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
- ssize_t retcode;
- unsigned long nread;
+ size_t nread;
- retcode = fread(ptr, size, nmemb, stream);
+ nread = fread(ptr, size, nmemb, stream);
- if(retcode > 0) {
- nread = (unsigned long)retcode;
- fprintf(stderr, "*** We read %lu bytes from file\n", nread);
+ if(nread > 0) {
+ fprintf(stderr, "*** We read %lu bytes from file\n", (unsigned long)nread);
}
- return retcode;
+ return nread;
}
int main(int argc, char **argv)
diff --git a/docs/examples/chkspeed.c b/docs/examples/chkspeed.c
index 45765b988..a8d95666c 100644
--- a/docs/examples/chkspeed.c
+++ b/docs/examples/chkspeed.c
@@ -126,15 +126,17 @@ int main(int argc, char *argv[])
default:
fprintf(stderr, "\r%s: invalid parameter %s\n",
appname, *argv + 3);
- exit(1);
+ return 1;
}
break;
}
- /* FALLTHROUGH */
+ fprintf(stderr, "\r%s: invalid or unknown option %s\n",
+ appname, *argv);
+ return 1;
default:
fprintf(stderr, "\r%s: invalid or unknown option %s\n",
appname, *argv);
- exit(1);
+ return 1;
}
}
else {
diff --git a/docs/examples/cookie_interface.c b/docs/examples/cookie_interface.c
index 557b57dc2..120049830 100644
--- a/docs/examples/cookie_interface.c
+++ b/docs/examples/cookie_interface.c
@@ -91,7 +91,7 @@ main(void)
printf("-----------------------------------------------\n"
"Setting a cookie \"PREF\" via cookie interface:\n");
-#ifdef WIN32
+#ifdef _WIN32
#define snprintf _snprintf
#endif
/* Netscape format cookie */
diff --git a/docs/examples/debug.c b/docs/examples/debug.c
index 684a18327..68d93039e 100644
--- a/docs/examples/debug.c
+++ b/docs/examples/debug.c
@@ -95,10 +95,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -117,6 +114,8 @@ int my_trace(CURL *handle, curl_infotype type,
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
dump(text, stderr, (unsigned char *)data, size, config->trace_ascii);
diff --git a/docs/examples/externalsocket.c b/docs/examples/externalsocket.c
index 1c78c3db4..9c3437344 100644
--- a/docs/examples/externalsocket.c
+++ b/docs/examples/externalsocket.c
@@ -30,10 +30,8 @@
#include <stdlib.h>
#include <curl/curl.h>
-#ifdef WIN32
-#include <windows.h>
+#ifdef _WIN32
#include <winsock2.h>
-#include <ws2tcpip.h>
#define close closesocket
#else
#include <sys/types.h> /* socket types */
@@ -96,7 +94,7 @@ int main(void)
struct sockaddr_in servaddr; /* socket address structure */
curl_socket_t sockfd;
-#ifdef WIN32
+#ifdef _WIN32
WSADATA wsaData;
int initwsa = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(initwsa) {
@@ -168,7 +166,7 @@ int main(void)
}
}
-#ifdef WIN32
+#ifdef _WIN32
WSACleanup();
#endif
return 0;
diff --git a/docs/examples/ftpget.c b/docs/examples/ftpget.c
index 94609fe0d..95369c1c0 100644
--- a/docs/examples/ftpget.c
+++ b/docs/examples/ftpget.c
@@ -42,7 +42,7 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
/* open file for writing */
out->stream = fopen(out->filename, "wb");
if(!out->stream)
- return -1; /* failure, cannot open file to write */
+ return 0; /* failure, cannot open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
diff --git a/docs/examples/ftpsget.c b/docs/examples/ftpsget.c
index dbe7d14bf..dfe80b9f8 100644
--- a/docs/examples/ftpsget.c
+++ b/docs/examples/ftpsget.c
@@ -44,7 +44,7 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
/* open file for writing */
out->stream = fopen(out->filename, "wb");
if(!out->stream)
- return -1; /* failure, cannot open file to write */
+ return 0; /* failure, cannot open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
diff --git a/docs/examples/ftpupload.c b/docs/examples/ftpupload.c
index 00de126ea..92bb0b8a0 100644
--- a/docs/examples/ftpupload.c
+++ b/docs/examples/ftpupload.c
@@ -29,7 +29,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
diff --git a/docs/examples/http2-download.c b/docs/examples/http2-download.c
index a2291a8c7..5da7ed603 100644
--- a/docs/examples/http2-download.c
+++ b/docs/examples/http2-download.c
@@ -54,7 +54,7 @@ struct transfer {
#define NUM_HANDLES 1000
static
-void dump(const char *text, int num, unsigned char *ptr, size_t size,
+void dump(const char *text, unsigned int num, unsigned char *ptr, size_t size,
char nohex)
{
size_t i;
@@ -66,7 +66,7 @@ void dump(const char *text, int num, unsigned char *ptr, size_t size,
/* without the hex output, we can fit more on screen */
width = 0x40;
- fprintf(stderr, "%d %s, %lu bytes (0x%lx)\n",
+ fprintf(stderr, "%u %s, %lu bytes (0x%lx)\n",
num, text, (unsigned long)size, (unsigned long)size);
for(i = 0; i<size; i += width) {
@@ -115,10 +115,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "== %u Info: %s", num, data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -137,6 +134,8 @@ int my_trace(CURL *handle, curl_infotype type,
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
dump(text, num, (unsigned char *)data, size, 1);
diff --git a/docs/examples/http2-serverpush.c b/docs/examples/http2-serverpush.c
index b5ebe2eb9..e830aa95d 100644
--- a/docs/examples/http2-serverpush.c
+++ b/docs/examples/http2-serverpush.c
@@ -100,10 +100,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -122,6 +119,8 @@ int my_trace(CURL *handle, curl_infotype type,
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
dump(text, (unsigned char *)data, size, 1);
diff --git a/docs/examples/http2-upload.c b/docs/examples/http2-upload.c
index 5889d0c36..dd63b8cd5 100644
--- a/docs/examples/http2-upload.c
+++ b/docs/examples/http2-upload.c
@@ -133,10 +133,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "%s [%d] Info: %s", timebuf, num, data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -155,6 +152,8 @@ int my_trace(CURL *handle, curl_infotype type,
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
dump(text, num, (unsigned char *)data, size, 1);
diff --git a/docs/examples/interface.c b/docs/examples/interface.c
new file mode 100644
index 000000000..f1a2016ce
--- /dev/null
+++ b/docs/examples/interface.c
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Use CURLOPT_INTERFACE to bind the outgoing socket to an interface
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ curl = curl_easy_init();
+ if(curl) {
+ /* The interface needs to be a local existing interface over which you can
+ connect to the host in the URL. It can also specify an IP address, but
+ that address needs to be assigned one of the local network
+ interfaces. */
+ curl_easy_setopt(curl, CURLOPT_INTERFACE, "enp3s0");
+ curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/");
+
+ res = curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+
+ return (int)res;
+}
diff --git a/docs/examples/ipv6.c b/docs/examples/ipv6.c
index 49a44fa7a..1b698705d 100644
--- a/docs/examples/ipv6.c
+++ b/docs/examples/ipv6.c
@@ -22,41 +22,27 @@
*
***************************************************************************/
/* <DESC>
- * HTTP GET to an IPv6 address with specific scope
+ * HTTPS GET using IPv6 only
* </DESC>
*/
#include <stdio.h>
#include <curl/curl.h>
-#ifndef WIN32
-#include <net/if.h>
-#endif
-
int main(void)
{
-#ifndef WIN32
- /* Windows users need to find how to use if_nametoindex() */
CURL *curl;
- CURLcode res;
+ CURLcode res = CURLE_OK;
curl = curl_easy_init();
if(curl) {
- long my_scope_id;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
- my_scope_id = if_nametoindex("eth0");
- curl_easy_setopt(curl, CURLOPT_ADDRESS_SCOPE, my_scope_id);
+ curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/");
- /* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
- /* Check for errors */
- if(res != CURLE_OK)
- fprintf(stderr, "curl_easy_perform() failed: %s\n",
- curl_easy_strerror(res));
- /* always cleanup */
curl_easy_cleanup(curl);
}
-#endif
- return 0;
+
+ return (int)res;
}
diff --git a/docs/examples/keepalive.c b/docs/examples/keepalive.c
new file mode 100644
index 000000000..1c876bb1f
--- /dev/null
+++ b/docs/examples/keepalive.c
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Use the TCP keep-alive options
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ curl = curl_easy_init();
+ if(curl) {
+ /* enable TCP keep-alive for this transfer */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
+
+ /* keep-alive idle time to 120 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
+
+ /* interval time between keep-alive probes: 60 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+
+ return (int)res;
+}
diff --git a/docs/examples/localport.c b/docs/examples/localport.c
new file mode 100644
index 000000000..56e0b62cf
--- /dev/null
+++ b/docs/examples/localport.c
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Use CURLOPT_LOCALPORT to control local port number
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ curl = curl_easy_init();
+ if(curl) {
+ /* Try to use a local port number between 20000-20009 */
+ curl_easy_setopt(curl, CURLOPT_LOCALPORT, 20000L);
+ /* 10 means number of attempts, which starts with the number set in
+ CURLOPT_LOCALPORT. The lowe value set, the smaller the change it will
+ work. */
+ curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, 10L);
+ curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/");
+
+ res = curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+
+ return (int)res;
+}
diff --git a/docs/examples/multi-debugcallback.c b/docs/examples/multi-debugcallback.c
index 8bdb58800..10842e950 100644
--- a/docs/examples/multi-debugcallback.c
+++ b/docs/examples/multi-debugcallback.c
@@ -100,10 +100,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -116,6 +113,8 @@ int my_trace(CURL *handle, curl_infotype type,
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
dump(text, stderr, data, size, TRUE);
diff --git a/docs/examples/netrc.c b/docs/examples/netrc.c
new file mode 100644
index 000000000..42e1b6341
--- /dev/null
+++ b/docs/examples/netrc.c
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Use credentials from .netrc
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+ curl_easy_setopt(curl, CURLOPT_NETRC_FILE,
+ "/home/daniel/s3cr3ts.txt");
+ curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+
+ return (int)res;
+}
diff --git a/docs/examples/range.c b/docs/examples/range.c
new file mode 100644
index 000000000..1a93f3676
--- /dev/null
+++ b/docs/examples/range.c
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * GET a range only of a HTTP resource
+ * </DESC>
+ */
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res = CURLE_OK;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/");
+ curl_easy_setopt(curl, CURLOPT_RANGE, "200-999");
+
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+
+ return (int)res;
+}
diff --git a/docs/examples/rtsp-options.c b/docs/examples/rtsp-options.c
new file mode 100644
index 000000000..e4a623048
--- /dev/null
+++ b/docs/examples/rtsp-options.c
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Very simple RTSP request sending OPTIONS.
+ * </DESC>
+ */
+#include <stdio.h>
+#include <curl/curl.h>
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
+
+ curl_easy_setopt(curl, CURLOPT_RTSP_SESSION_ID, "12345");
+
+ curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_OPTIONS);
+
+ /* Perform the request, res will get the return code */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
diff --git a/docs/examples/sendrecv.c b/docs/examples/sendrecv.c
index b935bee10..eabe0c226 100644
--- a/docs/examples/sendrecv.c
+++ b/docs/examples/sendrecv.c
@@ -44,6 +44,14 @@ static int wait_on_socket(curl_socket_t sockfd, int for_recv, long timeout_ms)
FD_ZERO(&outfd);
FD_ZERO(&errfd);
+/* Avoid this warning with pre-2020 Cygwin/MSYS releases:
+ * warning: conversion to 'long unsigned int' from 'curl_socket_t' {aka 'int'}
+ * may change the sign of the result [-Wsign-conversion]
+ */
+#if defined(__GNUC__) && defined(__CYGWIN__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
FD_SET(sockfd, &errfd); /* always check for error */
if(for_recv) {
@@ -52,6 +60,9 @@ static int wait_on_socket(curl_socket_t sockfd, int for_recv, long timeout_ms)
else {
FD_SET(sockfd, &outfd);
}
+#if defined(__GNUC__) && defined(__CYGWIN__)
+#pragma GCC diagnostic pop
+#endif
/* select() returns the number of signalled sockets or -1 */
res = select((int)sockfd + 1, &infd, &outfd, &errfd, &tv);
diff --git a/docs/examples/sftpget.c b/docs/examples/sftpget.c
index 6f0cb2ad4..992d607ef 100644
--- a/docs/examples/sftpget.c
+++ b/docs/examples/sftpget.c
@@ -53,7 +53,7 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
/* open file for writing */
out->stream = fopen(out->filename, "wb");
if(!out->stream)
- return -1; /* failure, cannot open file to write */
+ return 0; /* failure, cannot open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
diff --git a/docs/examples/synctime.c b/docs/examples/synctime.c
index fcf25d941..2d7d523d5 100644
--- a/docs/examples/synctime.c
+++ b/docs/examples/synctime.c
@@ -91,11 +91,11 @@
#include <stdio.h>
#include <time.h>
-#ifndef __CYGWIN__
-#include <winsock2.h>
+#include <curl/curl.h>
+
+#ifdef _WIN32
#include <windows.h>
#endif
-#include <curl/curl.h>
#define MAX_STRING 256
diff --git a/docs/libcurl/.gitignore b/docs/libcurl/.gitignore
index fd35ad0fc..d520903f7 100644
--- a/docs/libcurl/.gitignore
+++ b/docs/libcurl/.gitignore
@@ -2,7 +2,4 @@
#
# SPDX-License-Identifier: curl
-*.html
-*.pdf
-*.3.dist
-libcurl-symbols.3
+libcurl-symbols.md
diff --git a/docs/libcurl/CMakeLists.txt b/docs/libcurl/CMakeLists.txt
index c83b5c91c..6f0aa6490 100644
--- a/docs/libcurl/CMakeLists.txt
+++ b/docs/libcurl/CMakeLists.txt
@@ -26,42 +26,33 @@ transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
function(add_manual_pages _listname)
+ unset(_rofffiles)
+ unset(_mdfiles)
foreach(_file IN LISTS ${_listname})
+ list(APPEND _rofffiles "${CMAKE_CURRENT_BINARY_DIR}/${_file}")
if(_file STREQUAL "libcurl-symbols.3")
# Special case, an auto-generated file.
- set(_srcfile "${CMAKE_CURRENT_BINARY_DIR}/${_file}")
+ string(REPLACE ".3" ".md" _mdfile "${CMAKE_CURRENT_BINARY_DIR}/${_file}")
else()
- set(_srcfile "${CMAKE_CURRENT_SOURCE_DIR}/${_file}")
+ string(REPLACE ".3" ".md" _mdfile "${_file}")
endif()
+ list(APPEND _mdfiles "${_mdfile}")
+ endforeach()
- string(REPLACE ".3" ".html" _htmlfile "${CMAKE_CURRENT_BINARY_DIR}/${_file}")
- add_custom_command(OUTPUT "${_htmlfile}"
- COMMAND roffit "--mandir=${CMAKE_CURRENT_SOURCE_DIR}" "${_srcfile}" > "${_htmlfile}"
- DEPENDS "${_srcfile}"
- VERBATIM
- )
+ add_custom_command(OUTPUT ${_rofffiles}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ COMMAND ${PROJECT_SOURCE_DIR}/scripts/cd2nroff -k -d "${CMAKE_CURRENT_BINARY_DIR}" ${_mdfiles}
+ DEPENDS ${_mdfiles}
+ VERBATIM
+ )
- string(REPLACE ".3" ".pdf" _pdffile "${CMAKE_CURRENT_BINARY_DIR}/${_file}")
- string(REPLACE ".3" ".ps" _psfile "${CMAKE_CURRENT_BINARY_DIR}/${_file}")
- # XXX any reason why groff -Tpdf (for gropdf) is not used?
- add_custom_command(OUTPUT "${_pdffile}"
- COMMAND groff -Tps -man "${_srcfile}" > "${_psfile}"
- COMMAND ps2pdf "${_psfile}" "${_pdffile}"
- COMMAND "${CMAKE_COMMAND}" -E remove "${_psfile}"
- DEPENDS "${_srcfile}"
- #BYPRODUCTS "${_psfile}"
- VERBATIM
- )
- # "BYPRODUCTS" for add_custom_command requires CMake 3.2. For now hope that
- # the temporary files are removed (i.e. the command is not interrupted).
- endforeach()
endfunction()
-add_custom_command(OUTPUT libcurl-symbols.3
+add_custom_command(OUTPUT libcurl-symbols.md
COMMAND
"${PERL_EXECUTABLE}"
"${CMAKE_CURRENT_SOURCE_DIR}/mksymbolsmanpage.pl" <
- "${CMAKE_CURRENT_SOURCE_DIR}/symbols-in-versions" > libcurl-symbols.3
+ "${CMAKE_CURRENT_SOURCE_DIR}/symbols-in-versions" > libcurl-symbols.md
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/symbols-in-versions"
"${CMAKE_CURRENT_SOURCE_DIR}/mksymbolsmanpage.pl"
@@ -69,10 +60,10 @@ add_custom_command(OUTPUT libcurl-symbols.3
)
add_manual_pages(man_MANS)
-
-string(REPLACE ".3" ".html" HTMLPAGES "${man_MANS}")
-string(REPLACE ".3" ".pdf" PDFPAGES "${man_MANS}")
-add_custom_target(html DEPENDS ${HTMLPAGES})
-add_custom_target(pdf DEPENDS ${PDFPAGES})
+add_custom_target(man ALL DEPENDS ${man_MANS})
+if(NOT CURL_DISABLE_INSTALL)
+ install(FILES "$<LIST:TRANSFORM,${man_MANS},PREPEND,${CMAKE_CURRENT_BINARY_DIR}/>"
+ DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
+endif()
add_subdirectory(opts)
diff --git a/docs/libcurl/Makefile.am b/docs/libcurl/Makefile.am
index 8d512a6c2..17b2bc80d 100644
--- a/docs/libcurl/Makefile.am
+++ b/docs/libcurl/Makefile.am
@@ -28,53 +28,27 @@ SUBDIRS = opts
include Makefile.inc
-man_DISTMANS = $(man_MANS:.3=.3.dist)
-
-HTMLPAGES = $(man_MANS:.3=.html)
-
-PDFPAGES = $(man_MANS:.3=.pdf)
+CURLPAGES = $(man_MANS:.3=.md)
m4macrodir = $(datadir)/aclocal
dist_m4macro_DATA = libcurl.m4
-CLEANFILES = $(HTMLPAGES) $(PDFPAGES) $(TESTS) $(man_DISTMANS) \
- libcurl-symbols.3
+CLEANFILES = $(man_MANS) libcurl-symbols.md
+nodist_MANS = $(man_MANS)
-EXTRA_DIST = $(man_MANS) ABI.md symbols-in-versions symbols.pl \
+EXTRA_DIST = $(CURLPAGES) ABI.md symbols-in-versions symbols.pl \
mksymbolsmanpage.pl CMakeLists.txt
-MAN2HTML= roffit --mandir=. $< >$@
-
-SUFFIXES = .3 .html
-
-libcurl-symbols.3: $(srcdir)/symbols-in-versions $(srcdir)/mksymbolsmanpage.pl
- perl $(srcdir)/mksymbolsmanpage.pl < $(srcdir)/symbols-in-versions > $@
-
-html: $(HTMLPAGES)
- cd opts && $(MAKE) html
-
-.3.html:
- $(MAN2HTML)
-
-pdf: $(PDFPAGES)
- cd opts && $(MAKE) pdf
-.3.pdf:
- @(foo=`echo $@ | sed -e 's/\.[0-9]$$//g'`; \
- groff -Tps -man $< >$$foo.ps; \
- ps2pdf $$foo.ps $@; \
- rm $$foo.ps; \
- echo "converted $< to $@")
+CD2NROFF = $(top_srcdir)/scripts/cd2nroff $< >$@
+CD2 = $(CD2_$(V))
+CD2_0 = @echo " RENDER " $@;
+CD2_1 =
+CD2_ = $(CD2_0)
-# Make sure each option man page is referenced in the main man page
-TESTS = check-easy check-multi
-LOG_COMPILER = $(PERL)
-# The test fails if the log file contains any text
-AM_LOG_FLAGS = -p -e 'die "$$_" if ($$_);'
+SUFFIXES = .3 .md
-check-easy: $(srcdir)/curl_easy_setopt.3 $(srcdir)/opts/CURLOPT*.3
- OPTS="$$(ls $(srcdir)/opts/CURLOPT*.3 | $(SED) -e 's,^.*/,,' -e 's,\.3$$,,')" && \
- for opt in $$OPTS; do grep "^\.IP $$opt$$" $(srcdir)/curl_easy_setopt.3 >/dev/null || echo Missing $$opt; done > $@
+libcurl-symbols.md: $(srcdir)/symbols-in-versions $(srcdir)/mksymbolsmanpage.pl
+ $(CD2)perl $(srcdir)/mksymbolsmanpage.pl < $(srcdir)/symbols-in-versions > $@
-check-multi: $(srcdir)/curl_multi_setopt.3 $(srcdir)/opts/CURLMOPT*.3
- OPTS="$$(ls $(srcdir)/opts/CURLMOPT*.3 | $(SED) -e 's,^.*/,,' -e 's,\.3$$,,')" && \
- for opt in $$OPTS; do grep "^\.IP $$opt$$" $(srcdir)/curl_multi_setopt.3 >/dev/null || echo Missing $$opt; done > $@
+.md.3:
+ $(CD2)$(CD2NROFF)
diff --git a/docs/libcurl/curl_easy_cleanup.3 b/docs/libcurl/curl_easy_cleanup.3
deleted file mode 100644
index d40ba67a8..000000000
--- a/docs/libcurl/curl_easy_cleanup.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_cleanup 3 "22 Aug 2007" "libcurl" "libcurl"
-.SH NAME
-curl_easy_cleanup - End a libcurl easy handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_easy_cleanup(CURL *handle);
-.fi
-.SH DESCRIPTION
-This function is the opposite of \fIcurl_easy_init(3)\fP. It closes down and
-frees all resources previously associated with this easy handle.
-
-This call closes all connections this handle has used and possibly has kept
-open until now unless the easy handle was attached to a multi handle while
-doing the transfers. Do not call this function if you intend to transfer more
-files, reusing handles is a key to good performance with libcurl.
-
-Occasionally you may get your progress callback or header callback called from
-within \fIcurl_easy_cleanup(3)\fP (if previously set for the handle using
-\fIcurl_easy_setopt(3)\fP). Like if libcurl decides to shut down the
-connection and the protocol is of a kind that requires a command/response
-sequence before disconnect. Examples of such protocols are FTP, POP3 and IMAP.
-
-Any use of the easy \fBhandle\fP after this function has been called and have
-returned, is illegal.
-
-To close an easy handle that has been used with the multi interface, make sure
-to first call \fIcurl_multi_remove_handle(3)\fP to remove it from the multi
-handle before it is closed.
-
-Passing in a NULL pointer in \fIhandle\fP makes this function return
-immediately with no action.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.1
-.SH RETURN VALUE
-None
-.SH "SEE ALSO"
-.BR curl_easy_duphandle (3),
-.BR curl_easy_init (3),
-.BR curl_easy_reset (3),
-.BR curl_multi_cleanup (3),
-.BR curl_multi_remove_handle (3)
diff --git a/docs/libcurl/curl_easy_cleanup.md b/docs/libcurl/curl_easy_cleanup.md
new file mode 100644
index 000000000..bdbc05894
--- /dev/null
+++ b/docs/libcurl/curl_easy_cleanup.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_cleanup
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_duphandle (3)
+ - curl_easy_init (3)
+ - curl_easy_reset (3)
+ - curl_multi_cleanup (3)
+ - curl_multi_remove_handle (3)
+---
+
+# NAME
+
+curl_easy_cleanup - End a libcurl easy handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_easy_cleanup(CURL *handle);
+~~~
+
+# DESCRIPTION
+
+This function is the opposite of curl_easy_init(3). It closes down and frees
+all resources previously associated with this easy handle.
+
+This call closes all connections this handle has used and possibly has kept
+open until now unless the easy handle was attached to a multi handle while
+doing the transfers. Do not call this function if you intend to transfer more
+files, reusing handles is a key to good performance with libcurl.
+
+Occasionally you may get your progress callback or header callback called from
+within curl_easy_cleanup(3) (if previously set for the handle using
+curl_easy_setopt(3)). Like if libcurl decides to shut down the connection and
+the protocol is of a kind that requires a command/response sequence before
+disconnect. Examples of such protocols are FTP, POP3 and IMAP.
+
+Any use of the easy **handle** after this function has been called and have
+returned, is illegal.
+
+To close an easy handle that has been used with the multi interface, make sure
+to first call curl_multi_remove_handle(3) to remove it from the multi handle
+before it is closed.
+
+Passing in a NULL pointer in *handle* makes this function return immediately
+with no action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res)
+ printf("error: %s\n", curl_easy_strerror(res));
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.1
+
+# RETURN VALUE
+
+None
diff --git a/docs/libcurl/curl_easy_duphandle.3 b/docs/libcurl/curl_easy_duphandle.3
deleted file mode 100644
index f66c1dffb..000000000
--- a/docs/libcurl/curl_easy_duphandle.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_duphandle 3 "19 Sep 2014" "libcurl" "libcurl"
-.SH NAME
-curl_easy_duphandle - Clone a libcurl session handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURL *curl_easy_duphandle(CURL *handle);
-.fi
-.SH DESCRIPTION
-This function returns a new curl handle, a duplicate, using all the options
-previously set in the input curl \fIhandle\fP. Both handles can subsequently
-be used independently and they must both be freed with
-\fIcurl_easy_cleanup(3)\fP.
-
-Any options that the input handle has been told to point to (as opposed to
-copy) with previous calls to \fIcurl_easy_setopt(3)\fP, are pointed to by the
-new handle as well. You must therefore make sure to keep the data around until
-both handles have been cleaned up.
-
-The new handle does \fBnot\fP inherit any state information, no connections,
-no SSL sessions and no cookies. It also does not inherit any share object
-states or options (created as if \fICURLOPT_SHARE(3)\fP was set to NULL).
-
-In multi-threaded programs, this function must be called in a synchronous way,
-the input handle may not be in use when cloned.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-CURL *nother;
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- nother = curl_easy_duphandle(curl);
- res = curl_easy_perform(nother);
- curl_easy_cleanup(nother);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.9
-.SH RETURN VALUE
-If this function returns NULL, something went wrong and no valid handle was
-returned.
-.SH SEE ALSO
-.BR curl_easy_cleanup (3),
-.BR curl_easy_init (3),
-.BR curl_easy_reset (3),
-.BR curl_global_init (3)
diff --git a/docs/libcurl/curl_easy_duphandle.md b/docs/libcurl/curl_easy_duphandle.md
new file mode 100644
index 000000000..d7c5b03be
--- /dev/null
+++ b/docs/libcurl/curl_easy_duphandle.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_duphandle
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_cleanup (3)
+ - curl_easy_init (3)
+ - curl_easy_reset (3)
+ - curl_global_init (3)
+---
+
+# NAME
+
+curl_easy_duphandle - Clone a libcurl session handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURL *curl_easy_duphandle(CURL *handle);
+~~~
+
+# DESCRIPTION
+
+This function returns a new curl handle, a duplicate, using all the options
+previously set in the input curl *handle*. Both handles can subsequently be
+used independently and they must both be freed with curl_easy_cleanup(3).
+
+Any options that the input handle has been told to point to (as opposed to
+copy) with previous calls to curl_easy_setopt(3), are pointed to by the new
+handle as well. You must therefore make sure to keep the data around until
+both handles have been cleaned up.
+
+The new handle does **not** inherit any state information, no connections, no
+SSL sessions and no cookies. It also does not inherit any share object states
+or options (created as if CURLOPT_SHARE(3) was set to NULL).
+
+If the source handle has HSTS or alt-svc enabled, the duplicate gets data read
+data from the main filename to populate the cache.
+
+In multi-threaded programs, this function must be called in a synchronous way,
+the input handle may not be in use when cloned.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ CURL *nother;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ nother = curl_easy_duphandle(curl);
+ res = curl_easy_perform(nother);
+ curl_easy_cleanup(nother);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9
+
+# RETURN VALUE
+
+If this function returns NULL, something went wrong and no valid handle was
+returned.
diff --git a/docs/libcurl/curl_easy_escape.3 b/docs/libcurl/curl_easy_escape.3
deleted file mode 100644
index e9ad9ff60..000000000
--- a/docs/libcurl/curl_easy_escape.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_escape 3 "7 April 2006" "libcurl" "libcurl"
-.SH NAME
-curl_easy_escape - URL encodes the given string
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_easy_escape(CURL *curl, const char *string, int length);
-.fi
-.SH DESCRIPTION
-This function converts the given input \fIstring\fP to a URL encoded string
-and returns that as a new allocated string. All input characters that are not
-a-z, A-Z, 0-9, '-', '.', '_' or '~' are converted to their "URL escaped"
-version (\fB%NN\fP where \fBNN\fP is a two-digit hexadecimal number).
-
-If \fIlength\fP is set to 0 (zero), \fIcurl_easy_escape(3)\fP uses strlen() on
-the input \fIstring\fP to find out the size. This function does not accept
-input strings longer than \fBCURL_MAX_INPUT_LENGTH\fP (8 MB).
-
-Since 7.82.0, the \fBcurl\fP parameter is ignored. Prior to that there was
-per-handle character conversion support for some old operating systems such as
-TPF, but it was otherwise ignored.
-
-You must \fIcurl_free(3)\fP the returned string when you are done with it.
-.SH ENCODING
-libcurl is typically not aware of, nor does it care about, character
-encodings. \fIcurl_easy_escape(3)\fP encodes the data byte-by-byte into the
-URL encoded version without knowledge or care for what particular character
-encoding the application or the receiving server may assume that the data
-uses.
-
-The caller of \fIcurl_easy_escape(3)\fP must make sure that the data passed in
-to the function is encoded correctly.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- char *output = curl_easy_escape(curl, "data to convert", 15);
- if(output) {
- printf("Encoded: %s\\n", output);
- curl_free(output);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.4 and replaces the old \fIcurl_escape(3)\fP function.
-.SH RETURN VALUE
-A pointer to a null-terminated string or NULL if it failed.
-.SH "SEE ALSO"
-.BR curl_easy_unescape (3),
-.BR curl_free (3)
diff --git a/docs/libcurl/curl_easy_escape.md b/docs/libcurl/curl_easy_escape.md
new file mode 100644
index 000000000..655dbb446
--- /dev/null
+++ b/docs/libcurl/curl_easy_escape.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_escape
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_unescape (3)
+ - curl_free (3)
+---
+
+# NAME
+
+curl_easy_escape - URL encodes the given string
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_easy_escape(CURL *curl, const char *string, int length);
+~~~
+
+# DESCRIPTION
+
+This function converts the given input *string* to a URL encoded string
+and returns that as a new allocated string. All input characters that are not
+a-z, A-Z, 0-9, '-', '.', '_' or '~' are converted to their "URL escaped"
+version (**%NN** where **NN** is a two-digit hexadecimal number).
+
+If *length* is set to 0 (zero), curl_easy_escape(3) uses strlen() on
+the input *string* to find out the size. This function does not accept
+input strings longer than **CURL_MAX_INPUT_LENGTH** (8 MB).
+
+Since 7.82.0, the **curl** parameter is ignored. Prior to that there was
+per-handle character conversion support for some old operating systems such as
+TPF, but it was otherwise ignored.
+
+You must curl_free(3) the returned string when you are done with it.
+
+# ENCODING
+
+libcurl is typically not aware of, nor does it care about, character
+encodings. curl_easy_escape(3) encodes the data byte-by-byte into the
+URL encoded version without knowledge or care for what particular character
+encoding the application or the receiving server may assume that the data
+uses.
+
+The caller of curl_easy_escape(3) must make sure that the data passed in
+to the function is encoded correctly.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ char *output = curl_easy_escape(curl, "data to convert", 15);
+ if(output) {
+ printf("Encoded: %s\n", output);
+ curl_free(output);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.4 and replaces the old curl_escape(3) function.
+
+# RETURN VALUE
+
+A pointer to a null-terminated string or NULL if it failed.
diff --git a/docs/libcurl/curl_easy_getinfo.3 b/docs/libcurl/curl_easy_getinfo.3
deleted file mode 100644
index b0d8ae89d..000000000
--- a/docs/libcurl/curl_easy_getinfo.3
+++ /dev/null
@@ -1,325 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_getinfo 3 "11 Feb 2009" "libcurl" "libcurl"
-.SH NAME
-curl_easy_getinfo - extract information from a curl handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );
-.fi
-.SH DESCRIPTION
-Get the \fIinfo\fP kept in the \fIcurl\fP handle. The third argument
-\fBMUST\fP be pointing to the specific type of the used option which is
-documented in each man page of the \fIinfo\fP option. The data is stored
-accordingly and can be relied upon only if this function returns CURLE_OK. Use
-this function after a performed transfer if you want to get transfer related
-data.
-
-You should not free the memory returned by this function unless it is
-explicitly mentioned below.
-.SH AVAILABLE INFORMATION
-The following information can be extracted:
-.IP CURLINFO_EFFECTIVE_METHOD
-Last used HTTP method.
-See \fICURLINFO_EFFECTIVE_METHOD(3)\fP
-.IP CURLINFO_EFFECTIVE_URL
-Last used URL.
-See \fICURLINFO_EFFECTIVE_URL(3)\fP
-.IP CURLINFO_RESPONSE_CODE
-Last received response code.
-See \fICURLINFO_RESPONSE_CODE(3)\fP
-.IP CURLINFO_REFERER
-Referrer header.
-See \fICURLINFO_REFERER(3)\fP
-.IP CURLINFO_HTTP_CONNECTCODE
-Last proxy CONNECT response code.
-See \fICURLINFO_HTTP_CONNECTCODE(3)\fP
-.IP CURLINFO_HTTP_VERSION
-The http version used in the connection.
-See \fICURLINFO_HTTP_VERSION(3)\fP
-.IP CURLINFO_FILETIME
-Remote time of the retrieved document. See \fICURLINFO_FILETIME(3)\fP
-.IP CURLINFO_FILETIME_T
-Remote time of the retrieved document. See \fICURLINFO_FILETIME_T(3)\fP
-.IP CURLINFO_TOTAL_TIME
-Total time of previous transfer.
-See \fICURLINFO_TOTAL_TIME(3)\fP
-.IP CURLINFO_TOTAL_TIME_T
-Total time of previous transfer.
-See \fICURLINFO_TOTAL_TIME_T(3)\fP
-.IP CURLINFO_NAMELOOKUP_TIME
-Time from start until name resolving completed.
-See \fICURLINFO_NAMELOOKUP_TIME(3)\fP
-.IP CURLINFO_NAMELOOKUP_TIME_T
-Time from start until name resolving completed.
-See \fICURLINFO_NAMELOOKUP_TIME_T(3)\fP
-.IP CURLINFO_CONNECT_TIME
-Time from start until remote host or proxy completed.
-See \fICURLINFO_CONNECT_TIME(3)\fP
-.IP CURLINFO_CONNECT_TIME_T
-Time from start until remote host or proxy completed.
-See \fICURLINFO_CONNECT_TIME_T(3)\fP
-.IP CURLINFO_APPCONNECT_TIME
-Time from start until SSL/SSH handshake completed.
-See \fICURLINFO_APPCONNECT_TIME(3)\fP
-.IP CURLINFO_APPCONNECT_TIME_T
-Time from start until SSL/SSH handshake completed.
-See \fICURLINFO_APPCONNECT_TIME_T(3)\fP
-.IP CURLINFO_PRETRANSFER_TIME
-Time from start until just before the transfer begins.
-See \fICURLINFO_PRETRANSFER_TIME(3)\fP
-.IP CURLINFO_PRETRANSFER_TIME_T
-Time from start until just before the transfer begins.
-See \fICURLINFO_PRETRANSFER_TIME_T(3)\fP
-.IP CURLINFO_STARTTRANSFER_TIME
-Time from start until just when the first byte is received.
-See \fICURLINFO_STARTTRANSFER_TIME(3)\fP
-.IP CURLINFO_STARTTRANSFER_TIME_T
-Time from start until just when the first byte is received.
-See \fICURLINFO_STARTTRANSFER_TIME_T(3)\fP
-.IP CURLINFO_REDIRECT_TIME
-Time taken for all redirect steps before the final transfer.
-See \fICURLINFO_REDIRECT_TIME(3)\fP
-.IP CURLINFO_REDIRECT_TIME_T
-Time taken for all redirect steps before the final transfer.
-See \fICURLINFO_REDIRECT_TIME_T(3)\fP
-.IP CURLINFO_REDIRECT_COUNT
-Total number of redirects that were followed.
-See \fICURLINFO_REDIRECT_COUNT(3)\fP
-.IP CURLINFO_REDIRECT_URL
-URL a redirect would take you to, had you enabled redirects.
-See \fICURLINFO_REDIRECT_URL(3)\fP
-.IP CURLINFO_SIZE_UPLOAD
-(Deprecated) Number of bytes uploaded.
-See \fICURLINFO_SIZE_UPLOAD(3)\fP
-.IP CURLINFO_SIZE_UPLOAD_T
-Number of bytes uploaded.
-See \fICURLINFO_SIZE_UPLOAD_T(3)\fP
-.IP CURLINFO_SIZE_DOWNLOAD
-(Deprecated) Number of bytes downloaded.
-See \fICURLINFO_SIZE_DOWNLOAD(3)\fP
-.IP CURLINFO_SIZE_DOWNLOAD_T
-Number of bytes downloaded.
-See \fICURLINFO_SIZE_DOWNLOAD_T(3)\fP
-.IP CURLINFO_SPEED_DOWNLOAD
-(Deprecated) Average download speed.
-See \fICURLINFO_SPEED_DOWNLOAD(3)\fP
-.IP CURLINFO_SPEED_DOWNLOAD_T
-Average download speed.
-See \fICURLINFO_SPEED_DOWNLOAD_T(3)\fP
-.IP CURLINFO_SPEED_UPLOAD
-(Deprecated) Average upload speed.
-See \fICURLINFO_SPEED_UPLOAD(3)\fP
-.IP CURLINFO_SPEED_UPLOAD_T
-Average upload speed.
-See \fICURLINFO_SPEED_UPLOAD_T(3)\fP
-.IP CURLINFO_HEADER_SIZE
-Number of bytes of all headers received.
-See \fICURLINFO_HEADER_SIZE(3)\fP
-.IP CURLINFO_REQUEST_SIZE
-Number of bytes sent in the issued HTTP requests.
-See \fICURLINFO_REQUEST_SIZE(3)\fP
-.IP CURLINFO_SSL_VERIFYRESULT
-Certificate verification result.
-See \fICURLINFO_SSL_VERIFYRESULT(3)\fP
-.IP CURLINFO_PROXY_ERROR
-Detailed proxy error.
-See \fICURLINFO_PROXY_ERROR(3)\fP
-.IP CURLINFO_PROXY_SSL_VERIFYRESULT
-Proxy certificate verification result.
-See \fICURLINFO_PROXY_SSL_VERIFYRESULT(3)\fP
-.IP CURLINFO_SSL_ENGINES
-A list of OpenSSL crypto engines.
-See \fICURLINFO_SSL_ENGINES(3)\fP
-.IP CURLINFO_CONTENT_LENGTH_DOWNLOAD
-(Deprecated) Content length from the Content-Length header.
-See \fICURLINFO_CONTENT_LENGTH_DOWNLOAD(3)\fP
-.IP CURLINFO_CONTENT_LENGTH_DOWNLOAD_T
-Content length from the Content-Length header.
-See \fICURLINFO_CONTENT_LENGTH_DOWNLOAD_T(3)\fP
-.IP CURLINFO_CONTENT_LENGTH_UPLOAD
-(Deprecated) Upload size. See \fICURLINFO_CONTENT_LENGTH_UPLOAD(3)\fP
-.IP CURLINFO_CONTENT_LENGTH_UPLOAD_T
-Upload size. See \fICURLINFO_CONTENT_LENGTH_UPLOAD_T(3)\fP
-.IP CURLINFO_CONTENT_TYPE
-Content type from the Content-Type header.
-See \fICURLINFO_CONTENT_TYPE(3)\fP
-.IP CURLINFO_RETRY_AFTER
-The value from the Retry-After header.
-See \fICURLINFO_RETRY_AFTER(3)\fP
-.IP CURLINFO_PRIVATE
-User's private data pointer.
-See \fICURLINFO_PRIVATE(3)\fP
-.IP CURLINFO_HTTPAUTH_AVAIL
-Available HTTP authentication methods.
-See \fICURLINFO_HTTPAUTH_AVAIL(3)\fP
-.IP CURLINFO_PROXYAUTH_AVAIL
-Available HTTP proxy authentication methods.
-See \fICURLINFO_PROXYAUTH_AVAIL(3)\fP
-.IP CURLINFO_OS_ERRNO
-The errno from the last failure to connect.
-See \fICURLINFO_OS_ERRNO(3)\fP
-.IP CURLINFO_NUM_CONNECTS
-Number of new successful connections used for previous transfer.
-See \fICURLINFO_NUM_CONNECTS(3)\fP
-.IP CURLINFO_PRIMARY_IP
-IP address of the last connection.
-See \fICURLINFO_PRIMARY_IP(3)\fP
-.IP CURLINFO_PRIMARY_PORT
-Port of the last connection.
-See \fICURLINFO_PRIMARY_PORT(3)\fP
-.IP CURLINFO_LOCAL_IP
-Local-end IP address of last connection.
-See \fICURLINFO_LOCAL_IP(3)\fP
-.IP CURLINFO_LOCAL_PORT
-Local-end port of last connection.
-See \fICURLINFO_LOCAL_PORT(3)\fP
-.IP CURLINFO_COOKIELIST
-List of all known cookies.
-See \fICURLINFO_COOKIELIST(3)\fP
-.IP CURLINFO_LASTSOCKET
-(Deprecated) Last socket used.
-See \fICURLINFO_LASTSOCKET(3)\fP
-.IP CURLINFO_ACTIVESOCKET
-The session's active socket.
-See \fICURLINFO_ACTIVESOCKET(3)\fP
-.IP CURLINFO_FTP_ENTRY_PATH
-The entry path after logging in to an FTP server.
-See \fICURLINFO_FTP_ENTRY_PATH(3)\fP
-.IP CURLINFO_CAPATH
-Get the default value for \fICURLOPT_CAPATH(3)\fP.
-See \fICURLINFO_CAPATH(3)\fP
-.IP CURLINFO_CAINFO
-Get the default value for \fICURLOPT_CAINFO(3)\fP.
-See \fICURLINFO_CAINFO(3)\fP
-.IP CURLINFO_CERTINFO
-Certificate chain.
-See \fICURLINFO_CERTINFO(3)\fP
-.IP CURLINFO_TLS_SSL_PTR
-TLS session info that can be used for further processing.
-See \fICURLINFO_TLS_SSL_PTR(3)\fP
-.IP CURLINFO_TLS_SESSION
-TLS session info that can be used for further processing. See
-\fICURLINFO_TLS_SESSION(3)\fP. Deprecated option, use
-\fICURLINFO_TLS_SSL_PTR(3)\fP instead!
-.IP CURLINFO_CONDITION_UNMET
-Whether or not a time conditional was met or 304 HTTP response.
-See \fICURLINFO_CONDITION_UNMET(3)\fP
-.IP CURLINFO_RTSP_SESSION_ID
-RTSP session ID.
-See \fICURLINFO_RTSP_SESSION_ID(3)\fP
-.IP CURLINFO_RTSP_CLIENT_CSEQ
-The RTSP client CSeq that is expected next.
-See \fICURLINFO_RTSP_CLIENT_CSEQ(3)\fP
-.IP CURLINFO_RTSP_SERVER_CSEQ
-The RTSP server CSeq that is expected next.
-See \fICURLINFO_RTSP_SERVER_CSEQ(3)\fP
-.IP CURLINFO_RTSP_CSEQ_RECV
-RTSP CSeq last received.
-See \fICURLINFO_RTSP_CSEQ_RECV(3)\fP
-.IP CURLINFO_PROTOCOL
-(Deprecated) The protocol used for the connection. (Added in 7.52.0)
-See \fICURLINFO_PROTOCOL(3)\fP
-.IP CURLINFO_SCHEME
-The scheme used for the connection. (Added in 7.52.0)
-See \fICURLINFO_SCHEME(3)\fP
-.IP CURLINFO_CONN_ID
-The ID of the last connection used by the transfer. (Added in 8.2.0)
-See \fICURLINFO_CONN_ID(3)\fP
-.IP CURLINFO_XFER_ID
-The ID of the transfer. (Added in 8.2.0)
-See \fICURLINFO_XFER_ID(3)\fP
-.SH TIMES
-An overview of the six time values available from \fIcurl_easy_getinfo(3)\fP
-.nf
-
-curl_easy_perform()
- |
- |--NAMELOOKUP
- |--|--CONNECT
- |--|--|--APPCONNECT
- |--|--|--|--PRETRANSFER
- |--|--|--|--|--STARTTRANSFER
- |--|--|--|--|--|--TOTAL
- |--|--|--|--|--|--REDIRECT
-.fi
-.IP NAMELOOKUP
-\fICURLINFO_NAMELOOKUP_TIME(3)\fP and \fICURLINFO_NAMELOOKUP_TIME_T(3)\fP.
-The time it took from the start until the name resolving was completed.
-.IP CONNECT
-\fICURLINFO_CONNECT_TIME(3)\fP and \fICURLINFO_CONNECT_TIME_T(3)\fP. The time
-it took from the start until the connect to the remote host (or proxy) was
-completed.
-.IP APPCONNECT
-\fICURLINFO_APPCONNECT_TIME(3)\fP and \fICURLINFO_APPCONNECT_TIME_T(3)\fP.
-The time it took from the start until the SSL connect/handshake with the
-remote host was completed. (Added in 7.19.0) The latter is the integer version
-(measuring microseconds). (Added in 7.60.0)
-.IP PRETRANSFER
-\fICURLINFO_PRETRANSFER_TIME(3)\fP and \fICURLINFO_PRETRANSFER_TIME_T(3)\fP.
-The time it took from the start until the file transfer is just about to
-begin. This includes all pre-transfer commands and negotiations that are
-specific to the particular protocol(s) involved.
-.IP STARTTRANSFER
-\fICURLINFO_STARTTRANSFER_TIME(3)\fP and
-\fICURLINFO_STARTTRANSFER_TIME_T(3)\fP. The time it took from the start until
-the first byte is received by libcurl.
-.IP TOTAL
-\fICURLINFO_TOTAL_TIME(3)\fP and \fICURLINFO_TOTAL_TIME_T(3)\fP. Total time
-of the previous request.
-.IP REDIRECT
-\fICURLINFO_REDIRECT_TIME(3)\fP and \fICURLINFO_REDIRECT_TIME_T(3)\fP. The
-time it took for all redirection steps include name lookup, connect,
-pretransfer and transfer before final transaction was started. So, this is
-zero if no redirection took place.
-.SH EXAMPLE
-.nf
- curl = curl_easy_init();
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
- res = curl_easy_perform(curl);
-
- if(CURLE_OK == res) {
- char *ct;
- /* ask for the content-type */
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
-
- if((CURLE_OK == res) && ct)
- printf("We received Content-Type: %s\\n", ct);
- }
-
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
-.fi
-.SH AVAILABILITY
-Added in 7.4.1
-.SH RETURN VALUE
-If the operation was successful, CURLE_OK is returned. Otherwise an
-appropriate error code is returned.
-.SH "SEE ALSO"
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/curl_easy_getinfo.md b/docs/libcurl/curl_easy_getinfo.md
new file mode 100644
index 000000000..3b98ea4eb
--- /dev/null
+++ b/docs/libcurl/curl_easy_getinfo.md
@@ -0,0 +1,483 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_getinfo
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+curl_easy_getinfo - extract information from a curl handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );
+~~~
+
+# DESCRIPTION
+
+Get the *info* kept in the *curl* handle. The third argument **MUST** be
+pointing to the specific type of the used option which is documented in each
+man page of the *info* option. The data is stored accordingly and can be
+relied upon only if this function returns CURLE_OK. Use this function after a
+performed transfer if you want to get transfer related data.
+
+You should not free the memory returned by this function unless it is
+explicitly mentioned below.
+
+# AVAILABLE INFORMATION
+
+The following information can be extracted:
+
+## CURLINFO_EFFECTIVE_METHOD
+
+Last used HTTP method. See CURLINFO_EFFECTIVE_METHOD(3)
+
+## CURLINFO_EFFECTIVE_URL
+
+Last used URL. See CURLINFO_EFFECTIVE_URL(3)
+
+## CURLINFO_RESPONSE_CODE
+
+Last received response code. See CURLINFO_RESPONSE_CODE(3)
+
+## CURLINFO_REFERER
+
+Referrer header. See CURLINFO_REFERER(3)
+
+## CURLINFO_HTTP_CONNECTCODE
+
+Last proxy CONNECT response code. See CURLINFO_HTTP_CONNECTCODE(3)
+
+## CURLINFO_HTTP_VERSION
+
+The http version used in the connection. See CURLINFO_HTTP_VERSION(3)
+
+## CURLINFO_FILETIME
+
+Remote time of the retrieved document. See CURLINFO_FILETIME(3)
+
+## CURLINFO_FILETIME_T
+
+Remote time of the retrieved document. See CURLINFO_FILETIME_T(3)
+
+## CURLINFO_TOTAL_TIME
+
+Total time of previous transfer. See CURLINFO_TOTAL_TIME(3)
+
+## CURLINFO_TOTAL_TIME_T
+
+Total time of previous transfer. See CURLINFO_TOTAL_TIME_T(3)
+
+## CURLINFO_NAMELOOKUP_TIME
+
+Time from start until name resolving completed. See
+CURLINFO_NAMELOOKUP_TIME(3)
+
+## CURLINFO_NAMELOOKUP_TIME_T
+
+Time from start until name resolving completed. See
+CURLINFO_NAMELOOKUP_TIME_T(3)
+
+## CURLINFO_CONNECT_TIME
+
+Time from start until remote host or proxy completed.
+See CURLINFO_CONNECT_TIME(3)
+
+## CURLINFO_CONNECT_TIME_T
+
+Time from start until remote host or proxy completed.
+See CURLINFO_CONNECT_TIME_T(3)
+
+## CURLINFO_APPCONNECT_TIME
+
+Time from start until SSL/SSH handshake completed.
+See CURLINFO_APPCONNECT_TIME(3)
+
+## CURLINFO_APPCONNECT_TIME_T
+
+Time from start until SSL/SSH handshake completed.
+See CURLINFO_APPCONNECT_TIME_T(3)
+
+## CURLINFO_PRETRANSFER_TIME
+
+Time from start until just before the transfer begins.
+See CURLINFO_PRETRANSFER_TIME(3)
+
+## CURLINFO_PRETRANSFER_TIME_T
+
+Time from start until just before the transfer begins.
+See CURLINFO_PRETRANSFER_TIME_T(3)
+
+## CURLINFO_QUEUE_TIME_T
+
+Time during which this transfer was held in a waiting queue.
+See CURLINFO_QUEUE_TIME_T(3)
+
+## CURLINFO_STARTTRANSFER_TIME
+
+Time from start until just when the first byte is received.
+See CURLINFO_STARTTRANSFER_TIME(3)
+
+## CURLINFO_STARTTRANSFER_TIME_T
+
+Time from start until just when the first byte is received.
+See CURLINFO_STARTTRANSFER_TIME_T(3)
+
+## CURLINFO_REDIRECT_TIME
+
+Time taken for all redirect steps before the final transfer.
+See CURLINFO_REDIRECT_TIME(3)
+
+## CURLINFO_REDIRECT_TIME_T
+
+Time taken for all redirect steps before the final transfer.
+See CURLINFO_REDIRECT_TIME_T(3)
+
+## CURLINFO_REDIRECT_COUNT
+
+Total number of redirects that were followed.
+See CURLINFO_REDIRECT_COUNT(3)
+
+## CURLINFO_REDIRECT_URL
+
+URL a redirect would take you to, had you enabled redirects.
+See CURLINFO_REDIRECT_URL(3)
+
+## CURLINFO_SIZE_UPLOAD
+
+(Deprecated) Number of bytes uploaded.
+See CURLINFO_SIZE_UPLOAD(3)
+
+## CURLINFO_SIZE_UPLOAD_T
+
+Number of bytes uploaded.
+See CURLINFO_SIZE_UPLOAD_T(3)
+
+## CURLINFO_SIZE_DOWNLOAD
+
+(Deprecated) Number of bytes downloaded.
+See CURLINFO_SIZE_DOWNLOAD(3)
+
+## CURLINFO_SIZE_DOWNLOAD_T
+
+Number of bytes downloaded.
+See CURLINFO_SIZE_DOWNLOAD_T(3)
+
+## CURLINFO_SPEED_DOWNLOAD
+
+(Deprecated) Average download speed.
+See CURLINFO_SPEED_DOWNLOAD(3)
+
+## CURLINFO_SPEED_DOWNLOAD_T
+
+Average download speed.
+See CURLINFO_SPEED_DOWNLOAD_T(3)
+
+## CURLINFO_SPEED_UPLOAD
+
+(Deprecated) Average upload speed.
+See CURLINFO_SPEED_UPLOAD(3)
+
+## CURLINFO_SPEED_UPLOAD_T
+
+Average upload speed.
+See CURLINFO_SPEED_UPLOAD_T(3)
+
+## CURLINFO_HEADER_SIZE
+
+Number of bytes of all headers received.
+See CURLINFO_HEADER_SIZE(3)
+
+## CURLINFO_REQUEST_SIZE
+
+Number of bytes sent in the issued HTTP requests.
+See CURLINFO_REQUEST_SIZE(3)
+
+## CURLINFO_SSL_VERIFYRESULT
+
+Certificate verification result.
+See CURLINFO_SSL_VERIFYRESULT(3)
+
+## CURLINFO_PROXY_ERROR
+
+Detailed proxy error.
+See CURLINFO_PROXY_ERROR(3)
+
+## CURLINFO_PROXY_SSL_VERIFYRESULT
+
+Proxy certificate verification result.
+See CURLINFO_PROXY_SSL_VERIFYRESULT(3)
+
+## CURLINFO_SSL_ENGINES
+
+A list of OpenSSL crypto engines.
+See CURLINFO_SSL_ENGINES(3)
+
+## CURLINFO_CONTENT_LENGTH_DOWNLOAD
+
+(Deprecated) Content length from the Content-Length header.
+See CURLINFO_CONTENT_LENGTH_DOWNLOAD(3)
+
+## CURLINFO_CONTENT_LENGTH_DOWNLOAD_T
+
+Content length from the Content-Length header.
+See CURLINFO_CONTENT_LENGTH_DOWNLOAD_T(3)
+
+## CURLINFO_CONTENT_LENGTH_UPLOAD
+
+(Deprecated) Upload size. See CURLINFO_CONTENT_LENGTH_UPLOAD(3)
+
+## CURLINFO_CONTENT_LENGTH_UPLOAD_T
+
+Upload size. See CURLINFO_CONTENT_LENGTH_UPLOAD_T(3)
+
+## CURLINFO_CONTENT_TYPE
+
+Content type from the Content-Type header.
+See CURLINFO_CONTENT_TYPE(3)
+
+## CURLINFO_RETRY_AFTER
+
+The value from the Retry-After header.
+See CURLINFO_RETRY_AFTER(3)
+
+## CURLINFO_PRIVATE
+
+User's private data pointer.
+See CURLINFO_PRIVATE(3)
+
+## CURLINFO_HTTPAUTH_AVAIL
+
+Available HTTP authentication methods.
+See CURLINFO_HTTPAUTH_AVAIL(3)
+
+## CURLINFO_PROXYAUTH_AVAIL
+
+Available HTTP proxy authentication methods.
+See CURLINFO_PROXYAUTH_AVAIL(3)
+
+## CURLINFO_OS_ERRNO
+
+The errno from the last failure to connect.
+See CURLINFO_OS_ERRNO(3)
+
+## CURLINFO_NUM_CONNECTS
+
+Number of new successful connections used for previous transfer.
+See CURLINFO_NUM_CONNECTS(3)
+
+## CURLINFO_PRIMARY_IP
+
+Destination IP address of the last connection.
+See CURLINFO_PRIMARY_IP(3)
+
+## CURLINFO_PRIMARY_PORT
+
+Destination port of the last connection.
+See CURLINFO_PRIMARY_PORT(3)
+
+## CURLINFO_LOCAL_IP
+
+Source IP address of the last connection.
+See CURLINFO_LOCAL_IP(3)
+
+## CURLINFO_LOCAL_PORT
+
+Source port number of the last connection.
+See CURLINFO_LOCAL_PORT(3)
+
+## CURLINFO_COOKIELIST
+
+List of all known cookies.
+See CURLINFO_COOKIELIST(3)
+
+## CURLINFO_LASTSOCKET
+
+(Deprecated) Last socket used.
+See CURLINFO_LASTSOCKET(3)
+
+## CURLINFO_ACTIVESOCKET
+
+The session's active socket.
+See CURLINFO_ACTIVESOCKET(3)
+
+## CURLINFO_FTP_ENTRY_PATH
+
+The entry path after logging in to an FTP server.
+See CURLINFO_FTP_ENTRY_PATH(3)
+
+## CURLINFO_CAPATH
+
+Get the default value for CURLOPT_CAPATH(3).
+See CURLINFO_CAPATH(3)
+
+## CURLINFO_CAINFO
+
+Get the default value for CURLOPT_CAINFO(3).
+See CURLINFO_CAINFO(3)
+
+## CURLINFO_CERTINFO
+
+Certificate chain.
+See CURLINFO_CERTINFO(3)
+
+## CURLINFO_TLS_SSL_PTR
+
+TLS session info that can be used for further processing.
+See CURLINFO_TLS_SSL_PTR(3)
+
+## CURLINFO_TLS_SESSION
+
+TLS session info that can be used for further processing. See
+CURLINFO_TLS_SESSION(3). Deprecated option, use
+CURLINFO_TLS_SSL_PTR(3) instead!
+
+## CURLINFO_CONDITION_UNMET
+
+Whether or not a time conditional was met or 304 HTTP response.
+See CURLINFO_CONDITION_UNMET(3)
+
+## CURLINFO_RTSP_SESSION_ID
+
+RTSP session ID.
+See CURLINFO_RTSP_SESSION_ID(3)
+
+## CURLINFO_RTSP_CLIENT_CSEQ
+
+The RTSP client CSeq that is expected next.
+See CURLINFO_RTSP_CLIENT_CSEQ(3)
+
+## CURLINFO_RTSP_SERVER_CSEQ
+
+The RTSP server CSeq that is expected next.
+See CURLINFO_RTSP_SERVER_CSEQ(3)
+
+## CURLINFO_RTSP_CSEQ_RECV
+
+RTSP CSeq last received.
+See CURLINFO_RTSP_CSEQ_RECV(3)
+
+## CURLINFO_PROTOCOL
+
+(Deprecated) The protocol used for the connection. (Added in 7.52.0)
+See CURLINFO_PROTOCOL(3)
+
+## CURLINFO_SCHEME
+
+The scheme used for the connection. (Added in 7.52.0)
+See CURLINFO_SCHEME(3)
+
+## CURLINFO_CONN_ID
+
+The ID of the last connection used by the transfer. (Added in 8.2.0)
+See CURLINFO_CONN_ID(3)
+
+## CURLINFO_XFER_ID
+
+The ID of the transfer. (Added in 8.2.0)
+See CURLINFO_XFER_ID(3)
+
+# TIMES
+
+An overview of the time values available from curl_easy_getinfo(3)
+
+~~~
+curl_easy_perform()
+ |
+ |--QUEUE_TIME
+ |--|--NAMELOOKUP
+ |--|--|--CONNECT
+ |--|--|--|--APPCONNECT
+ |--|--|--|--|--PRETRANSFER
+ |--|--|--|--|--|--STARTTRANSFER
+ |--|--|--|--|--|--|--TOTAL
+ |--|--|--|--|--|--|--REDIRECT
+~~~
+
+## QUEUE_TIME
+
+CURLINFO_QUEUE_TIME_T(3). The time during which the transfer was held in a
+waiting queue before it could start for real. (Added in 8.6.0)
+
+## NAMELOOKUP
+
+CURLINFO_NAMELOOKUP_TIME(3) and CURLINFO_NAMELOOKUP_TIME_T(3). The time it
+took from the start until the name resolving was completed.
+
+## CONNECT
+
+CURLINFO_CONNECT_TIME(3) and CURLINFO_CONNECT_TIME_T(3). The time it took from
+the start until the connect to the remote host (or proxy) was completed.
+
+## APPCONNECT
+
+CURLINFO_APPCONNECT_TIME(3) and CURLINFO_APPCONNECT_TIME_T(3). The time it
+took from the start until the SSL connect/handshake with the remote host was
+completed. (Added in 7.19.0) The latter is the integer version (measuring
+microseconds). (Added in 7.60.0)
+
+## PRETRANSFER
+
+CURLINFO_PRETRANSFER_TIME(3) and CURLINFO_PRETRANSFER_TIME_T(3). The time it
+took from the start until the file transfer is just about to begin. This
+includes all pre-transfer commands and negotiations that are specific to the
+particular protocol(s) involved.
+
+## STARTTRANSFER
+
+CURLINFO_STARTTRANSFER_TIME(3) and CURLINFO_STARTTRANSFER_TIME_T(3). The time
+it took from the start until the first byte is received by libcurl.
+
+## TOTAL
+
+CURLINFO_TOTAL_TIME(3) and CURLINFO_TOTAL_TIME_T(3). Total time
+of the previous request.
+
+## REDIRECT
+
+CURLINFO_REDIRECT_TIME(3) and CURLINFO_REDIRECT_TIME_T(3). The time it took
+for all redirection steps include name lookup, connect, pretransfer and
+transfer before final transaction was started. So, this is zero if no
+redirection took place.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
+ res = curl_easy_perform(curl);
+
+ if(CURLE_OK == res) {
+ char *ct;
+ /* ask for the content-type */
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
+
+ if((CURLE_OK == res) && ct)
+ printf("We received Content-Type: %s\n", ct);
+ }
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1
+
+# RETURN VALUE
+
+If the operation was successful, CURLE_OK is returned. Otherwise an
+appropriate error code is returned.
diff --git a/docs/libcurl/curl_easy_header.3 b/docs/libcurl/curl_easy_header.3
deleted file mode 100644
index 3aa62649e..000000000
--- a/docs/libcurl/curl_easy_header.3
+++ /dev/null
@@ -1,142 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_header 3 "13 March 2022" "libcurl" "libcurl"
-.SH NAME
-curl_easy_header - get an HTTP header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLHcode curl_easy_header(CURL *easy,
- const char *name,
- size_t index,
- unsigned int origin,
- int request,
- struct curl_header **hout);
-.SH DESCRIPTION
-\fIcurl_easy_header(3)\fP returns a pointer to a "curl_header" struct in
-\fBhout\fP with data for the HTTP response header \fIname\fP. The case
-insensitive null-terminated header name should be specified without colon.
-
-\fIindex\fP 0 means asking for the first instance of the header. If the
-returned header struct has \fBamount\fP set larger than 1, it means there are
-more instances of the same header name available to get. Asking for a too big
-index makes \fBCURLHE_BADINDEX\fP get returned.
-
-The \fIorigin\fP argument is for specifying which headers to receive, as a
-single HTTP transfer might provide headers from several different places and
-they may then have different importance to the user and headers using the same
-name might be used. The \fIorigin\fP is a bitmask for what header sources you
-want. See the descriptions below.
-
-The \fIrequest\fP argument tells libcurl from which request you want headers
-from. A single transfer might consist of a series of HTTP requests and this
-argument lets you specify which particular individual request you want the
-headers from. 0 being the first request and then the number increases for
-further redirects or when multi-state authentication is used. Passing in -1 is
-a shortcut to "the last" request in the series, independently of the actual
-amount of requests used.
-
-libcurl stores and provides the actually used "correct" headers. If for
-example two headers with the same name arrive and the latter overrides the
-former, then only the latter is provided. If the first header survives the
-second, then only the first one is provided. An application using this API
-does not have to bother about multiple headers used wrongly.
-
-The memory for the returned struct is associated with the easy handle and
-subsequent calls to \fIcurl_easy_header(3)\fP clobbers the struct used in the
-previous calls for the same easy handle. Applications need to copy the data if
-it wants to keep it around. The memory used for the struct gets freed with
-calling \fIcurl_easy_cleanup(3)\fP of the easy handle.
-
-The first line in an HTTP response is called the status line. It is not
-considered a header by this function. Headers are the "name: value" lines
-following the status.
-
-This function can be used before (all) headers have been received and is fine
-to call from within libcurl callbacks. It returns the state of the headers at
-the time it is called.
-.SH "The header struct"
-.nf
-struct curl_header {
- char *name;
- char *value;
- size_t amount;
- size_t index;
- unsigned int origin;
- void *anchor;
-};
-.fi
-
-The data \fBname\fP field points to, is the same as the requested name, but
-might have a different case.
-
-The data \fBvalue\fP field points to, comes exactly as delivered over the
-network but with leading and trailing whitespace and newlines stripped
-off. The `value` data is null-terminated. For legacy HTTP/1 "folded headers",
-this API provides the full single value in an unfolded manner with a single
-whitespace between the lines.
-
-\fBamount\fP is how many headers using this name that exist, within the origin
-and request scope asked for.
-
-\fBindex\fP is the zero based entry number of this particular header, which in
-case this header was used more than once in the requested scope can be larger
-than 0 but is always less than \fBamount\fP.
-
-The \fBorigin\fP field in the "curl_header" struct has one of the origin bits
-set, indicating where from the header originates. At the time of this writing,
-there are 5 bits with defined use. The undocumented 27 remaining bits are
-reserved for future use and must not be assumed to have any particular value.
-
-\fBanchor\fP is a private handle used by libcurl internals. Do not modify.
-.SH ORIGINS
-.IP CURLH_HEADER
-The header arrived as a header from the server.
-.IP CURLH_TRAILER
-The header arrived as a trailer. A header that arrives after the body.
-.IP CURLH_CONNECT
-The header arrived in a CONNECT response. A CONNECT request is being done to
-setup a transfer "through" an HTTP(S) proxy.
-.IP CURLH_1XX
-The header arrived in an HTTP 1xx response. A 1xx response is an "intermediate"
-response that might happen before the "real" response.
-.IP CURLH_PSEUDO
-The header is an HTTP/2 or HTTP/3 pseudo header
-.SH EXAMPLE
-.nf
-struct curl_header *type;
-CURLHcode h =
- curl_easy_header(easy, "Content-Type", 0, CURLH_HEADER, -1, &type);
-.fi
-.SH AVAILABILITY
-Added in 7.83.0. Officially supported since 7.84.0.
-.SH RETURN VALUE
-This function returns a CURLHcode indicating success or error.
-.SH "SEE ALSO"
-.BR curl_easy_nextheader (3),
-.BR curl_easy_perform (3),
-.BR CURLINFO_CONTENT_TYPE (3),
-.BR CURLOPT_HEADERFUNCTION (3),
-.BR libcurl-errors (3)
diff --git a/docs/libcurl/curl_easy_header.md b/docs/libcurl/curl_easy_header.md
new file mode 100644
index 000000000..9c2d76cea
--- /dev/null
+++ b/docs/libcurl/curl_easy_header.md
@@ -0,0 +1,160 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_header
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONTENT_TYPE (3)
+ - CURLOPT_HEADERFUNCTION (3)
+ - curl_easy_nextheader (3)
+ - curl_easy_perform (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+curl_easy_header - get an HTTP header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLHcode curl_easy_header(CURL *easy,
+ const char *name,
+ size_t index,
+ unsigned int origin,
+ int request,
+ struct curl_header **hout);
+~~~
+
+# DESCRIPTION
+
+curl_easy_header(3) returns a pointer to a "curl_header" struct in **hout**
+with data for the HTTP response header *name*. The case insensitive
+null-terminated header name should be specified without colon.
+
+*index* 0 means asking for the first instance of the header. If the returned
+header struct has **amount** set larger than 1, it means there are more
+instances of the same header name available to get. Asking for a too big index
+makes **CURLHE_BADINDEX** get returned.
+
+The *origin* argument is for specifying which headers to receive, as a single
+HTTP transfer might provide headers from several different places and they may
+then have different importance to the user and headers using the same name
+might be used. The *origin* is a bitmask for what header sources you want. See
+the descriptions below.
+
+The *request* argument tells libcurl from which request you want headers
+from. A single transfer might consist of a series of HTTP requests and this
+argument lets you specify which particular individual request you want the
+headers from. 0 being the first request and then the number increases for
+further redirects or when multi-state authentication is used. Passing in -1 is
+a shortcut to "the last" request in the series, independently of the actual
+amount of requests used.
+
+libcurl stores and provides the actually used "correct" headers. If for
+example two headers with the same name arrive and the latter overrides the
+former, then only the latter is provided. If the first header survives the
+second, then only the first one is provided. An application using this API
+does not have to bother about multiple headers used wrongly.
+
+The memory for the returned struct is associated with the easy handle and
+subsequent calls to curl_easy_header(3) clobber the struct used in the
+previous calls for the same easy handle. Applications need to copy the data if
+it wants to keep it around. The memory used for the struct gets freed with
+calling curl_easy_cleanup(3) of the easy handle.
+
+The first line in an HTTP response is called the status line. It is not
+considered a header by this function. Headers are the "name: value" lines
+following the status.
+
+This function can be used before (all) headers have been received and is fine
+to call from within libcurl callbacks. It returns the state of the headers at
+the time it is called.
+
+# The header struct
+
+~~~c
+struct curl_header {
+ char *name;
+ char *value;
+ size_t amount;
+ size_t index;
+ unsigned int origin;
+ void *anchor;
+};
+~~~
+
+The data **name** field points to, is the same as the requested name, but
+might have a different case.
+
+The data **value** field points to, comes exactly as delivered over the
+network but with leading and trailing whitespace and newlines stripped
+off. The `value` data is null-terminated. For legacy HTTP/1 "folded headers",
+this API provides the full single value in an unfolded manner with a single
+whitespace between the lines.
+
+**amount** is how many headers using this name that exist, within the origin
+and request scope asked for.
+
+**index** is the zero based entry number of this particular header, which in
+case this header was used more than once in the requested scope can be larger
+than 0 but is always less than **amount**.
+
+The **origin** field in the "curl_header" struct has one of the origin bits
+set, indicating where from the header originates. At the time of this writing,
+there are 5 bits with defined use. The undocumented 27 remaining bits are
+reserved for future use and must not be assumed to have any particular value.
+
+**anchor** is a private handle used by libcurl internals. Do not modify.
+
+# ORIGINS
+
+## CURLH_HEADER
+
+The header arrived as a header from the server.
+
+## CURLH_TRAILER
+
+The header arrived as a trailer. A header that arrives after the body.
+
+## CURLH_CONNECT
+
+The header arrived in a CONNECT response. A CONNECT request is being done to
+setup a transfer "through" an HTTP(S) proxy.
+
+## CURLH_1XX
+
+The header arrived in an HTTP 1xx response. A 1xx response is an "intermediate"
+response that might happen before the "real" response.
+
+## CURLH_PSEUDO
+
+The header is an HTTP/2 or HTTP/3 pseudo header
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct curl_header *type;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLHcode h;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_perform(curl);
+ h = curl_easy_header(curl, "Content-Type", 0, CURLH_HEADER, -1, &type);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.83.0. Officially supported since 7.84.0.
+
+# RETURN VALUE
+
+This function returns a CURLHcode indicating success or error.
diff --git a/docs/libcurl/curl_easy_init.3 b/docs/libcurl/curl_easy_init.3
deleted file mode 100644
index 0fd901699..000000000
--- a/docs/libcurl/curl_easy_init.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_init 3 "4 March 2002" "libcurl" "libcurl"
-.SH NAME
-curl_easy_init - Start a libcurl easy session
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURL *curl_easy_init();
-.fi
-.SH DESCRIPTION
-This function allocates and returns a CURL easy handle. Such a handle is used
-as input to other functions in the easy interface. This call must have a
-corresponding call to \fIcurl_easy_cleanup(3)\fP when the operation is
-complete.
-
-The easy handle is used to hold and control a single network transfer. It is
-encouraged to reuse easy handles for repeated transfers.
-
-An alternative way to get a new easy handle is to duplicate an already
-existing one with \fIcurl_easy_duphandle(3)\fP, which has the upside that it
-gets all the options that were set in the source handle set in the new copy as
-well.
-
-If you did not already call \fIcurl_global_init(3)\fP before calling this
-function, \fIcurl_easy_init(3)\fP does it automatically. This may be lethal in
-multi-threaded cases, if \fIcurl_global_init(3)\fP is not thread-safe in your
-system, and it may then result in resource problems because there is no
-corresponding cleanup.
-
-You are strongly advised to not allow this automatic behavior, by calling
-\fIcurl_global_init(3)\fP yourself properly. See the description in
-\fBlibcurl\fP(3) of global environment requirements for details of how to use
-this function.
-
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-If this function returns NULL, something went wrong and you cannot use the
-other curl functions.
-.SH "SEE ALSO"
-.BR curl_easy_cleanup (3),
-.BR curl_easy_duphandle (3),
-.BR curl_easy_perform (3),
-.BR curl_easy_reset (3),
-.BR curl_global_init (3),
-.BR curl_multi_init (3)
diff --git a/docs/libcurl/curl_easy_init.md b/docs/libcurl/curl_easy_init.md
new file mode 100644
index 000000000..a7465547f
--- /dev/null
+++ b/docs/libcurl/curl_easy_init.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_init
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_cleanup (3)
+ - curl_easy_duphandle (3)
+ - curl_easy_perform (3)
+ - curl_easy_reset (3)
+ - curl_global_init (3)
+ - curl_multi_init (3)
+---
+
+# NAME
+
+curl_easy_init - Start a libcurl easy session
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURL *curl_easy_init();
+~~~
+
+# DESCRIPTION
+
+This function allocates and returns a CURL easy handle. Such a handle is used
+as input to other functions in the easy interface. This call must have a
+corresponding call to curl_easy_cleanup(3) when the operation is complete.
+
+The easy handle is used to hold and control a single network transfer. It is
+encouraged to reuse easy handles for repeated transfers.
+
+An alternative way to get a new easy handle is to duplicate an already
+existing one with curl_easy_duphandle(3), which has the upside that it gets
+all the options that were set in the source handle set in the new copy as
+well.
+
+If you did not already call curl_global_init(3) before calling this function,
+curl_easy_init(3) does it automatically. This may be lethal in multi-threaded
+cases, if curl_global_init(3) is not thread-safe in your system, and it may
+then result in resource problems because there is no corresponding cleanup.
+
+You are strongly advised to not allow this automatic behavior, by calling
+curl_global_init(3) yourself properly. See the description in libcurl(3) of
+global environment requirements for details of how to use this function.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+If this function returns NULL, something went wrong and you cannot use the
+other curl functions.
diff --git a/docs/libcurl/curl_easy_nextheader.3 b/docs/libcurl/curl_easy_nextheader.3
deleted file mode 100644
index b704e7643..000000000
--- a/docs/libcurl/curl_easy_nextheader.3
+++ /dev/null
@@ -1,97 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_nextheader 3 "13 March 2022" "libcurl" "libcurl"
-.SH NAME
-curl_easy_nextheader - get the next HTTP header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-struct curl_header *curl_easy_nextheader(CURL *easy,
- unsigned int origin,
- int request,
- struct curl_header *prev);
-.fi
-.SH DESCRIPTION
-This function lets an application iterate over all previously received HTTP
-headers.
-
-The \fIorigin\fP argument is for specifying which headers to receive, as a
-single HTTP transfer might provide headers from several different places and
-they may then have different importance to the user and headers using the same
-name might be used. The \fIorigin\fP is a bitmask for what header sources you
-want. See the \fIcurl_easy_header(3)\fP man page for the origin descriptions.
-
-The \fIrequest\fP argument tells libcurl from which request you want headers
-from. A single transfer might consist of a series of HTTP requests and this
-argument lets you specify which particular individual request you want the
-headers from. 0 being the first request and then the number increases for
-further redirects or when multi-state authentication is used. Passing in -1 is
-a shortcut to "the last" request in the series, independently of the actual
-amount of requests used.
-
-It is suggested that you pass in the same \fBorigin\fP and \fBrequest\fP when
-iterating over a range of headers as changing the value mid-loop might give
-you unexpected results.
-
-If \fIprev\fP is NULL, this function returns a pointer to the first header
-stored within the given scope (origin + request).
-
-If \fIprev\fP is a pointer to a previously returned header struct,
-\fIcurl_easy_nextheader(3)\fP returns a pointer the next header stored within
-the given scope. This way, an application can iterate over all available
-headers.
-
-The memory for the struct this points to, is owned and managed by libcurl and
-is associated with the easy handle. Applications must copy the data if they
-want it to survive subsequent API calls or the life-time of the easy handle.
-.SH EXAMPLE
-.nf
-struct curl_header *prev = NULL;
-struct curl_header *h;
-
-/* extract the normal headers from the first request */
-while((h = curl_easy_nextheader(easy, CURLH_HEADER, 0, prev))) {
- printf("%s: %s\\n", h->name, h->value);
- prev = h;
-}
-
-/* extract the normal headers + 1xx + trailers from the last request */
-unsigned int origin = CURLH_HEADER| CURLH_1XX | CURLH_TRAILER;
-while((h = curl_easy_nextheader(easy, origin, -1, prev))) {
- printf("%s: %s\\n", h->name, h->value);
- prev = h;
-}
-.fi
-.SH AVAILABILITY
-Added in 7.83.0. Officially supported since 7.84.0.
-.SH RETURN VALUE
-This function returns the next header, or NULL when there are no more
-(matching) headers or an error occurred.
-
-If this function returns NULL when \fIprev\fP was set to NULL, then there are
-no headers available within the scope to return.
-.SH "SEE ALSO"
-.BR curl_easy_header (3),
-.BR curl_easy_perform (3)
diff --git a/docs/libcurl/curl_easy_nextheader.md b/docs/libcurl/curl_easy_nextheader.md
new file mode 100644
index 000000000..7c7e151c3
--- /dev/null
+++ b/docs/libcurl/curl_easy_nextheader.md
@@ -0,0 +1,100 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_nextheader
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_header (3)
+ - curl_easy_perform (3)
+---
+
+# NAME
+
+curl_easy_nextheader - get the next HTTP header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+struct curl_header *curl_easy_nextheader(CURL *easy,
+ unsigned int origin,
+ int request,
+ struct curl_header *prev);
+~~~
+
+# DESCRIPTION
+
+This function lets an application iterate over all previously received HTTP
+headers.
+
+The *origin* argument is for specifying which headers to receive, as a single
+HTTP transfer might provide headers from several different places and they may
+then have different importance to the user and headers using the same name
+might be used. The *origin* is a bitmask for what header sources you want. See
+the curl_easy_header(3) man page for the origin descriptions.
+
+The *request* argument tells libcurl from which request you want headers
+from. A single transfer might consist of a series of HTTP requests and this
+argument lets you specify which particular individual request you want the
+headers from. 0 being the first request and then the number increases for
+further redirects or when multi-state authentication is used. Passing in -1 is
+a shortcut to "the last" request in the series, independently of the actual
+amount of requests used.
+
+It is suggested that you pass in the same **origin** and **request** when
+iterating over a range of headers as changing the value mid-loop might give
+you unexpected results.
+
+If *prev* is NULL, this function returns a pointer to the first header stored
+within the given scope (origin + request).
+
+If *prev* is a pointer to a previously returned header struct,
+curl_easy_nextheader(3) returns a pointer the next header stored within the
+given scope. This way, an application can iterate over all available headers.
+
+The memory for the struct this points to, is owned and managed by libcurl and
+is associated with the easy handle. Applications must copy the data if they
+want it to survive subsequent API calls or the life-time of the easy handle.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct curl_header *prev = NULL;
+ struct curl_header *h;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_perform(curl);
+
+ /* extract the normal headers from the first request */
+ while((h = curl_easy_nextheader(curl, CURLH_HEADER, 0, prev))) {
+ printf("%s: %s\n", h->name, h->value);
+ prev = h;
+ }
+
+ /* extract the normal headers + 1xx + trailers from the last request */
+ unsigned int origin = CURLH_HEADER| CURLH_1XX | CURLH_TRAILER;
+ while((h = curl_easy_nextheader(curl, origin, -1, prev))) {
+ printf("%s: %s\n", h->name, h->value);
+ prev = h;
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.83.0. Officially supported since 7.84.0.
+
+# RETURN VALUE
+
+This function returns the next header, or NULL when there are no more
+(matching) headers or an error occurred.
+
+If this function returns NULL when *prev* was set to NULL, then there are no
+headers available within the scope to return.
diff --git a/docs/libcurl/curl_easy_option_by_id.3 b/docs/libcurl/curl_easy_option_by_id.3
deleted file mode 100644
index 3be115182..000000000
--- a/docs/libcurl/curl_easy_option_by_id.3
+++ /dev/null
@@ -1,56 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_option_by_id 3 "27 Aug 2020" "libcurl" "libcurl"
-.SH NAME
-curl_easy_option_by_id - find an easy setopt option by id
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-const struct curl_easyoption *curl_easy_option_by_id(CURLoption id);
-.fi
-.SH DESCRIPTION
-Given a \fICURLoption\fP \fBid\fP, this function returns a pointer to the
-\fIcurl_easyoption\fP struct, holding information about the
-\fIcurl_easy_setopt(3)\fP option using that id. The option id is the CURLOPT_
-prefix ones provided in the standard curl/curl.h header file. This function
-returns the non-alias version of the cases where there is an alias function as
-well.
-
-If libcurl has no option with the given id, this function returns NULL.
-.SH EXAMPLE
-.nf
-const struct curl_easyoption *opt = curl_easy_option_by_id(CURLOPT_URL);
-if(opt) {
- printf("This option wants type %x\\n", opt->type);
-}
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.73.0
-.SH RETURN VALUE
-A pointer to the \fIcurl_easyoption\fP struct for the option or NULL.
-.SH "SEE ALSO"
-.BR curl_easy_option_by_name (3),
-.BR curl_easy_option_next (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/curl_easy_option_by_id.md b/docs/libcurl/curl_easy_option_by_id.md
new file mode 100644
index 000000000..b1d6d421b
--- /dev/null
+++ b/docs/libcurl/curl_easy_option_by_id.md
@@ -0,0 +1,54 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_option_by_id
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_option_by_name (3)
+ - curl_easy_option_next (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+curl_easy_option_by_id - find an easy setopt option by id
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const struct curl_easyoption *curl_easy_option_by_id(CURLoption id);
+~~~
+
+# DESCRIPTION
+
+Given a *CURLoption* **id**, this function returns a pointer to the
+*curl_easyoption* struct, holding information about the
+curl_easy_setopt(3) option using that id. The option id is the CURLOPT_
+prefix ones provided in the standard curl/curl.h header file. This function
+returns the non-alias version of the cases where there is an alias function as
+well.
+
+If libcurl has no option with the given id, this function returns NULL.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ const struct curl_easyoption *opt = curl_easy_option_by_id(CURLOPT_URL);
+ if(opt) {
+ printf("This option wants type %x\n", opt->type);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.73.0
+
+# RETURN VALUE
+
+A pointer to the *curl_easyoption* struct for the option or NULL.
diff --git a/docs/libcurl/curl_easy_option_by_name.3 b/docs/libcurl/curl_easy_option_by_name.3
deleted file mode 100644
index 701587792..000000000
--- a/docs/libcurl/curl_easy_option_by_name.3
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_option_by_name 3 "27 Aug 2020" "libcurl" "libcurl"
-.SH NAME
-curl_easy_option_by_name - find an easy setopt option by name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-const struct curl_easyoption *curl_easy_option_by_name(const char *name);
-.fi
-.SH DESCRIPTION
-Given a \fBname\fP, this function returns a pointer to the
-\fIcurl_easyoption\fP struct, holding information about the
-\fIcurl_easy_setopt(3)\fP option using that name. The name should be specified
-without the "CURLOPT_" prefix and the name comparison is made case
-insensitive.
-
-If libcurl has no option with the given name, this function returns NULL.
-.SH EXAMPLE
-.nf
-const struct curl_easyoption *opt = curl_easy_option_by_name("URL");
-if(opt) {
- printf("This option wants CURLoption %x\\n", (int)opt->id);
-}
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.73.0
-.SH RETURN VALUE
-A pointer to the \fIcurl_easyoption\fP struct for the option or NULL.
-.SH "SEE ALSO"
-.BR curl_easy_option_by_id (3),
-.BR curl_easy_option_next (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/curl_easy_option_by_name.md b/docs/libcurl/curl_easy_option_by_name.md
new file mode 100644
index 000000000..86ccbd4da
--- /dev/null
+++ b/docs/libcurl/curl_easy_option_by_name.md
@@ -0,0 +1,53 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_option_by_name
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_option_by_id (3)
+ - curl_easy_option_next (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+curl_easy_option_by_name - find an easy setopt option by name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const struct curl_easyoption *curl_easy_option_by_name(const char *name);
+~~~
+
+# DESCRIPTION
+
+Given a **name**, this function returns a pointer to the
+*curl_easyoption* struct, holding information about the
+curl_easy_setopt(3) option using that name. The name should be specified
+without the "CURLOPT_" prefix and the name comparison is made case
+insensitive.
+
+If libcurl has no option with the given name, this function returns NULL.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ const struct curl_easyoption *opt = curl_easy_option_by_name("URL");
+ if(opt) {
+ printf("This option wants CURLoption %x\n", (int)opt->id);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.73.0
+
+# RETURN VALUE
+
+A pointer to the *curl_easyoption* struct for the option or NULL.
diff --git a/docs/libcurl/curl_easy_option_next.3 b/docs/libcurl/curl_easy_option_next.3
deleted file mode 100644
index 8109573e1..000000000
--- a/docs/libcurl/curl_easy_option_next.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_option_next 3 "27 Aug 2020" "libcurl" "libcurl"
-.SH NAME
-curl_easy_option_next - iterate over easy setopt options
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef enum {
- CURLOT_LONG, /* long (a range of values) */
- CURLOT_VALUES, /* (a defined set or bitmask) */
- CURLOT_OFF_T, /* curl_off_t (a range of values) */
- CURLOT_OBJECT, /* pointer (void *) */
- CURLOT_STRING, /* (char * to null-terminated buffer) */
- CURLOT_SLIST, /* (struct curl_slist *) */
- CURLOT_CBPTR, /* (void * passed as-is to a callback) */
- CURLOT_BLOB, /* blob (struct curl_blob *) */
- CURLOT_FUNCTION /* function pointer */
-} curl_easytype;
-
-/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
- to use for curl_easy_setopt() for the given id */
-struct curl_easyoption {
- const char *name;
- CURLoption id;
- curl_easytype type;
- unsigned int flags;
-};
-
-const struct curl_easyoption *
-curl_easy_option_next(const struct curl_easyoption *prev);
-.fi
-.SH DESCRIPTION
-This function returns a pointer to the first or the next \fIcurl_easyoption\fP
-struct, providing an ability to iterate over all known options for
-\fIcurl_easy_setopt(3)\fP in this instance of libcurl.
-
-Pass a \fBNULL\fP argument as \fBprev\fP to get the first option returned, or
-pass in the current option to get the next one returned. If there is no more
-option to return, \fIcurl_easy_option_next(3)\fP returns NULL.
-
-The options returned by this functions are the ones known to this libcurl and
-information about what argument type they want.
-
-If the \fBCURLOT_FLAG_ALIAS\fP bit is set in the flags field, it means the
-name is provided for backwards compatibility as an alias.
-.SH EXAMPLE
-.nf
-/* iterate over all available options */
-const struct curl_easyoption *opt;
-opt = curl_easy_option_by_next(NULL);
-while(opt) {
- printf("Name: %s\\n", opt->name);
- opt = curl_easy_option_by_next(opt);
-}
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.73.0
-.SH RETURN VALUE
-A pointer to the \fIcurl_easyoption\fP struct for the next option or NULL if
-no more options.
-.SH "SEE ALSO"
-.BR curl_easy_option_by_id (3),
-.BR curl_easy_option_by_name (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/curl_easy_option_next.md b/docs/libcurl/curl_easy_option_next.md
new file mode 100644
index 000000000..f5da17cfc
--- /dev/null
+++ b/docs/libcurl/curl_easy_option_next.md
@@ -0,0 +1,89 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_option_next
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_option_by_id (3)
+ - curl_easy_option_by_name (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+curl_easy_option_next - iterate over easy setopt options
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const struct curl_easyoption *
+curl_easy_option_next(const struct curl_easyoption *prev);
+~~~
+
+# DESCRIPTION
+
+This function returns a pointer to the first or the next *curl_easyoption*
+struct, providing an ability to iterate over all known options for
+curl_easy_setopt(3) in this instance of libcurl.
+
+Pass a **NULL** argument as **prev** to get the first option returned, or
+pass in the current option to get the next one returned. If there is no more
+option to return, curl_easy_option_next(3) returns NULL.
+
+The options returned by this functions are the ones known to this libcurl and
+information about what argument type they want.
+
+If the **CURLOT_FLAG_ALIAS** bit is set in the flags field, it means the
+name is provided for backwards compatibility as an alias.
+
+# struct
+
+~~~c
+typedef enum {
+ CURLOT_LONG, /* long (a range of values) */
+ CURLOT_VALUES, /* (a defined set or bitmask) */
+ CURLOT_OFF_T, /* curl_off_t (a range of values) */
+ CURLOT_OBJECT, /* pointer (void *) */
+ CURLOT_STRING, /* (char * to null-terminated buffer) */
+ CURLOT_SLIST, /* (struct curl_slist *) */
+ CURLOT_CBPTR, /* (void * passed as-is to a callback) */
+ CURLOT_BLOB, /* blob (struct curl_blob *) */
+ CURLOT_FUNCTION /* function pointer */
+} curl_easytype;
+
+/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
+ to use for curl_easy_setopt() for the given id */
+struct curl_easyoption {
+ const char *name;
+ CURLoption id;
+ curl_easytype type;
+ unsigned int flags;
+};
+~~~
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* iterate over all available options */
+ const struct curl_easyoption *opt;
+ opt = curl_easy_option_next(NULL);
+ while(opt) {
+ printf("Name: %s\n", opt->name);
+ opt = curl_easy_option_next(opt);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.73.0
+
+# RETURN VALUE
+
+A pointer to the *curl_easyoption* struct for the next option or NULL if
+no more options.
diff --git a/docs/libcurl/curl_easy_pause.3 b/docs/libcurl/curl_easy_pause.3
deleted file mode 100644
index a3cf4b81c..000000000
--- a/docs/libcurl/curl_easy_pause.3
+++ /dev/null
@@ -1,124 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_pause 3 "17 Dec 2007" "libcurl" "libcurl"
-.SH NAME
-curl_easy_pause - pause and unpause a connection
-.SH SYNOPSIS
-.nf
-.B #include <curl/curl.h>
-
-.BI "CURLcode curl_easy_pause(CURL *"handle ", int "bitmask ");"
-.fi
-.SH DESCRIPTION
-Using this function, you can explicitly mark a running connection to get
-paused, and you can unpause a connection that was previously paused. Unlike
-most other libcurl functions, \fIcurl_easy_pause(3)\fP can be used from within
-callbacks.
-
-A connection can be paused by using this function or by letting the read or
-the write callbacks return the proper magic return code
-(\fICURL_READFUNC_PAUSE\fP and \fICURL_WRITEFUNC_PAUSE\fP). A write callback
-that returns pause signals to the library that it could not take care of any
-data at all, and that data is then delivered again to the callback when the
-transfer is unpaused.
-
-While it may feel tempting, take care and notice that you cannot call this
-function from another thread. To unpause, you may for example call it from the
-progress callback (\fICURLOPT_PROGRESSFUNCTION(3)\fP).
-
-When this function is called to unpause receiving, the write callback might
-get called before this function returns to deliver cached content. When
-libcurl delivers such cached data to the write callback, it is delivered as
-fast as possible, which may overstep the boundary set in
-\fICURLOPT_MAX_RECV_SPEED_LARGE(3)\fP etc.
-
-The \fBhandle\fP argument identifies the transfer you want to pause or
-unpause.
-
-A paused transfer is excluded from low speed cancels via the
-\fICURLOPT_LOW_SPEED_LIMIT(3)\fP option and unpausing a transfer resets the
-time period required for the low speed limit to be met.
-
-The \fBbitmask\fP argument is a set of bits that sets the new state of the
-connection. The following bits can be used:
-.IP CURLPAUSE_RECV
-Pause receiving data. There is no data received on this connection until this
-function is called again without this bit set. Thus, the write callback
-(\fICURLOPT_WRITEFUNCTION(3)\fP) is not called.
-.IP CURLPAUSE_SEND
-Pause sending data. There is no data sent on this connection until this
-function is called again without this bit set. Thus, the read callback
-(\fICURLOPT_READFUNCTION(3)\fP) is not called.
-.IP CURLPAUSE_ALL
-Convenience define that pauses both directions.
-.IP CURLPAUSE_CONT
-Convenience define that unpauses both directions.
-.SH LIMITATIONS
-The pausing of transfers does not work with protocols that work without
-network connectivity, like FILE://. Trying to pause such a transfer, in any
-direction, might cause problems or error.
-.SH MULTIPLEXED
-When a connection is used multiplexed, like for HTTP/2, and one of the
-transfers over the connection is paused and the others continue flowing,
-libcurl might end up buffering contents for the paused transfer. It has to do
-this because it needs to drain the socket for the other transfers and the
-already announced window size for the paused transfer allows the server to
-continue sending data up to that window size amount. By default, libcurl
-announces a 32 megabyte window size, which thus can make libcurl end up
-buffering 32 megabyte of data for a paused stream.
-
-When such a paused stream is unpaused again, any buffered data is delivered
-first.
-.SH EXAMPLE
-.nf
-/* pause a transfer in both directions */
-curl_easy_pause(curl, CURL_READFUNC_PAUSE | CURL_WRITEFUNC_PAUSE);
-.fi
-.SH "MEMORY USE"
-When pausing a download transfer by returning the magic return code from a
-write callback, the read data is already in libcurl's internal buffers so it
-has to keep it in an allocated buffer until the receiving is again unpaused
-using this function.
-
-If the downloaded data is compressed and is asked to get uncompressed
-automatically on download, libcurl continues to uncompress the entire
-downloaded chunk and it caches the data uncompressed. This has the side-
-effect that if you download something that is compressed a lot, it can result
-in a large data amount needing to be allocated to save the data during the
-pause. consider not using paused receiving if you allow libcurl to uncompress
-data automatically.
-
-If the download is done with HTTP/2 or HTTP/3, there is up to a stream window
-size worth of data that curl cannot stop but instead needs to cache while the
-transfer is paused. This means that if a window size of 64 MB is used, libcurl
-might end up having to cache 64 MB of data.
-.SH AVAILABILITY
-Added in 7.18.0.
-.SH RETURN VALUE
-CURLE_OK (zero) means that the option was set properly, and a non-zero return
-code means something wrong occurred after the new state was set. See the
-\fIlibcurl-errors(3)\fP man page for the full list with descriptions.
-.SH "SEE ALSO"
-.BR curl_easy_cleanup (3),
-.BR curl_easy_reset (3)
diff --git a/docs/libcurl/curl_easy_pause.md b/docs/libcurl/curl_easy_pause.md
new file mode 100644
index 000000000..03e6b917a
--- /dev/null
+++ b/docs/libcurl/curl_easy_pause.md
@@ -0,0 +1,140 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_pause
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_cleanup (3)
+ - curl_easy_reset (3)
+---
+
+# NAME
+
+curl_easy_pause - pause and unpause a connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_pause(CURL *handle, int bitmask );
+~~~
+
+# DESCRIPTION
+
+Using this function, you can explicitly mark a running connection to get
+paused, and you can unpause a connection that was previously paused. Unlike
+most other libcurl functions, curl_easy_pause(3) can be used from within
+callbacks.
+
+A connection can be paused by using this function or by letting the read or
+the write callbacks return the proper magic return code
+(*CURL_READFUNC_PAUSE* and *CURL_WRITEFUNC_PAUSE*). A write callback
+that returns pause signals to the library that it could not take care of any
+data at all, and that data is then delivered again to the callback when the
+transfer is unpaused.
+
+While it may feel tempting, take care and notice that you cannot call this
+function from another thread. To unpause, you may for example call it from the
+progress callback (CURLOPT_PROGRESSFUNCTION(3)).
+
+When this function is called to unpause receiving, the write callback might
+get called before this function returns to deliver cached content. When
+libcurl delivers such cached data to the write callback, it is delivered as
+fast as possible, which may overstep the boundary set in
+CURLOPT_MAX_RECV_SPEED_LARGE(3) etc.
+
+The **handle** argument identifies the transfer you want to pause or
+unpause.
+
+A paused transfer is excluded from low speed cancels via the
+CURLOPT_LOW_SPEED_LIMIT(3) option and unpausing a transfer resets the
+time period required for the low speed limit to be met.
+
+The **bitmask** argument is a set of bits that sets the new state of the
+connection. The following bits can be used:
+
+## CURLPAUSE_RECV
+
+Pause receiving data. There is no data received on this connection until this
+function is called again without this bit set. Thus, the write callback
+(CURLOPT_WRITEFUNCTION(3)) is not called.
+
+## CURLPAUSE_SEND
+
+Pause sending data. There is no data sent on this connection until this
+function is called again without this bit set. Thus, the read callback
+(CURLOPT_READFUNCTION(3)) is not called.
+
+## CURLPAUSE_ALL
+
+Convenience define that pauses both directions.
+
+## CURLPAUSE_CONT
+
+Convenience define that unpauses both directions.
+
+# LIMITATIONS
+
+The pausing of transfers does not work with protocols that work without
+network connectivity, like FILE://. Trying to pause such a transfer, in any
+direction, might cause problems or error.
+
+# MULTIPLEXED
+
+When a connection is used multiplexed, like for HTTP/2, and one of the
+transfers over the connection is paused and the others continue flowing,
+libcurl might end up buffering contents for the paused transfer. It has to do
+this because it needs to drain the socket for the other transfers and the
+already announced window size for the paused transfer allows the server to
+continue sending data up to that window size amount. By default, libcurl
+announces a 32 megabyte window size, which thus can make libcurl end up
+buffering 32 megabyte of data for a paused stream.
+
+When such a paused stream is unpaused again, any buffered data is delivered
+first.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* pause a transfer in both directions */
+ curl_easy_pause(curl, CURL_READFUNC_PAUSE | CURL_WRITEFUNC_PAUSE);
+
+ }
+}
+~~~
+
+# MEMORY USE
+
+When pausing a download transfer by returning the magic return code from a
+write callback, the read data is already in libcurl's internal buffers so it
+has to keep it in an allocated buffer until the receiving is again unpaused
+using this function.
+
+If the downloaded data is compressed and is asked to get uncompressed
+automatically on download, libcurl continues to uncompress the entire
+downloaded chunk and it caches the data uncompressed. This has the side-
+effect that if you download something that is compressed a lot, it can result
+in a large data amount needing to be allocated to save the data during the
+pause. Consider not using paused receiving if you allow libcurl to uncompress
+data automatically.
+
+If the download is done with HTTP/2 or HTTP/3, there is up to a stream window
+size worth of data that curl cannot stop but instead needs to cache while the
+transfer is paused. This means that if a window size of 64 MB is used, libcurl
+might end up having to cache 64 MB of data.
+
+# AVAILABILITY
+
+Added in 7.18.0.
+
+# RETURN VALUE
+
+CURLE_OK (zero) means that the option was set properly, and a non-zero return
+code means something wrong occurred after the new state was set. See the
+libcurl-errors(3) man page for the full list with descriptions.
diff --git a/docs/libcurl/curl_easy_perform.3 b/docs/libcurl/curl_easy_perform.3
deleted file mode 100644
index 7852d764f..000000000
--- a/docs/libcurl/curl_easy_perform.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_perform 3 "5 Mar 2001" "libcurl" "libcurl"
-.SH NAME
-curl_easy_perform - perform a blocking file transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_perform(CURL *easy_handle);
-.fi
-.SH DESCRIPTION
-\fIcurl_easy_perform(3)\fP performs a network transfer in a blocking manner
-and returns when done, or earlier if it fails. For non-blocking behavior, see
-\fIcurl_multi_perform(3)\fP.
-
-Invoke this function after \fIcurl_easy_init(3)\fP and all the
-\fIcurl_easy_setopt(3)\fP calls are made, and it performs the transfer as
-described in the options. It must be called with the same \fBeasy_handle\fP as
-input as the \fIcurl_easy_init(3)\fP call returned.
-
-You can do any amount of calls to \fIcurl_easy_perform(3)\fP while using the
-same \fBeasy_handle\fP. If you intend to transfer more than one file, you are
-even encouraged to do so. libcurl attempts to reuse existing connections for
-the following transfers, thus making the operations faster, less CPU intense
-and using less network resources. You probably want to use
-\fIcurl_easy_setopt(3)\fP between the invokes to set options for the following
-\fIcurl_easy_perform(3)\fP call.
-
-You must never call this function simultaneously from two places using the
-same \fBeasy_handle\fP. Let the function return first before invoking it
-another time. If you want parallel transfers, you must use several curl
-easy_handles.
-
-A network transfer moves data to a peer or from a peer. An application tells
-libcurl how to receive data by setting the \fICURLOPT_WRITEFUNCTION(3)\fP and
-\fICURLOPT_WRITEDATA(3)\fP options. To tell libcurl what data to send, there
-are a few more alternatives but two common ones are
-\fICURLOPT_READFUNCTION(3)\fP and \fICURLOPT_POSTFIELDS(3)\fP.
-
-While the \fBeasy_handle\fP is added to a multi handle, it cannot be used by
-\fIcurl_easy_perform(3)\fP.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-CURLE_OK (0) means everything was OK, non-zero means an error occurred as
-.I <curl/curl.h>
-defines - see \fIlibcurl-errors(3)\fP. If the \fICURLOPT_ERRORBUFFER(3)\fP was
-set with \fIcurl_easy_setopt(3)\fP there is a readable error message stored in
-the error buffer when non-zero is returned.
-.SH "SEE ALSO"
-.BR curl_easy_init (3),
-.BR curl_easy_setopt (3),
-.BR curl_multi_add_handle (3),
-.BR curl_multi_perform (3),
-.BR libcurl-errors (3)
diff --git a/docs/libcurl/curl_easy_perform.md b/docs/libcurl/curl_easy_perform.md
new file mode 100644
index 000000000..ff65a82ee
--- /dev/null
+++ b/docs/libcurl/curl_easy_perform.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_perform
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_init (3)
+ - curl_easy_setopt (3)
+ - curl_multi_add_handle (3)
+ - curl_multi_perform (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+curl_easy_perform - perform a blocking file transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_perform(CURL *easy_handle);
+~~~
+
+# DESCRIPTION
+
+curl_easy_perform(3) performs a network transfer in a blocking manner and
+returns when done, or earlier if it fails. For non-blocking behavior, see
+curl_multi_perform(3).
+
+Invoke this function after curl_easy_init(3) and all the curl_easy_setopt(3)
+calls are made, and it performs the transfer as described in the options. It
+must be called with the same **easy_handle** as input as the curl_easy_init(3)
+call returned.
+
+You can do any amount of calls to curl_easy_perform(3) while using the same
+**easy_handle**. If you intend to transfer more than one file, you are even
+encouraged to do so. libcurl attempts to reuse existing connections for the
+following transfers, thus making the operations faster, less CPU intense and
+using less network resources. You probably want to use curl_easy_setopt(3)
+between the invokes to set options for the following curl_easy_perform(3)
+call.
+
+You must never call this function simultaneously from two places using the
+same **easy_handle**. Let the function return first before invoking it another
+time. If you want parallel transfers, you must use several curl easy_handles.
+
+A network transfer moves data to a peer or from a peer. An application tells
+libcurl how to receive data by setting the CURLOPT_WRITEFUNCTION(3) and
+CURLOPT_WRITEDATA(3) options. To tell libcurl what data to send, there are a
+few more alternatives but two common ones are CURLOPT_READFUNCTION(3) and
+CURLOPT_POSTFIELDS(3).
+
+While the **easy_handle** is added to a multi handle, it cannot be used by
+curl_easy_perform(3).
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+CURLE_OK (0) means everything was OK, non-zero means an error occurred as
+*<curl/curl.h>* defines - see libcurl-errors(3). If the CURLOPT_ERRORBUFFER(3)
+was set with curl_easy_setopt(3) there is a readable error message stored in
+the error buffer when non-zero is returned.
diff --git a/docs/libcurl/curl_easy_recv.3 b/docs/libcurl/curl_easy_recv.3
deleted file mode 100644
index c215a544f..000000000
--- a/docs/libcurl/curl_easy_recv.3
+++ /dev/null
@@ -1,98 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_recv 3 "29 April 2008" "libcurl" "libcurl"
-.SH NAME
-curl_easy_recv - receives raw data on an "easy" connection
-.SH SYNOPSIS
-.nf
-#include <curl/easy.h>
-
-CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n);
-.fi
-.SH DESCRIPTION
-This function receives raw data from the established connection. You may use
-it together with \fIcurl_easy_send(3)\fP to implement custom protocols using
-libcurl. This functionality can be particularly useful if you use proxies
-and/or SSL encryption: libcurl takes care of proxy negotiation and connection
-setup.
-
-\fBbuffer\fP is a pointer to your buffer memory that gets populated by the
-received data. \fBbuflen\fP is the maximum amount of data you can get in that
-buffer. The variable \fBn\fP points to receives the number of received bytes.
-
-To establish the connection, set \fICURLOPT_CONNECT_ONLY(3)\fP option before
-calling \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP. Note that
-\fIcurl_easy_recv(3)\fP does not work on connections that were created without
-this option.
-
-The call returns \fBCURLE_AGAIN\fP if there is no data to read - the socket is
-used in non-blocking mode internally. When \fBCURLE_AGAIN\fP is returned, use
-your operating system facilities like \fIselect(2)\fP to wait for data. The
-socket may be obtained using \fIcurl_easy_getinfo(3)\fP with
-\fICURLINFO_ACTIVESOCKET(3)\fP.
-
-Wait on the socket only if \fIcurl_easy_recv(3)\fP returns \fBCURLE_AGAIN\fP.
-The reason for this is libcurl or the SSL library may internally cache some
-data, therefore you should call \fIcurl_easy_recv(3)\fP until all data is
-read which would include any cached data.
-
-Furthermore if you wait on the socket and it tells you there is data to read,
-\fIcurl_easy_recv(3)\fP may return \fBCURLE_AGAIN\fP if the only data that was
-read was for internal SSL processing, and no other data is available.
-.SH EXAMPLE
-.nf
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- /* Do not do the transfer - only connect to host */
- curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
- res = curl_easy_perform(curl);
-
- if(res == CURLE_OK) {
- /* Extract the socket from the curl handle - we need it for waiting. */
- res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
-
- /* read data */
- res = curl_easy_recv(curl, buf, sizeof(buf), &nread);
- }
-.fi
-.SH AVAILABILITY
-Added in 7.18.2.
-.SH RETURN VALUE
-On success, returns \fBCURLE_OK\fP, stores the received data into
-\fBbuffer\fP, and the number of bytes it actually read into \fB*n\fP.
-
-On failure, returns the appropriate error code.
-
-The function may return \fBCURLE_AGAIN\fP. In this case, use your operating
-system facilities to wait until data can be read, and retry.
-
-Reading exactly 0 bytes indicates a closed connection.
-
-If there is no socket available to use from the previous transfer, this function
-returns \fBCURLE_UNSUPPORTED_PROTOCOL\fP.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_perform (3),
-.BR curl_easy_send (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/curl_easy_recv.md b/docs/libcurl/curl_easy_recv.md
new file mode 100644
index 000000000..df210f71a
--- /dev/null
+++ b/docs/libcurl/curl_easy_recv.md
@@ -0,0 +1,103 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_recv
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_perform (3)
+ - curl_easy_send (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+curl_easy_recv - receives raw data on an "easy" connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n);
+~~~
+
+# DESCRIPTION
+
+This function receives raw data from the established connection. You may use
+it together with curl_easy_send(3) to implement custom protocols using
+libcurl. This functionality can be particularly useful if you use proxies
+and/or SSL encryption: libcurl takes care of proxy negotiation and connection
+setup.
+
+**buffer** is a pointer to your buffer memory that gets populated by the
+received data. **buflen** is the maximum amount of data you can get in that
+buffer. The variable **n** points to receives the number of received bytes.
+
+To establish the connection, set CURLOPT_CONNECT_ONLY(3) option before
+calling curl_easy_perform(3) or curl_multi_perform(3). Note that
+curl_easy_recv(3) does not work on connections that were created without
+this option.
+
+The call returns **CURLE_AGAIN** if there is no data to read - the socket is
+used in non-blocking mode internally. When **CURLE_AGAIN** is returned, use
+your operating system facilities like *select(2)* to wait for data. The
+socket may be obtained using curl_easy_getinfo(3) with
+CURLINFO_ACTIVESOCKET(3).
+
+Wait on the socket only if curl_easy_recv(3) returns **CURLE_AGAIN**.
+The reason for this is libcurl or the SSL library may internally cache some
+data, therefore you should call curl_easy_recv(3) until all data is
+read which would include any cached data.
+
+Furthermore if you wait on the socket and it tells you there is data to read,
+curl_easy_recv(3) may return **CURLE_AGAIN** if the only data that was
+read was for internal SSL processing, and no other data is available.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ /* Do not do the transfer - only connect to host */
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
+ res = curl_easy_perform(curl);
+
+ if(res == CURLE_OK) {
+ char buf[256];
+ size_t nread;
+ long sockfd;
+
+ /* Extract the socket from the curl handle - we need it for waiting. */
+ res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
+
+ /* read data */
+ res = curl_easy_recv(curl, buf, sizeof(buf), &nread);
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.18.2.
+
+# RETURN VALUE
+
+On success, returns **CURLE_OK**, stores the received data into
+**buffer**, and the number of bytes it actually read into ***n**.
+
+On failure, returns the appropriate error code.
+
+The function may return **CURLE_AGAIN**. In this case, use your operating
+system facilities to wait until data can be read, and retry.
+
+Reading exactly 0 bytes indicates a closed connection.
+
+If there is no socket available to use from the previous transfer, this function
+returns **CURLE_UNSUPPORTED_PROTOCOL**.
diff --git a/docs/libcurl/curl_easy_reset.3 b/docs/libcurl/curl_easy_reset.3
deleted file mode 100644
index c7615655d..000000000
--- a/docs/libcurl/curl_easy_reset.3
+++ /dev/null
@@ -1,57 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_reset 3 "31 July 2004" "libcurl" "libcurl"
-.SH NAME
-curl_easy_reset - reset all options of a libcurl session handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_easy_reset(CURL *handle);
-.fi
-.SH DESCRIPTION
-Re-initializes all options previously set on a specified CURL handle to the
-default values. This puts back the handle to the same state as it was in when
-it was just created with \fIcurl_easy_init(3)\fP.
-
-It does not change the following information kept in the handle: live
-connections, the Session ID cache, the DNS cache, the cookies, the shares or
-the alt-svc cache.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-
-/* ... the handle is used and options are set ... */
-
-curl_easy_reset(curl);
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.12.1
-.SH RETURN VALUE
-Nothing
-.SH "SEE ALSO"
-.BR curl_easy_cleanup (3),
-.BR curl_easy_duphandle (3),
-.BR curl_easy_init (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/curl_easy_reset.md b/docs/libcurl/curl_easy_reset.md
new file mode 100644
index 000000000..c2aea6e10
--- /dev/null
+++ b/docs/libcurl/curl_easy_reset.md
@@ -0,0 +1,56 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_reset
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_cleanup (3)
+ - curl_easy_duphandle (3)
+ - curl_easy_init (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+curl_easy_reset - reset all options of a libcurl session handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_easy_reset(CURL *handle);
+~~~
+
+# DESCRIPTION
+
+Re-initializes all options previously set on a specified CURL handle to the
+default values. This puts back the handle to the same state as it was in when
+it was just created with curl_easy_init(3).
+
+It does not change the following information kept in the handle: live
+connections, the Session ID cache, the DNS cache, the cookies, the shares or
+the alt-svc cache.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+
+ /* ... the handle is used and options are set ... */
+ curl_easy_reset(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.12.1
+
+# RETURN VALUE
+
+Nothing
diff --git a/docs/libcurl/curl_easy_send.3 b/docs/libcurl/curl_easy_send.3
deleted file mode 100644
index 4da5a2387..000000000
--- a/docs/libcurl/curl_easy_send.3
+++ /dev/null
@@ -1,92 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_send 3 "29 April 2008" "libcurl" "libcurl"
-.SH NAME
-curl_easy_send - sends raw data over an "easy" connection
-.SH SYNOPSIS
-.nf
-#include <curl/easy.h>
-
-CURLcode curl_easy_send(CURL *curl, const void *buffer,
- size_t buflen, size_t *n);
-.fi
-.SH DESCRIPTION
-This function sends arbitrary data over the established connection. You may
-use it together with \fIcurl_easy_recv(3)\fP to implement custom protocols
-using libcurl. This functionality can be particularly useful if you use
-proxies and/or SSL encryption: libcurl takes care of proxy negotiation and
-connection setup.
-
-\fBbuffer\fP is a pointer to the data of length \fBbuflen\fP that you want
-sent. The variable \fBn\fP points to receives the number of sent bytes.
-
-To establish the connection, set \fICURLOPT_CONNECT_ONLY(3)\fP option before
-calling \fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP. Note that
-\fIcurl_easy_send(3)\fP does not work on connections that were created without
-this option.
-
-The call returns \fBCURLE_AGAIN\fP if it's not possible to send data right now
-- the socket is used in non-blocking mode internally. When \fBCURLE_AGAIN\fP
-is returned, use your operating system facilities like \fIselect(2)\fP to wait
-until the socket is writable. The socket may be obtained using
-\fIcurl_easy_getinfo(3)\fP with \fICURLINFO_ACTIVESOCKET(3)\fP.
-
-Furthermore if you wait on the socket and it tells you it's writable,
-\fIcurl_easy_send(3)\fP may return \fBCURLE_AGAIN\fP if the only data that was
-sent was for internal SSL processing, and no other data could be sent.
-.SH EXAMPLE
-.nf
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- /* Do not do the transfer - only connect to host */
- curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
- res = curl_easy_perform(curl);
-
- if(res == CURLE_OK) {
- /* Extract the socket from the curl handle - we need it for waiting. */
- res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
-
- /* send data */
- res = curl_easy_send(curl, "hello", 5, &sent);
- }
-.fi
-.SH AVAILABILITY
-Added in 7.18.2.
-.SH RETURN VALUE
-On success, returns \fBCURLE_OK\fP and stores the number of bytes actually
-sent into \fB*n\fP. Note that this may be less than the amount you wanted to
-send.
-
-On failure, returns the appropriate error code.
-
-This function may return \fBCURLE_AGAIN\fP. In this case, use your operating
-system facilities to wait until the socket is writable, and retry.
-
-If there is no socket available to use from the previous transfer, this function
-returns \fBCURLE_UNSUPPORTED_PROTOCOL\fP.
-.SH "SEE ALSO"
-.BR curl_easy_setopt (3),
-.BR curl_easy_perform (3),
-.BR curl_easy_getinfo (3),
-.BR curl_easy_recv (3)
diff --git a/docs/libcurl/curl_easy_send.md b/docs/libcurl/curl_easy_send.md
new file mode 100644
index 000000000..725b05ca1
--- /dev/null
+++ b/docs/libcurl/curl_easy_send.md
@@ -0,0 +1,95 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_send
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_perform (3)
+ - curl_easy_recv (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+curl_easy_send - sends raw data over an "easy" connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_send(CURL *curl, const void *buffer,
+ size_t buflen, size_t *n);
+~~~
+
+# DESCRIPTION
+
+This function sends arbitrary data over the established connection. You may
+use it together with curl_easy_recv(3) to implement custom protocols
+using libcurl. This functionality can be particularly useful if you use
+proxies and/or SSL encryption: libcurl takes care of proxy negotiation and
+connection setup.
+
+**buffer** is a pointer to the data of length **buflen** that you want
+sent. The variable **n** points to receives the number of sent bytes.
+
+To establish the connection, set CURLOPT_CONNECT_ONLY(3) option before
+calling curl_easy_perform(3) or curl_multi_perform(3). Note that
+curl_easy_send(3) does not work on connections that were created without
+this option.
+
+The call returns **CURLE_AGAIN** if it is not possible to send data right now
+- the socket is used in non-blocking mode internally. When **CURLE_AGAIN**
+is returned, use your operating system facilities like *select(2)* to wait
+until the socket is writable. The socket may be obtained using
+curl_easy_getinfo(3) with CURLINFO_ACTIVESOCKET(3).
+
+Furthermore if you wait on the socket and it tells you it is writable,
+curl_easy_send(3) may return **CURLE_AGAIN** if the only data that was sent
+was for internal SSL processing, and no other data could be sent.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ /* Do not do the transfer - only connect to host */
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
+ res = curl_easy_perform(curl);
+
+ if(res == CURLE_OK) {
+ long sockfd;
+ size_t sent;
+ /* Extract the socket from the curl handle - we need it for waiting. */
+ res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
+
+ /* send data */
+ res = curl_easy_send(curl, "hello", 5, &sent);
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.18.2.
+
+# RETURN VALUE
+
+On success, returns **CURLE_OK** and stores the number of bytes actually
+sent into ***n**. Note that this may be less than the amount you wanted to
+send.
+
+On failure, returns the appropriate error code.
+
+This function may return **CURLE_AGAIN**. In this case, use your operating
+system facilities to wait until the socket is writable, and retry.
+
+If there is no socket available to use from the previous transfer, this function
+returns **CURLE_UNSUPPORTED_PROTOCOL**.
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
deleted file mode 100644
index ae43811ab..000000000
--- a/docs/libcurl/curl_easy_setopt.3
+++ /dev/null
@@ -1,746 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_setopt 3 "25 Jun 2014" "libcurl" "libcurl"
-.SH NAME
-curl_easy_setopt \- set options for a curl easy handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
-.fi
-.SH DESCRIPTION
-\fIcurl_easy_setopt(3)\fP is used to tell libcurl how to behave. By setting
-the appropriate options, the application can change libcurl's behavior. All
-options are set with an \fIoption\fP followed by a \fIparameter\fP. That
-parameter can be a \fBlong\fP, a \fBfunction pointer\fP, an \fBobject
-pointer\fP or a \fBcurl_off_t\fP, depending on what the specific option
-expects. Read this manual carefully as bad input values may cause libcurl to
-behave badly! You can only set one option in each function call. A typical
-application uses many \fIcurl_easy_setopt(3)\fP calls in the setup phase.
-
-Options set with this function call are valid for all forthcoming transfers
-performed using this \fIhandle\fP. The options are not in any way reset
-between transfers, so if you want subsequent transfers with different options,
-you must change them between the transfers. You can optionally reset all
-options back to internal default with \fIcurl_easy_reset(3)\fP.
-
-Strings passed to libcurl as 'char *' arguments, are copied by the library;
-the string storage associated to the pointer argument may be discarded or
-reused after \fIcurl_easy_setopt(3)\fP returns. The only exception to this
-rule is really \fICURLOPT_POSTFIELDS(3)\fP, but the alternative that copies
-the string \fICURLOPT_COPYPOSTFIELDS(3)\fP has some usage characteristics you
-need to read up on. This function does not accept input strings longer than
-\fBCURL_MAX_INPUT_LENGTH\fP (8 MB).
-
-The order in which the options are set does not matter.
-
-Before version 7.17.0, strings were not copied. Instead the user was forced
-keep them available until libcurl no longer needed them.
-
-The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
-\fIcurl_easy_duphandle(3)\fP call.
-.SH BEHAVIOR OPTIONS
-.IP CURLOPT_VERBOSE
-Display verbose information. See \fICURLOPT_VERBOSE(3)\fP
-.IP CURLOPT_HEADER
-Include the header in the body output. See \fICURLOPT_HEADER(3)\fP
-.IP CURLOPT_NOPROGRESS
-Shut off the progress meter. See \fICURLOPT_NOPROGRESS(3)\fP
-.IP CURLOPT_NOSIGNAL
-Do not install signal handlers. See \fICURLOPT_NOSIGNAL(3)\fP
-.IP CURLOPT_WILDCARDMATCH
-Transfer multiple files according to a file name pattern. See \fICURLOPT_WILDCARDMATCH(3)\fP
-.SH CALLBACK OPTIONS
-.IP CURLOPT_WRITEFUNCTION
-Callback for writing data. See \fICURLOPT_WRITEFUNCTION(3)\fP
-.IP CURLOPT_WRITEDATA
-Data pointer to pass to the write callback. See \fICURLOPT_WRITEDATA(3)\fP
-.IP CURLOPT_READFUNCTION
-Callback for reading data. See \fICURLOPT_READFUNCTION(3)\fP
-.IP CURLOPT_READDATA
-Data pointer to pass to the read callback. See \fICURLOPT_READDATA(3)\fP
-.IP CURLOPT_IOCTLFUNCTION
-\fBDeprecated option\fP Callback for I/O operations.
-See \fICURLOPT_IOCTLFUNCTION(3)\fP
-.IP CURLOPT_IOCTLDATA
-\fBDeprecated option\fP Data pointer to pass to the I/O callback.
-See \fICURLOPT_IOCTLDATA(3)\fP
-.IP CURLOPT_SEEKFUNCTION
-Callback for seek operations. See \fICURLOPT_SEEKFUNCTION(3)\fP
-.IP CURLOPT_SEEKDATA
-Data pointer to pass to the seek callback. See \fICURLOPT_SEEKDATA(3)\fP
-.IP CURLOPT_SOCKOPTFUNCTION
-Callback for sockopt operations. See \fICURLOPT_SOCKOPTFUNCTION(3)\fP
-.IP CURLOPT_SOCKOPTDATA
-Data pointer to pass to the sockopt callback. See \fICURLOPT_SOCKOPTDATA(3)\fP
-.IP CURLOPT_OPENSOCKETFUNCTION
-Callback for socket creation. See \fICURLOPT_OPENSOCKETFUNCTION(3)\fP
-.IP CURLOPT_OPENSOCKETDATA
-Data pointer to pass to the open socket callback. See \fICURLOPT_OPENSOCKETDATA(3)\fP
-.IP CURLOPT_CLOSESOCKETFUNCTION
-Callback for closing socket. See \fICURLOPT_CLOSESOCKETFUNCTION(3)\fP
-.IP CURLOPT_CLOSESOCKETDATA
-Data pointer to pass to the close socket callback. See \fICURLOPT_CLOSESOCKETDATA(3)\fP
-.IP CURLOPT_PROGRESSFUNCTION
-\fBOBSOLETE\fP callback for progress meter.
-See \fICURLOPT_PROGRESSFUNCTION(3)\fP
-.IP CURLOPT_PROGRESSDATA
-Data pointer to pass to the progress meter callback. See \fICURLOPT_PROGRESSDATA(3)\fP
-.IP CURLOPT_XFERINFOFUNCTION
-Callback for progress meter. See \fICURLOPT_XFERINFOFUNCTION(3)\fP
-.IP CURLOPT_XFERINFODATA
-Data pointer to pass to the progress meter callback. See \fICURLOPT_XFERINFODATA(3)\fP
-.IP CURLOPT_HEADERFUNCTION
-Callback for writing received headers. See \fICURLOPT_HEADERFUNCTION(3)\fP
-.IP CURLOPT_HEADERDATA
-Data pointer to pass to the header callback. See \fICURLOPT_HEADERDATA(3)\fP
-.IP CURLOPT_DEBUGFUNCTION
-Callback for debug information. See \fICURLOPT_DEBUGFUNCTION(3)\fP
-.IP CURLOPT_DEBUGDATA
-Data pointer to pass to the debug callback. See \fICURLOPT_DEBUGDATA(3)\fP
-.IP CURLOPT_SSL_CTX_FUNCTION
-Callback for SSL context logic. See \fICURLOPT_SSL_CTX_FUNCTION(3)\fP
-.IP CURLOPT_SSL_CTX_DATA
-Data pointer to pass to the SSL context callback. See \fICURLOPT_SSL_CTX_DATA(3)\fP
-.IP CURLOPT_CONV_TO_NETWORK_FUNCTION
-\fBOBSOLETE\fP Callback for code base conversion.
-See \fICURLOPT_CONV_TO_NETWORK_FUNCTION(3)\fP
-.IP CURLOPT_CONV_FROM_NETWORK_FUNCTION
-\fBOBSOLETE\fP Callback for code base conversion.
-See \fICURLOPT_CONV_FROM_NETWORK_FUNCTION(3)\fP
-.IP CURLOPT_CONV_FROM_UTF8_FUNCTION
-\fBOBSOLETE\fP Callback for code base conversion.
-See \fICURLOPT_CONV_FROM_UTF8_FUNCTION(3)\fP
-.IP CURLOPT_INTERLEAVEFUNCTION
-Callback for RTSP interleaved data. See \fICURLOPT_INTERLEAVEFUNCTION(3)\fP
-.IP CURLOPT_INTERLEAVEDATA
-Data pointer to pass to the RTSP interleave callback. See \fICURLOPT_INTERLEAVEDATA(3)\fP
-.IP CURLOPT_CHUNK_BGN_FUNCTION
-Callback for wildcard download start of chunk. See \fICURLOPT_CHUNK_BGN_FUNCTION(3)\fP
-.IP CURLOPT_CHUNK_END_FUNCTION
-Callback for wildcard download end of chunk. See \fICURLOPT_CHUNK_END_FUNCTION(3)\fP
-.IP CURLOPT_CHUNK_DATA
-Data pointer to pass to the chunk callbacks. See \fICURLOPT_CHUNK_DATA(3)\fP
-.IP CURLOPT_FNMATCH_FUNCTION
-Callback for wildcard matching. See \fICURLOPT_FNMATCH_FUNCTION(3)\fP
-.IP CURLOPT_FNMATCH_DATA
-Data pointer to pass to the wildcard matching callback. See \fICURLOPT_FNMATCH_DATA(3)\fP
-.IP CURLOPT_SUPPRESS_CONNECT_HEADERS
-Suppress proxy CONNECT response headers from user callbacks. See \fICURLOPT_SUPPRESS_CONNECT_HEADERS(3)\fP
-.IP CURLOPT_RESOLVER_START_FUNCTION
-Callback to be called before a new resolve request is started. See \fICURLOPT_RESOLVER_START_FUNCTION(3)\fP
-.IP CURLOPT_RESOLVER_START_DATA
-Data pointer to pass to resolver start callback. See \fICURLOPT_RESOLVER_START_DATA(3)\fP
-.IP CURLOPT_PREREQFUNCTION
-Callback to be called after a connection is established but before a request is made on that connection. See \fICURLOPT_PREREQFUNCTION(3)\fP
-.IP CURLOPT_PREREQDATA
-Data pointer to pass to the CURLOPT_PREREQFUNCTION callback. See \fICURLOPT_PREREQDATA(3)\fP
-.SH ERROR OPTIONS
-.IP CURLOPT_ERRORBUFFER
-Error message buffer. See \fICURLOPT_ERRORBUFFER(3)\fP
-.IP CURLOPT_STDERR
-stderr replacement stream. See \fICURLOPT_STDERR(3)\fP
-.IP CURLOPT_FAILONERROR
-Fail on HTTP 4xx errors. \fICURLOPT_FAILONERROR(3)\fP
-.IP CURLOPT_KEEP_SENDING_ON_ERROR
-Keep sending on HTTP >= 300 errors. \fICURLOPT_KEEP_SENDING_ON_ERROR(3)\fP
-.SH NETWORK OPTIONS
-.IP CURLOPT_URL
-URL to work on. See \fICURLOPT_URL(3)\fP
-.IP CURLOPT_PATH_AS_IS
-Disable squashing /../ and /./ sequences in the path. See \fICURLOPT_PATH_AS_IS(3)\fP
-.IP CURLOPT_PROTOCOLS
-\fBDeprecated option\fP Allowed protocols. See \fICURLOPT_PROTOCOLS(3)\fP
-.IP CURLOPT_PROTOCOLS_STR
-Allowed protocols. See \fICURLOPT_PROTOCOLS_STR(3)\fP
-.IP CURLOPT_REDIR_PROTOCOLS
-\fBDeprecated option\fP Protocols to allow redirects to. See
-\fICURLOPT_REDIR_PROTOCOLS(3)\fP
-.IP CURLOPT_REDIR_PROTOCOLS_STR
-Protocols to allow redirects to. See \fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP
-.IP CURLOPT_DEFAULT_PROTOCOL
-Default protocol. See \fICURLOPT_DEFAULT_PROTOCOL(3)\fP
-.IP CURLOPT_PROXY
-Proxy to use. See \fICURLOPT_PROXY(3)\fP
-.IP CURLOPT_PRE_PROXY
-Socks proxy to use. See \fICURLOPT_PRE_PROXY(3)\fP
-.IP CURLOPT_PROXYPORT
-Proxy port to use. See \fICURLOPT_PROXYPORT(3)\fP
-.IP CURLOPT_PROXYTYPE
-Proxy type. See \fICURLOPT_PROXYTYPE(3)\fP
-.IP CURLOPT_NOPROXY
-Filter out hosts from proxy use. \fICURLOPT_NOPROXY(3)\fP
-.IP CURLOPT_HTTPPROXYTUNNEL
-Tunnel through the HTTP proxy. \fICURLOPT_HTTPPROXYTUNNEL(3)\fP
-.IP CURLOPT_CONNECT_TO
-Connect to a specific host and port. See \fICURLOPT_CONNECT_TO(3)\fP
-.IP CURLOPT_SOCKS5_AUTH
-Socks5 authentication methods. See \fICURLOPT_SOCKS5_AUTH(3)\fP
-.IP CURLOPT_SOCKS5_GSSAPI_SERVICE
-\fBDeprecated option\fP Socks5 GSSAPI service name.
-See \fICURLOPT_SOCKS5_GSSAPI_SERVICE(3)\fP
-.IP CURLOPT_SOCKS5_GSSAPI_NEC
-Socks5 GSSAPI NEC mode. See \fICURLOPT_SOCKS5_GSSAPI_NEC(3)\fP
-.IP CURLOPT_PROXY_SERVICE_NAME
-Proxy authentication service name. \fICURLOPT_PROXY_SERVICE_NAME(3)\fP
-.IP CURLOPT_HAPROXYPROTOCOL
-Send an HAProxy PROXY protocol v1 header. See \fICURLOPT_HAPROXYPROTOCOL(3)\fP
-.IP CURLOPT_HAPROXY_CLIENT_IP
-Spoof the client IP in an HAProxy PROXY protocol v1 header. See \fICURLOPT_HAPROXY_CLIENT_IP(3)\fP
-.IP CURLOPT_SERVICE_NAME
-Authentication service name. \fICURLOPT_SERVICE_NAME(3)\fP
-.IP CURLOPT_INTERFACE
-Bind connection locally to this. See \fICURLOPT_INTERFACE(3)\fP
-.IP CURLOPT_LOCALPORT
-Bind connection locally to this port. See \fICURLOPT_LOCALPORT(3)\fP
-.IP CURLOPT_LOCALPORTRANGE
-Bind connection locally to port range. See \fICURLOPT_LOCALPORTRANGE(3)\fP
-.IP CURLOPT_DNS_CACHE_TIMEOUT
-Timeout for DNS cache. See \fICURLOPT_DNS_CACHE_TIMEOUT(3)\fP
-.IP CURLOPT_DNS_USE_GLOBAL_CACHE
-\fBOBSOLETE\fP Enable global DNS cache.
-See \fICURLOPT_DNS_USE_GLOBAL_CACHE(3)\fP
-.IP CURLOPT_DOH_URL
-Use this DoH server for name resolves. See \fICURLOPT_DOH_URL(3)\fP
-.IP CURLOPT_BUFFERSIZE
-Ask for alternate buffer size. See \fICURLOPT_BUFFERSIZE(3)\fP
-.IP CURLOPT_PORT
-Port number to connect to. See \fICURLOPT_PORT(3)\fP
-.IP CURLOPT_TCP_FASTOPEN
-Enable TCP Fast Open. See \fICURLOPT_TCP_FASTOPEN(3)\fP
-.IP CURLOPT_TCP_NODELAY
-Disable the Nagle algorithm. See \fICURLOPT_TCP_NODELAY(3)\fP
-.IP CURLOPT_ADDRESS_SCOPE
-IPv6 scope for local addresses. See \fICURLOPT_ADDRESS_SCOPE(3)\fP
-.IP CURLOPT_TCP_KEEPALIVE
-Enable TCP keep-alive. See \fICURLOPT_TCP_KEEPALIVE(3)\fP
-.IP CURLOPT_TCP_KEEPIDLE
-Idle time before sending keep-alive. See \fICURLOPT_TCP_KEEPIDLE(3)\fP
-.IP CURLOPT_TCP_KEEPINTVL
-Interval between keep-alive probes. See \fICURLOPT_TCP_KEEPINTVL(3)\fP
-.IP CURLOPT_UNIX_SOCKET_PATH
-Path to a Unix domain socket. See \fICURLOPT_UNIX_SOCKET_PATH(3)\fP
-.IP CURLOPT_ABSTRACT_UNIX_SOCKET
-Path to an abstract Unix domain socket. See \fICURLOPT_ABSTRACT_UNIX_SOCKET(3)\fP
-.SH NAMES and PASSWORDS OPTIONS (Authentication)
-.IP CURLOPT_NETRC
-Enable .netrc parsing. See \fICURLOPT_NETRC(3)\fP
-.IP CURLOPT_NETRC_FILE
-\&.netrc file name. See \fICURLOPT_NETRC_FILE(3)\fP
-.IP CURLOPT_USERPWD
-User name and password. See \fICURLOPT_USERPWD(3)\fP
-.IP CURLOPT_PROXYUSERPWD
-Proxy user name and password. See \fICURLOPT_PROXYUSERPWD(3)\fP
-.IP CURLOPT_USERNAME
-User name. See \fICURLOPT_USERNAME(3)\fP
-.IP CURLOPT_PASSWORD
-Password. See \fICURLOPT_PASSWORD(3)\fP
-.IP CURLOPT_LOGIN_OPTIONS
-Login options. See \fICURLOPT_LOGIN_OPTIONS(3)\fP
-.IP CURLOPT_PROXYUSERNAME
-Proxy user name. See \fICURLOPT_PROXYUSERNAME(3)\fP
-.IP CURLOPT_PROXYPASSWORD
-Proxy password. See \fICURLOPT_PROXYPASSWORD(3)\fP
-.IP CURLOPT_HTTPAUTH
-HTTP server authentication methods. See \fICURLOPT_HTTPAUTH(3)\fP
-.IP CURLOPT_TLSAUTH_USERNAME
-TLS authentication user name. See \fICURLOPT_TLSAUTH_USERNAME(3)\fP
-.IP CURLOPT_PROXY_TLSAUTH_USERNAME
-Proxy TLS authentication user name. See \fICURLOPT_PROXY_TLSAUTH_USERNAME(3)\fP
-.IP CURLOPT_TLSAUTH_PASSWORD
-TLS authentication password. See \fICURLOPT_TLSAUTH_PASSWORD(3)\fP
-.IP CURLOPT_PROXY_TLSAUTH_PASSWORD
-Proxy TLS authentication password. See \fICURLOPT_PROXY_TLSAUTH_PASSWORD(3)\fP
-.IP CURLOPT_TLSAUTH_TYPE
-TLS authentication methods. See \fICURLOPT_TLSAUTH_TYPE(3)\fP
-.IP CURLOPT_PROXY_TLSAUTH_TYPE
-Proxy TLS authentication methods. See \fICURLOPT_PROXY_TLSAUTH_TYPE(3)\fP
-.IP CURLOPT_PROXYAUTH
-HTTP proxy authentication methods. See \fICURLOPT_PROXYAUTH(3)\fP
-.IP CURLOPT_SASL_AUTHZID
-SASL authorization identity (identity to act as). See \fICURLOPT_SASL_AUTHZID(3)\fP
-.IP CURLOPT_SASL_IR
-Enable SASL initial response. See \fICURLOPT_SASL_IR(3)\fP
-.IP CURLOPT_XOAUTH2_BEARER
-OAuth2 bearer token. See \fICURLOPT_XOAUTH2_BEARER(3)\fP
-.IP CURLOPT_DISALLOW_USERNAME_IN_URL
-Do not allow username in URL. See \fICURLOPT_DISALLOW_USERNAME_IN_URL(3)\fP
-.SH HTTP OPTIONS
-.IP CURLOPT_AUTOREFERER
-Automatically set Referer: header. See \fICURLOPT_AUTOREFERER(3)\fP
-.IP CURLOPT_ACCEPT_ENCODING
-Accept-Encoding and automatic decompressing data. See \fICURLOPT_ACCEPT_ENCODING(3)\fP
-.IP CURLOPT_TRANSFER_ENCODING
-Request Transfer-Encoding. See \fICURLOPT_TRANSFER_ENCODING(3)\fP
-.IP CURLOPT_FOLLOWLOCATION
-Follow HTTP redirects. See \fICURLOPT_FOLLOWLOCATION(3)\fP
-.IP CURLOPT_UNRESTRICTED_AUTH
-Do not restrict authentication to original host. \fICURLOPT_UNRESTRICTED_AUTH(3)\fP
-.IP CURLOPT_MAXREDIRS
-Maximum number of redirects to follow. See \fICURLOPT_MAXREDIRS(3)\fP
-.IP CURLOPT_POSTREDIR
-How to act on redirects after POST. See \fICURLOPT_POSTREDIR(3)\fP
-.IP CURLOPT_PUT
-\fBDeprecated option\fP Issue an HTTP PUT request. See \fICURLOPT_PUT(3)\fP
-.IP CURLOPT_POST
-Issue an HTTP POST request. See \fICURLOPT_POST(3)\fP
-.IP CURLOPT_POSTFIELDS
-Send a POST with this data. See \fICURLOPT_POSTFIELDS(3)\fP
-.IP CURLOPT_POSTFIELDSIZE
-The POST data is this big. See \fICURLOPT_POSTFIELDSIZE(3)\fP
-.IP CURLOPT_POSTFIELDSIZE_LARGE
-The POST data is this big. See \fICURLOPT_POSTFIELDSIZE_LARGE(3)\fP
-.IP CURLOPT_COPYPOSTFIELDS
-Send a POST with this data - and copy it. See \fICURLOPT_COPYPOSTFIELDS(3)\fP
-.IP CURLOPT_HTTPPOST
-\fBDeprecated option\fP Multipart formpost HTTP POST.
-See \fICURLOPT_HTTPPOST(3)\fP
-.IP CURLOPT_REFERER
-Referer: header. See \fICURLOPT_REFERER(3)\fP
-.IP CURLOPT_USERAGENT
-User-Agent: header. See \fICURLOPT_USERAGENT(3)\fP
-.IP CURLOPT_HTTPHEADER
-Custom HTTP headers. See \fICURLOPT_HTTPHEADER(3)\fP
-.IP CURLOPT_HEADEROPT
-Control custom headers. See \fICURLOPT_HEADEROPT(3)\fP
-.IP CURLOPT_PROXYHEADER
-Custom HTTP headers sent to proxy. See \fICURLOPT_PROXYHEADER(3)\fP
-.IP CURLOPT_HTTP200ALIASES
-Alternative versions of 200 OK. See \fICURLOPT_HTTP200ALIASES(3)\fP
-.IP CURLOPT_COOKIE
-Cookie(s) to send. See \fICURLOPT_COOKIE(3)\fP
-.IP CURLOPT_COOKIEFILE
-File to read cookies from. See \fICURLOPT_COOKIEFILE(3)\fP
-.IP CURLOPT_COOKIEJAR
-File to write cookies to. See \fICURLOPT_COOKIEJAR(3)\fP
-.IP CURLOPT_COOKIESESSION
-Start a new cookie session. See \fICURLOPT_COOKIESESSION(3)\fP
-.IP CURLOPT_COOKIELIST
-Add or control cookies. See \fICURLOPT_COOKIELIST(3)\fP
-.IP CURLOPT_ALTSVC
-Specify the Alt-Svc: cache file name. See \fICURLOPT_ALTSVC(3)\fP
-.IP CURLOPT_ALTSVC_CTRL
-Enable and configure Alt-Svc: treatment. See \fICURLOPT_ALTSVC_CTRL(3)\fP
-.IP CURLOPT_HSTS
-Set HSTS cache file. See \fICURLOPT_HSTS(3)\fP
-.IP CURLOPT_HSTS_CTRL
-Enable HSTS. See \fICURLOPT_HSTS_CTRL(3)\fP
-.IP CURLOPT_HSTSREADFUNCTION
-Set HSTS read callback. See \fICURLOPT_HSTSREADFUNCTION(3)\fP
-.IP CURLOPT_HSTSREADDATA
-Pass pointer to the HSTS read callback. See \fICURLOPT_HSTSREADDATA(3)\fP
-.IP CURLOPT_HSTSWRITEFUNCTION
-Set HSTS write callback. See \fICURLOPT_HSTSWRITEFUNCTION(3)\fP
-.IP CURLOPT_HSTSWRITEDATA
-Pass pointer to the HSTS write callback. See \fICURLOPT_HSTSWRITEDATA(3)\fP
-.IP CURLOPT_HTTPGET
-Do an HTTP GET request. See \fICURLOPT_HTTPGET(3)\fP
-.IP CURLOPT_REQUEST_TARGET
-Set the request target. \fICURLOPT_REQUEST_TARGET(3)\fP
-.IP CURLOPT_HTTP_VERSION
-HTTP version to use. \fICURLOPT_HTTP_VERSION(3)\fP
-.IP CURLOPT_HTTP09_ALLOWED
-Allow HTTP/0.9 responses. \fICURLOPT_HTTP09_ALLOWED(3)\fP
-.IP CURLOPT_IGNORE_CONTENT_LENGTH
-Ignore Content-Length. See \fICURLOPT_IGNORE_CONTENT_LENGTH(3)\fP
-.IP CURLOPT_HTTP_CONTENT_DECODING
-Disable Content decoding. See \fICURLOPT_HTTP_CONTENT_DECODING(3)\fP
-.IP CURLOPT_HTTP_TRANSFER_DECODING
-Disable Transfer decoding. See \fICURLOPT_HTTP_TRANSFER_DECODING(3)\fP
-.IP CURLOPT_EXPECT_100_TIMEOUT_MS
-100-continue timeout. See \fICURLOPT_EXPECT_100_TIMEOUT_MS(3)\fP
-.IP CURLOPT_TRAILERFUNCTION
-Set callback for sending trailing headers. See
-\fICURLOPT_TRAILERFUNCTION(3)\fP
-.IP CURLOPT_TRAILERDATA
-Custom pointer passed to the trailing headers callback. See
-\fICURLOPT_TRAILERDATA(3)\fP
-.IP CURLOPT_PIPEWAIT
-Wait on connection to pipeline on it. See \fICURLOPT_PIPEWAIT(3)\fP
-.IP CURLOPT_STREAM_DEPENDS
-This HTTP/2 stream depends on another. See \fICURLOPT_STREAM_DEPENDS(3)\fP
-.IP CURLOPT_STREAM_DEPENDS_E
-This HTTP/2 stream depends on another exclusively. See
-\fICURLOPT_STREAM_DEPENDS_E(3)\fP
-.IP CURLOPT_STREAM_WEIGHT
-Set this HTTP/2 stream's weight. See \fICURLOPT_STREAM_WEIGHT(3)\fP
-.SH SMTP OPTIONS
-.IP CURLOPT_MAIL_FROM
-Address of the sender. See \fICURLOPT_MAIL_FROM(3)\fP
-.IP CURLOPT_MAIL_RCPT
-Address of the recipients. See \fICURLOPT_MAIL_RCPT(3)\fP
-.IP CURLOPT_MAIL_AUTH
-Authentication address. See \fICURLOPT_MAIL_AUTH(3)\fP
-.IP CURLOPT_MAIL_RCPT_ALLOWFAILS
-Allow RCPT TO command to fail for some recipients. See
-\fICURLOPT_MAIL_RCPT_ALLOWFAILS(3)\fP
-.SH TFTP OPTIONS
-.IP CURLOPT_TFTP_BLKSIZE
-TFTP block size. See \fICURLOPT_TFTP_BLKSIZE(3)\fP
-.IP CURLOPT_TFTP_NO_OPTIONS
-Do not send TFTP options requests. See \fICURLOPT_TFTP_NO_OPTIONS(3)\fP
-.SH FTP OPTIONS
-.IP CURLOPT_FTPPORT
-Use active FTP. See \fICURLOPT_FTPPORT(3)\fP
-.IP CURLOPT_QUOTE
-Commands to run before transfer. See \fICURLOPT_QUOTE(3)\fP
-.IP CURLOPT_POSTQUOTE
-Commands to run after transfer. See \fICURLOPT_POSTQUOTE(3)\fP
-.IP CURLOPT_PREQUOTE
-Commands to run just before transfer. See \fICURLOPT_PREQUOTE(3)\fP
-.IP CURLOPT_APPEND
-Append to remote file. See \fICURLOPT_APPEND(3)\fP
-.IP CURLOPT_FTP_USE_EPRT
-Use EPRT. See \fICURLOPT_FTP_USE_EPRT(3)\fP
-.IP CURLOPT_FTP_USE_EPSV
-Use EPSV. See \fICURLOPT_FTP_USE_EPSV(3)\fP
-.IP CURLOPT_FTP_USE_PRET
-Use PRET. See \fICURLOPT_FTP_USE_PRET(3)\fP
-.IP CURLOPT_FTP_CREATE_MISSING_DIRS
-Create missing directories on the remote server. See \fICURLOPT_FTP_CREATE_MISSING_DIRS(3)\fP
-.IP CURLOPT_SERVER_RESPONSE_TIMEOUT
-Timeout for server responses. See \fICURLOPT_SERVER_RESPONSE_TIMEOUT(3)\fP
-.IP CURLOPT_FTP_ALTERNATIVE_TO_USER
-Alternative to USER. See \fICURLOPT_FTP_ALTERNATIVE_TO_USER(3)\fP
-.IP CURLOPT_FTP_SKIP_PASV_IP
-Ignore the IP address in the PASV response. See \fICURLOPT_FTP_SKIP_PASV_IP(3)\fP
-.IP CURLOPT_FTPSSLAUTH
-Control how to do TLS. See \fICURLOPT_FTPSSLAUTH(3)\fP
-.IP CURLOPT_FTP_SSL_CCC
-Back to non-TLS again after authentication. See \fICURLOPT_FTP_SSL_CCC(3)\fP
-.IP CURLOPT_FTP_ACCOUNT
-Send ACCT command. See \fICURLOPT_FTP_ACCOUNT(3)\fP
-.IP CURLOPT_FTP_FILEMETHOD
-Specify how to reach files. See \fICURLOPT_FTP_FILEMETHOD(3)\fP
-.SH RTSP OPTIONS
-.IP CURLOPT_RTSP_REQUEST
-RTSP request. See \fICURLOPT_RTSP_REQUEST(3)\fP
-.IP CURLOPT_RTSP_SESSION_ID
-RTSP session-id. See \fICURLOPT_RTSP_SESSION_ID(3)\fP
-.IP CURLOPT_RTSP_STREAM_URI
-RTSP stream URI. See \fICURLOPT_RTSP_STREAM_URI(3)\fP
-.IP CURLOPT_RTSP_TRANSPORT
-RTSP Transport: header. See \fICURLOPT_RTSP_TRANSPORT(3)\fP
-.IP CURLOPT_RTSP_CLIENT_CSEQ
-Client CSEQ number. See \fICURLOPT_RTSP_CLIENT_CSEQ(3)\fP
-.IP CURLOPT_RTSP_SERVER_CSEQ
-CSEQ number for RTSP Server->Client request. See \fICURLOPT_RTSP_SERVER_CSEQ(3)\fP
-.IP CURLOPT_AWS_SIGV4
-AWS HTTP V4 Signature. See \fICURLOPT_AWS_SIGV4(3)\fP
-.SH PROTOCOL OPTIONS
-.IP CURLOPT_TRANSFERTEXT
-Use text transfer. See \fICURLOPT_TRANSFERTEXT(3)\fP
-.IP CURLOPT_PROXY_TRANSFER_MODE
-Add transfer mode to URL over proxy. See \fICURLOPT_PROXY_TRANSFER_MODE(3)\fP
-.IP CURLOPT_CRLF
-Convert newlines. See \fICURLOPT_CRLF(3)\fP
-.IP CURLOPT_RANGE
-Range requests. See \fICURLOPT_RANGE(3)\fP
-.IP CURLOPT_RESUME_FROM
-Resume a transfer. See \fICURLOPT_RESUME_FROM(3)\fP
-.IP CURLOPT_RESUME_FROM_LARGE
-Resume a transfer. See \fICURLOPT_RESUME_FROM_LARGE(3)\fP
-.IP CURLOPT_CURLU
-Set URL to work on with a URL handle. See \fICURLOPT_CURLU(3)\fP
-.IP CURLOPT_CUSTOMREQUEST
-Custom request/method. See \fICURLOPT_CUSTOMREQUEST(3)\fP
-.IP CURLOPT_FILETIME
-Request file modification date and time. See \fICURLOPT_FILETIME(3)\fP
-.IP CURLOPT_DIRLISTONLY
-List only. See \fICURLOPT_DIRLISTONLY(3)\fP
-.IP CURLOPT_NOBODY
-Do not get the body contents. See \fICURLOPT_NOBODY(3)\fP
-.IP CURLOPT_INFILESIZE
-Size of file to send. \fICURLOPT_INFILESIZE(3)\fP
-.IP CURLOPT_INFILESIZE_LARGE
-Size of file to send. \fICURLOPT_INFILESIZE_LARGE(3)\fP
-.IP CURLOPT_UPLOAD
-Upload data. See \fICURLOPT_UPLOAD(3)\fP
-.IP CURLOPT_UPLOAD_BUFFERSIZE
-Set upload buffer size. See \fICURLOPT_UPLOAD_BUFFERSIZE(3)\fP
-.IP CURLOPT_MIMEPOST
-Post/send MIME data. See \fICURLOPT_MIMEPOST(3)\fP
-.IP CURLOPT_MIME_OPTIONS
-Set MIME option flags. See \fICURLOPT_MIME_OPTIONS(3)\fP
-.IP CURLOPT_MAXFILESIZE
-Maximum file size to get. See \fICURLOPT_MAXFILESIZE(3)\fP
-.IP CURLOPT_MAXFILESIZE_LARGE
-Maximum file size to get. See \fICURLOPT_MAXFILESIZE_LARGE(3)\fP
-.IP CURLOPT_TIMECONDITION
-Make a time conditional request. See \fICURLOPT_TIMECONDITION(3)\fP
-.IP CURLOPT_TIMEVALUE
-Time value for the time conditional request. See \fICURLOPT_TIMEVALUE(3)\fP
-.IP CURLOPT_TIMEVALUE_LARGE
-Time value for the time conditional request. See \fICURLOPT_TIMEVALUE_LARGE(3)\fP
-.SH CONNECTION OPTIONS
-.IP CURLOPT_TIMEOUT
-Timeout for the entire request. See \fICURLOPT_TIMEOUT(3)\fP
-.IP CURLOPT_TIMEOUT_MS
-Millisecond timeout for the entire request. See \fICURLOPT_TIMEOUT_MS(3)\fP
-.IP CURLOPT_LOW_SPEED_LIMIT
-Low speed limit to abort transfer. See \fICURLOPT_LOW_SPEED_LIMIT(3)\fP
-.IP CURLOPT_LOW_SPEED_TIME
-Time to be below the speed to trigger low speed abort. See \fICURLOPT_LOW_SPEED_TIME(3)\fP
-.IP CURLOPT_MAX_SEND_SPEED_LARGE
-Cap the upload speed to this. See \fICURLOPT_MAX_SEND_SPEED_LARGE(3)\fP
-.IP CURLOPT_MAX_RECV_SPEED_LARGE
-Cap the download speed to this. See \fICURLOPT_MAX_RECV_SPEED_LARGE(3)\fP
-.IP CURLOPT_MAXCONNECTS
-Maximum number of connections in the connection pool. See \fICURLOPT_MAXCONNECTS(3)\fP
-.IP CURLOPT_FRESH_CONNECT
-Use a new connection. \fICURLOPT_FRESH_CONNECT(3)\fP
-.IP CURLOPT_FORBID_REUSE
-Prevent subsequent connections from reusing this. See \fICURLOPT_FORBID_REUSE(3)\fP
-.IP CURLOPT_MAXAGE_CONN
-Limit the age (idle time) of connections for reuse. See \fICURLOPT_MAXAGE_CONN(3)\fP
-.IP CURLOPT_MAXLIFETIME_CONN
-Limit the age (since creation) of connections for reuse. See \fICURLOPT_MAXLIFETIME_CONN(3)\fP
-.IP CURLOPT_CONNECTTIMEOUT
-Timeout for the connection phase. See \fICURLOPT_CONNECTTIMEOUT(3)\fP
-.IP CURLOPT_CONNECTTIMEOUT_MS
-Millisecond timeout for the connection phase. See \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
-.IP CURLOPT_IPRESOLVE
-IP version to use. See \fICURLOPT_IPRESOLVE(3)\fP
-.IP CURLOPT_CONNECT_ONLY
-Only connect, nothing else. See \fICURLOPT_CONNECT_ONLY(3)\fP
-.IP CURLOPT_USE_SSL
-Use TLS/SSL. See \fICURLOPT_USE_SSL(3)\fP
-.IP CURLOPT_RESOLVE
-Provide fixed/fake name resolves. See \fICURLOPT_RESOLVE(3)\fP
-.IP CURLOPT_DNS_INTERFACE
-Bind name resolves to this interface. See \fICURLOPT_DNS_INTERFACE(3)\fP
-.IP CURLOPT_DNS_LOCAL_IP4
-Bind name resolves to this IP4 address. See \fICURLOPT_DNS_LOCAL_IP4(3)\fP
-.IP CURLOPT_DNS_LOCAL_IP6
-Bind name resolves to this IP6 address. See \fICURLOPT_DNS_LOCAL_IP6(3)\fP
-.IP CURLOPT_DNS_SERVERS
-Preferred DNS servers. See \fICURLOPT_DNS_SERVERS(3)\fP
-.IP CURLOPT_DNS_SHUFFLE_ADDRESSES
-Shuffle addresses before use. See \fICURLOPT_DNS_SHUFFLE_ADDRESSES(3)\fP
-.IP CURLOPT_ACCEPTTIMEOUT_MS
-Timeout for waiting for the server's connect back to be accepted. See \fICURLOPT_ACCEPTTIMEOUT_MS(3)\fP
-.IP CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS
-Timeout for happy eyeballs. See \fICURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS(3)\fP
-.IP CURLOPT_UPKEEP_INTERVAL_MS
-Sets the interval at which connection upkeep are performed. See
-\fICURLOPT_UPKEEP_INTERVAL_MS(3)\fP
-.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
-Proxy client key type. See \fICURLOPT_PROXY_SSLKEYTYPE(3)\fP
-.IP CURLOPT_KEYPASSWD
-Client key password. See \fICURLOPT_KEYPASSWD(3)\fP
-.IP CURLOPT_PROXY_KEYPASSWD
-Proxy client key password. See \fICURLOPT_PROXY_KEYPASSWD(3)\fP
-.IP CURLOPT_SSL_EC_CURVES
-Set key exchange curves. See \fICURLOPT_SSL_EC_CURVES(3)\fP
-.IP CURLOPT_SSL_ENABLE_ALPN
-Enable use of ALPN. See \fICURLOPT_SSL_ENABLE_ALPN(3)\fP
-.IP CURLOPT_SSL_ENABLE_NPN
-\fBOBSOLETE\fP Enable use of NPN. See \fICURLOPT_SSL_ENABLE_NPN(3)\fP
-.IP CURLOPT_SSLENGINE
-Use identifier with SSL engine. See \fICURLOPT_SSLENGINE(3)\fP
-.IP CURLOPT_SSLENGINE_DEFAULT
-Default SSL engine. See \fICURLOPT_SSLENGINE_DEFAULT(3)\fP
-.IP CURLOPT_SSL_FALSESTART
-Enable TLS False Start. See \fICURLOPT_SSL_FALSESTART(3)\fP
-.IP CURLOPT_SSLVERSION
-SSL version to use. See \fICURLOPT_SSLVERSION(3)\fP
-.IP CURLOPT_PROXY_SSLVERSION
-Proxy SSL version to use. See \fICURLOPT_PROXY_SSLVERSION(3)\fP
-.IP CURLOPT_SSL_VERIFYHOST
-Verify the host name in the SSL certificate. See \fICURLOPT_SSL_VERIFYHOST(3)\fP
-.IP CURLOPT_DOH_SSL_VERIFYHOST
-Verify the host name in the DoH (DNS-over-HTTPS) SSL certificate. See
-\fICURLOPT_DOH_SSL_VERIFYHOST(3)\fP
-.IP CURLOPT_PROXY_SSL_VERIFYHOST
-Verify the host name in the proxy SSL certificate. See \fICURLOPT_PROXY_SSL_VERIFYHOST(3)\fP
-.IP CURLOPT_SSL_VERIFYPEER
-Verify the SSL certificate. See \fICURLOPT_SSL_VERIFYPEER(3)\fP
-.IP CURLOPT_DOH_SSL_VERIFYPEER
-Verify the DoH (DNS-over-HTTPS) SSL certificate. See
-\fICURLOPT_DOH_SSL_VERIFYPEER(3)\fP
-.IP CURLOPT_PROXY_SSL_VERIFYPEER
-Verify the proxy SSL certificate. See \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP
-.IP CURLOPT_SSL_VERIFYSTATUS
-Verify the SSL certificate's status. See \fICURLOPT_SSL_VERIFYSTATUS(3)\fP
-.IP CURLOPT_DOH_SSL_VERIFYSTATUS
-Verify the DoH (DNS-over-HTTPS) SSL certificate's status. See
-\fICURLOPT_DOH_SSL_VERIFYSTATUS(3)\fP
-.IP CURLOPT_CAINFO
-CA cert bundle. See \fICURLOPT_CAINFO(3)\fP
-.IP CURLOPT_CAINFO_BLOB
-CA cert bundle memory buffer. See \fICURLOPT_CAINFO_BLOB(3)\fP
-.IP CURLOPT_PROXY_CAINFO
-Proxy CA cert bundle. See \fICURLOPT_PROXY_CAINFO(3)\fP
-.IP CURLOPT_PROXY_CAINFO_BLOB
-Proxy CA cert bundle memory buffer. See \fICURLOPT_PROXY_CAINFO_BLOB(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
-Path to proxy CA cert bundle. See \fICURLOPT_PROXY_CAPATH(3)\fP
-.IP CURLOPT_CRLFILE
-Certificate Revocation List. See \fICURLOPT_CRLFILE(3)\fP
-.IP CURLOPT_PROXY_CRLFILE
-Proxy Certificate Revocation List. See \fICURLOPT_PROXY_CRLFILE(3)\fP
-.IP CURLOPT_CA_CACHE_TIMEOUT
-Timeout for CA cache. See \fICURLOPT_CA_CACHE_TIMEOUT(3)\fP
-.IP CURLOPT_CERTINFO
-Extract certificate info. See \fICURLOPT_CERTINFO(3)\fP
-.IP CURLOPT_PINNEDPUBLICKEY
-Set pinned SSL public key . See \fICURLOPT_PINNEDPUBLICKEY(3)\fP
-.IP CURLOPT_PROXY_PINNEDPUBLICKEY
-Set the proxy's pinned SSL public key. See
-\fICURLOPT_PROXY_PINNEDPUBLICKEY(3)\fP
-.IP CURLOPT_RANDOM_FILE
-\fBOBSOLETE\fP Provide source for entropy random data.
-See \fICURLOPT_RANDOM_FILE(3)\fP
-.IP CURLOPT_EGDSOCKET
-\fBOBSOLETE\fP Identify EGD socket for entropy. See \fICURLOPT_EGDSOCKET(3)\fP
-.IP CURLOPT_SSL_CIPHER_LIST
-Ciphers to use. See \fICURLOPT_SSL_CIPHER_LIST(3)\fP
-.IP CURLOPT_PROXY_SSL_CIPHER_LIST
-Proxy ciphers to use. See \fICURLOPT_PROXY_SSL_CIPHER_LIST(3)\fP
-.IP CURLOPT_TLS13_CIPHERS
-TLS 1.3 cipher suites to use. See \fICURLOPT_TLS13_CIPHERS(3)\fP
-.IP CURLOPT_PROXY_TLS13_CIPHERS
-Proxy TLS 1.3 cipher suites to use. See \fICURLOPT_PROXY_TLS13_CIPHERS(3)\fP
-.IP CURLOPT_SSL_SESSIONID_CACHE
-Disable SSL session-id cache. See \fICURLOPT_SSL_SESSIONID_CACHE(3)\fP
-.IP CURLOPT_SSL_OPTIONS
-Control SSL behavior. See \fICURLOPT_SSL_OPTIONS(3)\fP
-.IP CURLOPT_PROXY_SSL_OPTIONS
-Control proxy SSL behavior. See \fICURLOPT_PROXY_SSL_OPTIONS(3)\fP
-.IP CURLOPT_KRBLEVEL
-Kerberos security level. See \fICURLOPT_KRBLEVEL(3)\fP
-.IP CURLOPT_GSSAPI_DELEGATION
-Disable GSS-API delegation. See \fICURLOPT_GSSAPI_DELEGATION(3)\fP
-.SH SSH OPTIONS
-.IP CURLOPT_SSH_AUTH_TYPES
-SSH authentication types. See \fICURLOPT_SSH_AUTH_TYPES(3)\fP
-.IP CURLOPT_SSH_COMPRESSION
-Enable SSH compression. See \fICURLOPT_SSH_COMPRESSION(3)\fP
-.IP CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
-MD5 of host's public key. See \fICURLOPT_SSH_HOST_PUBLIC_KEY_MD5(3)\fP
-.IP CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256
-SHA256 of host's public key. See \fICURLOPT_SSH_HOST_PUBLIC_KEY_SHA256(3)\fP
-.IP CURLOPT_SSH_PUBLIC_KEYFILE
-File name of public key. See \fICURLOPT_SSH_PUBLIC_KEYFILE(3)\fP
-.IP CURLOPT_SSH_PRIVATE_KEYFILE
-File name of private key. See \fICURLOPT_SSH_PRIVATE_KEYFILE(3)\fP
-.IP CURLOPT_SSH_KNOWNHOSTS
-File name with known hosts. See \fICURLOPT_SSH_KNOWNHOSTS(3)\fP
-.IP CURLOPT_SSH_KEYFUNCTION
-Callback for known hosts handling. See \fICURLOPT_SSH_KEYFUNCTION(3)\fP
-.IP CURLOPT_SSH_KEYDATA
-Custom pointer to pass to ssh key callback. See \fICURLOPT_SSH_KEYDATA(3)\fP
-.IP CURLOPT_SSH_HOSTKEYFUNCTION
-Callback for checking host key handling. See \fICURLOPT_SSH_HOSTKEYFUNCTION(3)\fP
-.IP CURLOPT_SSH_HOSTKEYDATA
-Custom pointer to pass to ssh host key callback. See \fICURLOPT_SSH_HOSTKEYDATA(3)\fP
-.SH WEBSOCKET
-.IP CURLOPT_WS_OPTIONS
-Set WebSocket options. See \fICURLOPT_WS_OPTIONS(3)\fP
-.SH OTHER OPTIONS
-.IP CURLOPT_PRIVATE
-Private pointer to store. See \fICURLOPT_PRIVATE(3)\fP
-.IP CURLOPT_SHARE
-Share object to use. See \fICURLOPT_SHARE(3)\fP
-.IP CURLOPT_NEW_FILE_PERMS
-Mode for creating new remote files. See \fICURLOPT_NEW_FILE_PERMS(3)\fP
-.IP CURLOPT_NEW_DIRECTORY_PERMS
-Mode for creating new remote directories. See \fICURLOPT_NEW_DIRECTORY_PERMS(3)\fP
-.IP CURLOPT_QUICK_EXIT
-To be set by toplevel tools like "curl" to skip lengthy cleanups when they are about to call exit() anyway. See \fICURLOPT_QUICK_EXIT(3)\fP
-.SH TELNET OPTIONS
-.IP CURLOPT_TELNETOPTIONS
-TELNET options. See \fICURLOPT_TELNETOPTIONS(3)\fP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-\fICURLE_OK\fP (zero) means that the option was set properly, non-zero means an
-error occurred as \fI<curl/curl.h>\fP defines. See the \fIlibcurl-errors(3)\fP
-man page for the full list with descriptions.
-
-Strings passed on to libcurl must be shorter than 8000000 bytes, otherwise
-\fIcurl_easy_setopt(3)\fP returns \fBCURLE_BAD_FUNCTION_ARGUMENT\fP (added in
-7.65.0).
-
-\fBCURLE_BAD_FUNCTION_ARGUMENT\fP is returned when the argument to an option
-is invalid, like perhaps out of range.
-
-If you try to set an option that libcurl does not know about, perhaps because
-the library is too old to support it or the option was removed in a recent
-version, this function returns \fICURLE_UNKNOWN_OPTION\fP. If support for the
-option was disabled at compile-time, it returns \fICURLE_NOT_BUILT_IN\fP.
-.SH "SEE ALSO"
-.BR curl_easy_cleanup (3),
-.BR curl_easy_getinfo (3),
-.BR curl_easy_init (3),
-.BR curl_easy_option_by_id (3),
-.BR curl_easy_option_by_name (3),
-.BR curl_easy_option_next (3),
-.BR curl_easy_reset (3),
-.BR curl_multi_setopt (3)
diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md
new file mode 100644
index 000000000..5724b09cb
--- /dev/null
+++ b/docs/libcurl/curl_easy_setopt.md
@@ -0,0 +1,1381 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_setopt
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_cleanup (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_init (3)
+ - curl_easy_option_by_id (3)
+ - curl_easy_option_by_name (3)
+ - curl_easy_option_next (3)
+ - curl_easy_reset (3)
+ - curl_multi_setopt (3)
+---
+
+# NAME
+
+curl_easy_setopt - set options for a curl easy handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
+~~~
+
+# DESCRIPTION
+
+curl_easy_setopt(3) is used to tell libcurl how to behave. By setting the
+appropriate options, the application can change libcurl's behavior. All
+options are set with an *option* followed by a *parameter*. That parameter can
+be a **long**, a **function pointer**, an **object pointer** or a
+**curl_off_t**, depending on what the specific option expects. Read this
+manual carefully as bad input values may cause libcurl to behave badly! You
+can only set one option in each function call. A typical application uses many
+curl_easy_setopt(3) calls in the setup phase.
+
+Options set with this function call are valid for all forthcoming transfers
+performed using this *handle*. The options are not in any way reset between
+transfers, so if you want subsequent transfers with different options, you
+must change them between the transfers. You can optionally reset all options
+back to internal default with curl_easy_reset(3).
+
+Strings passed to libcurl as 'char *' arguments, are copied by the library;
+the string storage associated to the pointer argument may be discarded or
+reused after curl_easy_setopt(3) returns. The only exception to this rule is
+really CURLOPT_POSTFIELDS(3), but the alternative that copies the string
+CURLOPT_COPYPOSTFIELDS(3) has some usage characteristics you need to read up
+on. This function does not accept input strings longer than
+**CURL_MAX_INPUT_LENGTH** (8 MB).
+
+The order in which the options are set does not matter.
+
+Before version 7.17.0, strings were not copied. Instead the user was forced
+keep them available until libcurl no longer needed them.
+
+The *handle* is the return code from a curl_easy_init(3) or
+curl_easy_duphandle(3) call.
+
+# BEHAVIOR OPTIONS
+
+## CURLOPT_VERBOSE
+
+Display verbose information. See CURLOPT_VERBOSE(3)
+
+## CURLOPT_HEADER
+
+Include the header in the body output. See CURLOPT_HEADER(3)
+
+## CURLOPT_NOPROGRESS
+
+Shut off the progress meter. See CURLOPT_NOPROGRESS(3)
+
+## CURLOPT_NOSIGNAL
+
+Do not install signal handlers. See CURLOPT_NOSIGNAL(3)
+
+## CURLOPT_WILDCARDMATCH
+
+Transfer multiple files according to a filename pattern. See
+CURLOPT_WILDCARDMATCH(3)
+
+# CALLBACK OPTIONS
+
+## CURLOPT_WRITEFUNCTION
+
+Callback for writing data. See CURLOPT_WRITEFUNCTION(3)
+
+## CURLOPT_WRITEDATA
+
+Data pointer to pass to the write callback. See CURLOPT_WRITEDATA(3)
+
+## CURLOPT_READFUNCTION
+
+Callback for reading data. See CURLOPT_READFUNCTION(3)
+
+## CURLOPT_READDATA
+
+Data pointer to pass to the read callback. See CURLOPT_READDATA(3)
+
+## CURLOPT_IOCTLFUNCTION
+
+**Deprecated option** Callback for I/O operations.
+See CURLOPT_IOCTLFUNCTION(3)
+
+## CURLOPT_IOCTLDATA
+
+**Deprecated option** Data pointer to pass to the I/O callback.
+See CURLOPT_IOCTLDATA(3)
+
+## CURLOPT_SEEKFUNCTION
+
+Callback for seek operations. See CURLOPT_SEEKFUNCTION(3)
+
+## CURLOPT_SEEKDATA
+
+Data pointer to pass to the seek callback. See CURLOPT_SEEKDATA(3)
+
+## CURLOPT_SOCKOPTFUNCTION
+
+Callback for sockopt operations. See CURLOPT_SOCKOPTFUNCTION(3)
+
+## CURLOPT_SOCKOPTDATA
+
+Data pointer to pass to the sockopt callback. See CURLOPT_SOCKOPTDATA(3)
+
+## CURLOPT_OPENSOCKETFUNCTION
+
+Callback for socket creation. See CURLOPT_OPENSOCKETFUNCTION(3)
+
+## CURLOPT_OPENSOCKETDATA
+
+Data pointer to pass to the open socket callback. See CURLOPT_OPENSOCKETDATA(3)
+
+## CURLOPT_CLOSESOCKETFUNCTION
+
+Callback for closing socket. See CURLOPT_CLOSESOCKETFUNCTION(3)
+
+## CURLOPT_CLOSESOCKETDATA
+
+Data pointer to pass to the close socket callback. See CURLOPT_CLOSESOCKETDATA(3)
+
+## CURLOPT_PROGRESSFUNCTION
+
+**OBSOLETE** callback for progress meter.
+See CURLOPT_PROGRESSFUNCTION(3)
+
+## CURLOPT_PROGRESSDATA
+
+Data pointer to pass to the progress meter callback. See CURLOPT_PROGRESSDATA(3)
+
+## CURLOPT_XFERINFOFUNCTION
+
+Callback for progress meter. See CURLOPT_XFERINFOFUNCTION(3)
+
+## CURLOPT_XFERINFODATA
+
+Data pointer to pass to the progress meter callback. See CURLOPT_XFERINFODATA(3)
+
+## CURLOPT_HEADERFUNCTION
+
+Callback for writing received headers. See CURLOPT_HEADERFUNCTION(3)
+
+## CURLOPT_HEADERDATA
+
+Data pointer to pass to the header callback. See CURLOPT_HEADERDATA(3)
+
+## CURLOPT_DEBUGFUNCTION
+
+Callback for debug information. See CURLOPT_DEBUGFUNCTION(3)
+
+## CURLOPT_DEBUGDATA
+
+Data pointer to pass to the debug callback. See CURLOPT_DEBUGDATA(3)
+
+## CURLOPT_SSL_CTX_FUNCTION
+
+Callback for SSL context logic. See CURLOPT_SSL_CTX_FUNCTION(3)
+
+## CURLOPT_SSL_CTX_DATA
+
+Data pointer to pass to the SSL context callback. See CURLOPT_SSL_CTX_DATA(3)
+
+## CURLOPT_CONV_TO_NETWORK_FUNCTION
+
+**OBSOLETE** Callback for code base conversion.
+See CURLOPT_CONV_TO_NETWORK_FUNCTION(3)
+
+## CURLOPT_CONV_FROM_NETWORK_FUNCTION
+
+**OBSOLETE** Callback for code base conversion.
+See CURLOPT_CONV_FROM_NETWORK_FUNCTION(3)
+
+## CURLOPT_CONV_FROM_UTF8_FUNCTION
+
+**OBSOLETE** Callback for code base conversion.
+See CURLOPT_CONV_FROM_UTF8_FUNCTION(3)
+
+## CURLOPT_INTERLEAVEFUNCTION
+
+Callback for RTSP interleaved data. See CURLOPT_INTERLEAVEFUNCTION(3)
+
+## CURLOPT_INTERLEAVEDATA
+
+Data pointer to pass to the RTSP interleave callback. See CURLOPT_INTERLEAVEDATA(3)
+
+## CURLOPT_CHUNK_BGN_FUNCTION
+
+Callback for wildcard download start of chunk. See CURLOPT_CHUNK_BGN_FUNCTION(3)
+
+## CURLOPT_CHUNK_END_FUNCTION
+
+Callback for wildcard download end of chunk. See CURLOPT_CHUNK_END_FUNCTION(3)
+
+## CURLOPT_CHUNK_DATA
+
+Data pointer to pass to the chunk callbacks. See CURLOPT_CHUNK_DATA(3)
+
+## CURLOPT_FNMATCH_FUNCTION
+
+Callback for wildcard matching. See CURLOPT_FNMATCH_FUNCTION(3)
+
+## CURLOPT_FNMATCH_DATA
+
+Data pointer to pass to the wildcard matching callback. See CURLOPT_FNMATCH_DATA(3)
+
+## CURLOPT_SUPPRESS_CONNECT_HEADERS
+
+Suppress proxy CONNECT response headers from user callbacks. See
+CURLOPT_SUPPRESS_CONNECT_HEADERS(3)
+
+## CURLOPT_RESOLVER_START_FUNCTION
+
+Callback to be called before a new resolve request is started. See
+CURLOPT_RESOLVER_START_FUNCTION(3)
+
+## CURLOPT_RESOLVER_START_DATA
+
+Data pointer to pass to resolver start callback. See CURLOPT_RESOLVER_START_DATA(3)
+
+## CURLOPT_PREREQFUNCTION
+
+Callback to be called after a connection is established but before a request
+is made on that connection. See CURLOPT_PREREQFUNCTION(3)
+
+## CURLOPT_PREREQDATA
+
+Data pointer to pass to the CURLOPT_PREREQFUNCTION callback. See
+CURLOPT_PREREQDATA(3)
+
+# ERROR OPTIONS
+
+## CURLOPT_ERRORBUFFER
+
+Error message buffer. See CURLOPT_ERRORBUFFER(3)
+
+## CURLOPT_STDERR
+
+stderr replacement stream. See CURLOPT_STDERR(3)
+
+## CURLOPT_FAILONERROR
+
+Fail on HTTP 4xx errors. CURLOPT_FAILONERROR(3)
+
+## CURLOPT_KEEP_SENDING_ON_ERROR
+
+Keep sending on HTTP >= 300 errors. CURLOPT_KEEP_SENDING_ON_ERROR(3)
+
+# NETWORK OPTIONS
+
+## CURLOPT_URL
+
+URL to work on. See CURLOPT_URL(3)
+
+## CURLOPT_PATH_AS_IS
+
+Disable squashing /../ and /./ sequences in the path. See CURLOPT_PATH_AS_IS(3)
+
+## CURLOPT_PROTOCOLS
+
+**Deprecated option** Allowed protocols. See CURLOPT_PROTOCOLS(3)
+
+## CURLOPT_PROTOCOLS_STR
+
+Allowed protocols. See CURLOPT_PROTOCOLS_STR(3)
+
+## CURLOPT_REDIR_PROTOCOLS
+
+**Deprecated option** Protocols to allow redirects to. See
+CURLOPT_REDIR_PROTOCOLS(3)
+
+## CURLOPT_REDIR_PROTOCOLS_STR
+
+Protocols to allow redirects to. See CURLOPT_REDIR_PROTOCOLS_STR(3)
+
+## CURLOPT_DEFAULT_PROTOCOL
+
+Default protocol. See CURLOPT_DEFAULT_PROTOCOL(3)
+
+## CURLOPT_PROXY
+
+Proxy to use. See CURLOPT_PROXY(3)
+
+## CURLOPT_PRE_PROXY
+
+Socks proxy to use. See CURLOPT_PRE_PROXY(3)
+
+## CURLOPT_PROXYPORT
+
+Proxy port to use. See CURLOPT_PROXYPORT(3)
+
+## CURLOPT_PROXYTYPE
+
+Proxy type. See CURLOPT_PROXYTYPE(3)
+
+## CURLOPT_NOPROXY
+
+Filter out hosts from proxy use. CURLOPT_NOPROXY(3)
+
+## CURLOPT_HTTPPROXYTUNNEL
+
+Tunnel through the HTTP proxy. CURLOPT_HTTPPROXYTUNNEL(3)
+
+## CURLOPT_CONNECT_TO
+
+Connect to a specific host and port. See CURLOPT_CONNECT_TO(3)
+
+## CURLOPT_SOCKS5_AUTH
+
+Socks5 authentication methods. See CURLOPT_SOCKS5_AUTH(3)
+
+## CURLOPT_SOCKS5_GSSAPI_SERVICE
+
+**Deprecated option** Socks5 GSSAPI service name.
+See CURLOPT_SOCKS5_GSSAPI_SERVICE(3)
+
+## CURLOPT_SOCKS5_GSSAPI_NEC
+
+Socks5 GSSAPI NEC mode. See CURLOPT_SOCKS5_GSSAPI_NEC(3)
+
+## CURLOPT_PROXY_SERVICE_NAME
+
+Proxy authentication service name. CURLOPT_PROXY_SERVICE_NAME(3)
+
+## CURLOPT_HAPROXYPROTOCOL
+
+Send an HAProxy PROXY protocol v1 header. See CURLOPT_HAPROXYPROTOCOL(3)
+
+## CURLOPT_HAPROXY_CLIENT_IP
+
+Spoof the client IP in an HAProxy PROXY protocol v1 header. See
+CURLOPT_HAPROXY_CLIENT_IP(3)
+
+## CURLOPT_SERVICE_NAME
+
+Authentication service name. CURLOPT_SERVICE_NAME(3)
+
+## CURLOPT_INTERFACE
+
+Bind connection locally to this. See CURLOPT_INTERFACE(3)
+
+## CURLOPT_LOCALPORT
+
+Bind connection locally to this port. See CURLOPT_LOCALPORT(3)
+
+## CURLOPT_LOCALPORTRANGE
+
+Bind connection locally to port range. See CURLOPT_LOCALPORTRANGE(3)
+
+## CURLOPT_DNS_CACHE_TIMEOUT
+
+Timeout for DNS cache. See CURLOPT_DNS_CACHE_TIMEOUT(3)
+
+## CURLOPT_DNS_USE_GLOBAL_CACHE
+
+**OBSOLETE** Enable global DNS cache.
+See CURLOPT_DNS_USE_GLOBAL_CACHE(3)
+
+## CURLOPT_DOH_URL
+
+Use this DoH server for name resolves. See CURLOPT_DOH_URL(3)
+
+## CURLOPT_BUFFERSIZE
+
+Ask for alternate buffer size. See CURLOPT_BUFFERSIZE(3)
+
+## CURLOPT_PORT
+
+Port number to connect to. See CURLOPT_PORT(3)
+
+## CURLOPT_TCP_FASTOPEN
+
+Enable TCP Fast Open. See CURLOPT_TCP_FASTOPEN(3)
+
+## CURLOPT_TCP_NODELAY
+
+Disable the Nagle algorithm. See CURLOPT_TCP_NODELAY(3)
+
+## CURLOPT_ADDRESS_SCOPE
+
+IPv6 scope for local addresses. See CURLOPT_ADDRESS_SCOPE(3)
+
+## CURLOPT_TCP_KEEPALIVE
+
+Enable TCP keep-alive. See CURLOPT_TCP_KEEPALIVE(3)
+
+## CURLOPT_TCP_KEEPIDLE
+
+Idle time before sending keep-alive. See CURLOPT_TCP_KEEPIDLE(3)
+
+## CURLOPT_TCP_KEEPINTVL
+
+Interval between keep-alive probes. See CURLOPT_TCP_KEEPINTVL(3)
+
+## CURLOPT_UNIX_SOCKET_PATH
+
+Path to a Unix domain socket. See CURLOPT_UNIX_SOCKET_PATH(3)
+
+## CURLOPT_ABSTRACT_UNIX_SOCKET
+
+Path to an abstract Unix domain socket. See CURLOPT_ABSTRACT_UNIX_SOCKET(3)
+
+# NAMES and PASSWORDS OPTIONS (Authentication)
+
+## CURLOPT_NETRC
+
+Enable .netrc parsing. See CURLOPT_NETRC(3)
+
+## CURLOPT_NETRC_FILE
+
+.netrc filename. See CURLOPT_NETRC_FILE(3)
+
+## CURLOPT_USERPWD
+
+User name and password. See CURLOPT_USERPWD(3)
+
+## CURLOPT_PROXYUSERPWD
+
+Proxy user name and password. See CURLOPT_PROXYUSERPWD(3)
+
+## CURLOPT_USERNAME
+
+User name. See CURLOPT_USERNAME(3)
+
+## CURLOPT_PASSWORD
+
+Password. See CURLOPT_PASSWORD(3)
+
+## CURLOPT_LOGIN_OPTIONS
+
+Login options. See CURLOPT_LOGIN_OPTIONS(3)
+
+## CURLOPT_PROXYUSERNAME
+
+Proxy user name. See CURLOPT_PROXYUSERNAME(3)
+
+## CURLOPT_PROXYPASSWORD
+
+Proxy password. See CURLOPT_PROXYPASSWORD(3)
+
+## CURLOPT_HTTPAUTH
+
+HTTP server authentication methods. See CURLOPT_HTTPAUTH(3)
+
+## CURLOPT_TLSAUTH_USERNAME
+
+TLS authentication user name. See CURLOPT_TLSAUTH_USERNAME(3)
+
+## CURLOPT_PROXY_TLSAUTH_USERNAME
+
+Proxy TLS authentication user name. See CURLOPT_PROXY_TLSAUTH_USERNAME(3)
+
+## CURLOPT_TLSAUTH_PASSWORD
+
+TLS authentication password. See CURLOPT_TLSAUTH_PASSWORD(3)
+
+## CURLOPT_PROXY_TLSAUTH_PASSWORD
+
+Proxy TLS authentication password. See CURLOPT_PROXY_TLSAUTH_PASSWORD(3)
+
+## CURLOPT_TLSAUTH_TYPE
+
+TLS authentication methods. See CURLOPT_TLSAUTH_TYPE(3)
+
+## CURLOPT_PROXY_TLSAUTH_TYPE
+
+Proxy TLS authentication methods. See CURLOPT_PROXY_TLSAUTH_TYPE(3)
+
+## CURLOPT_PROXYAUTH
+
+HTTP proxy authentication methods. See CURLOPT_PROXYAUTH(3)
+
+## CURLOPT_SASL_AUTHZID
+
+SASL authorization identity (identity to act as). See CURLOPT_SASL_AUTHZID(3)
+
+## CURLOPT_SASL_IR
+
+Enable SASL initial response. See CURLOPT_SASL_IR(3)
+
+## CURLOPT_XOAUTH2_BEARER
+
+OAuth2 bearer token. See CURLOPT_XOAUTH2_BEARER(3)
+
+## CURLOPT_DISALLOW_USERNAME_IN_URL
+
+Do not allow username in URL. See CURLOPT_DISALLOW_USERNAME_IN_URL(3)
+
+# HTTP OPTIONS
+
+## CURLOPT_AUTOREFERER
+
+Automatically set Referer: header. See CURLOPT_AUTOREFERER(3)
+
+## CURLOPT_ACCEPT_ENCODING
+
+Accept-Encoding and automatic decompressing data. See CURLOPT_ACCEPT_ENCODING(3)
+
+## CURLOPT_TRANSFER_ENCODING
+
+Request Transfer-Encoding. See CURLOPT_TRANSFER_ENCODING(3)
+
+## CURLOPT_FOLLOWLOCATION
+
+Follow HTTP redirects. See CURLOPT_FOLLOWLOCATION(3)
+
+## CURLOPT_UNRESTRICTED_AUTH
+
+Do not restrict authentication to original host. CURLOPT_UNRESTRICTED_AUTH(3)
+
+## CURLOPT_MAXREDIRS
+
+Maximum number of redirects to follow. See CURLOPT_MAXREDIRS(3)
+
+## CURLOPT_POSTREDIR
+
+How to act on redirects after POST. See CURLOPT_POSTREDIR(3)
+
+## CURLOPT_PUT
+
+**Deprecated option** Issue an HTTP PUT request. See CURLOPT_PUT(3)
+
+## CURLOPT_POST
+
+Issue an HTTP POST request. See CURLOPT_POST(3)
+
+## CURLOPT_POSTFIELDS
+
+Send a POST with this data. See CURLOPT_POSTFIELDS(3)
+
+## CURLOPT_POSTFIELDSIZE
+
+The POST data is this big. See CURLOPT_POSTFIELDSIZE(3)
+
+## CURLOPT_POSTFIELDSIZE_LARGE
+
+The POST data is this big. See CURLOPT_POSTFIELDSIZE_LARGE(3)
+
+## CURLOPT_COPYPOSTFIELDS
+
+Send a POST with this data - and copy it. See CURLOPT_COPYPOSTFIELDS(3)
+
+## CURLOPT_HTTPPOST
+
+**Deprecated option** Multipart formpost HTTP POST.
+See CURLOPT_HTTPPOST(3)
+
+## CURLOPT_REFERER
+
+Referer: header. See CURLOPT_REFERER(3)
+
+## CURLOPT_USERAGENT
+
+User-Agent: header. See CURLOPT_USERAGENT(3)
+
+## CURLOPT_HTTPHEADER
+
+Custom HTTP headers. See CURLOPT_HTTPHEADER(3)
+
+## CURLOPT_HEADEROPT
+
+Control custom headers. See CURLOPT_HEADEROPT(3)
+
+## CURLOPT_PROXYHEADER
+
+Custom HTTP headers sent to proxy. See CURLOPT_PROXYHEADER(3)
+
+## CURLOPT_HTTP200ALIASES
+
+Alternative versions of 200 OK. See CURLOPT_HTTP200ALIASES(3)
+
+## CURLOPT_COOKIE
+
+Cookie(s) to send. See CURLOPT_COOKIE(3)
+
+## CURLOPT_COOKIEFILE
+
+File to read cookies from. See CURLOPT_COOKIEFILE(3)
+
+## CURLOPT_COOKIEJAR
+
+File to write cookies to. See CURLOPT_COOKIEJAR(3)
+
+## CURLOPT_COOKIESESSION
+
+Start a new cookie session. See CURLOPT_COOKIESESSION(3)
+
+## CURLOPT_COOKIELIST
+
+Add or control cookies. See CURLOPT_COOKIELIST(3)
+
+## CURLOPT_ALTSVC
+
+Specify the Alt-Svc: cache filename. See CURLOPT_ALTSVC(3)
+
+## CURLOPT_ALTSVC_CTRL
+
+Enable and configure Alt-Svc: treatment. See CURLOPT_ALTSVC_CTRL(3)
+
+## CURLOPT_HSTS
+
+Set HSTS cache file. See CURLOPT_HSTS(3)
+
+## CURLOPT_HSTS_CTRL
+
+Enable HSTS. See CURLOPT_HSTS_CTRL(3)
+
+## CURLOPT_HSTSREADFUNCTION
+
+Set HSTS read callback. See CURLOPT_HSTSREADFUNCTION(3)
+
+## CURLOPT_HSTSREADDATA
+
+Pass pointer to the HSTS read callback. See CURLOPT_HSTSREADDATA(3)
+
+## CURLOPT_HSTSWRITEFUNCTION
+
+Set HSTS write callback. See CURLOPT_HSTSWRITEFUNCTION(3)
+
+## CURLOPT_HSTSWRITEDATA
+
+Pass pointer to the HSTS write callback. See CURLOPT_HSTSWRITEDATA(3)
+
+## CURLOPT_HTTPGET
+
+Do an HTTP GET request. See CURLOPT_HTTPGET(3)
+
+## CURLOPT_REQUEST_TARGET
+
+Set the request target. CURLOPT_REQUEST_TARGET(3)
+
+## CURLOPT_HTTP_VERSION
+
+HTTP version to use. CURLOPT_HTTP_VERSION(3)
+
+## CURLOPT_HTTP09_ALLOWED
+
+Allow HTTP/0.9 responses. CURLOPT_HTTP09_ALLOWED(3)
+
+## CURLOPT_IGNORE_CONTENT_LENGTH
+
+Ignore Content-Length. See CURLOPT_IGNORE_CONTENT_LENGTH(3)
+
+## CURLOPT_HTTP_CONTENT_DECODING
+
+Disable Content decoding. See CURLOPT_HTTP_CONTENT_DECODING(3)
+
+## CURLOPT_HTTP_TRANSFER_DECODING
+
+Disable Transfer decoding. See CURLOPT_HTTP_TRANSFER_DECODING(3)
+
+## CURLOPT_EXPECT_100_TIMEOUT_MS
+
+100-continue timeout. See CURLOPT_EXPECT_100_TIMEOUT_MS(3)
+
+## CURLOPT_TRAILERFUNCTION
+
+Set callback for sending trailing headers. See
+CURLOPT_TRAILERFUNCTION(3)
+
+## CURLOPT_TRAILERDATA
+
+Custom pointer passed to the trailing headers callback. See
+CURLOPT_TRAILERDATA(3)
+
+## CURLOPT_PIPEWAIT
+
+Wait on connection to pipeline on it. See CURLOPT_PIPEWAIT(3)
+
+## CURLOPT_STREAM_DEPENDS
+
+This HTTP/2 stream depends on another. See CURLOPT_STREAM_DEPENDS(3)
+
+## CURLOPT_STREAM_DEPENDS_E
+
+This HTTP/2 stream depends on another exclusively. See
+CURLOPT_STREAM_DEPENDS_E(3)
+
+## CURLOPT_STREAM_WEIGHT
+
+Set this HTTP/2 stream's weight. See CURLOPT_STREAM_WEIGHT(3)
+
+# SMTP OPTIONS
+
+## CURLOPT_MAIL_FROM
+
+Address of the sender. See CURLOPT_MAIL_FROM(3)
+
+## CURLOPT_MAIL_RCPT
+
+Address of the recipients. See CURLOPT_MAIL_RCPT(3)
+
+## CURLOPT_MAIL_AUTH
+
+Authentication address. See CURLOPT_MAIL_AUTH(3)
+
+## CURLOPT_MAIL_RCPT_ALLOWFAILS
+
+Allow RCPT TO command to fail for some recipients. See
+CURLOPT_MAIL_RCPT_ALLOWFAILS(3)
+
+# TFTP OPTIONS
+
+## CURLOPT_TFTP_BLKSIZE
+
+TFTP block size. See CURLOPT_TFTP_BLKSIZE(3)
+
+## CURLOPT_TFTP_NO_OPTIONS
+
+Do not send TFTP options requests. See CURLOPT_TFTP_NO_OPTIONS(3)
+
+# FTP OPTIONS
+
+## CURLOPT_FTPPORT
+
+Use active FTP. See CURLOPT_FTPPORT(3)
+
+## CURLOPT_QUOTE
+
+Commands to run before transfer. See CURLOPT_QUOTE(3)
+
+## CURLOPT_POSTQUOTE
+
+Commands to run after transfer. See CURLOPT_POSTQUOTE(3)
+
+## CURLOPT_PREQUOTE
+
+Commands to run just before transfer. See CURLOPT_PREQUOTE(3)
+
+## CURLOPT_APPEND
+
+Append to remote file. See CURLOPT_APPEND(3)
+
+## CURLOPT_FTP_USE_EPRT
+
+Use EPRT. See CURLOPT_FTP_USE_EPRT(3)
+
+## CURLOPT_FTP_USE_EPSV
+
+Use EPSV. See CURLOPT_FTP_USE_EPSV(3)
+
+## CURLOPT_FTP_USE_PRET
+
+Use PRET. See CURLOPT_FTP_USE_PRET(3)
+
+## CURLOPT_FTP_CREATE_MISSING_DIRS
+
+Create missing directories on the remote server. See CURLOPT_FTP_CREATE_MISSING_DIRS(3)
+
+## CURLOPT_SERVER_RESPONSE_TIMEOUT
+
+Timeout for server responses. See CURLOPT_SERVER_RESPONSE_TIMEOUT(3)
+
+## CURLOPT_SERVER_RESPONSE_TIMEOUT_MS
+
+Timeout for server responses. See CURLOPT_SERVER_RESPONSE_TIMEOUT_MS(3)
+
+## CURLOPT_FTP_ALTERNATIVE_TO_USER
+
+Alternative to USER. See CURLOPT_FTP_ALTERNATIVE_TO_USER(3)
+
+## CURLOPT_FTP_SKIP_PASV_IP
+
+Ignore the IP address in the PASV response. See CURLOPT_FTP_SKIP_PASV_IP(3)
+
+## CURLOPT_FTPSSLAUTH
+
+Control how to do TLS. See CURLOPT_FTPSSLAUTH(3)
+
+## CURLOPT_FTP_SSL_CCC
+
+Back to non-TLS again after authentication. See CURLOPT_FTP_SSL_CCC(3)
+
+## CURLOPT_FTP_ACCOUNT
+
+Send ACCT command. See CURLOPT_FTP_ACCOUNT(3)
+
+## CURLOPT_FTP_FILEMETHOD
+
+Specify how to reach files. See CURLOPT_FTP_FILEMETHOD(3)
+
+# RTSP OPTIONS
+
+## CURLOPT_RTSP_REQUEST
+
+RTSP request. See CURLOPT_RTSP_REQUEST(3)
+
+## CURLOPT_RTSP_SESSION_ID
+
+RTSP session-id. See CURLOPT_RTSP_SESSION_ID(3)
+
+## CURLOPT_RTSP_STREAM_URI
+
+RTSP stream URI. See CURLOPT_RTSP_STREAM_URI(3)
+
+## CURLOPT_RTSP_TRANSPORT
+
+RTSP Transport: header. See CURLOPT_RTSP_TRANSPORT(3)
+
+## CURLOPT_RTSP_CLIENT_CSEQ
+
+Client CSEQ number. See CURLOPT_RTSP_CLIENT_CSEQ(3)
+
+## CURLOPT_RTSP_SERVER_CSEQ
+
+CSEQ number for RTSP Server->Client request. See CURLOPT_RTSP_SERVER_CSEQ(3)
+
+## CURLOPT_AWS_SIGV4
+
+AWS HTTP V4 Signature. See CURLOPT_AWS_SIGV4(3)
+
+# PROTOCOL OPTIONS
+
+## CURLOPT_TRANSFERTEXT
+
+Use text transfer. See CURLOPT_TRANSFERTEXT(3)
+
+## CURLOPT_PROXY_TRANSFER_MODE
+
+Add transfer mode to URL over proxy. See CURLOPT_PROXY_TRANSFER_MODE(3)
+
+## CURLOPT_CRLF
+
+Convert newlines. See CURLOPT_CRLF(3)
+
+## CURLOPT_RANGE
+
+Range requests. See CURLOPT_RANGE(3)
+
+## CURLOPT_RESUME_FROM
+
+Resume a transfer. See CURLOPT_RESUME_FROM(3)
+
+## CURLOPT_RESUME_FROM_LARGE
+
+Resume a transfer. See CURLOPT_RESUME_FROM_LARGE(3)
+
+## CURLOPT_CURLU
+
+Set URL to work on with a URL handle. See CURLOPT_CURLU(3)
+
+## CURLOPT_CUSTOMREQUEST
+
+Custom request/method. See CURLOPT_CUSTOMREQUEST(3)
+
+## CURLOPT_FILETIME
+
+Request file modification date and time. See CURLOPT_FILETIME(3)
+
+## CURLOPT_DIRLISTONLY
+
+List only. See CURLOPT_DIRLISTONLY(3)
+
+## CURLOPT_NOBODY
+
+Do not get the body contents. See CURLOPT_NOBODY(3)
+
+## CURLOPT_INFILESIZE
+
+Size of file to send. CURLOPT_INFILESIZE(3)
+
+## CURLOPT_INFILESIZE_LARGE
+
+Size of file to send. CURLOPT_INFILESIZE_LARGE(3)
+
+## CURLOPT_UPLOAD
+
+Upload data. See CURLOPT_UPLOAD(3)
+
+## CURLOPT_UPLOAD_BUFFERSIZE
+
+Set upload buffer size. See CURLOPT_UPLOAD_BUFFERSIZE(3)
+
+## CURLOPT_MIMEPOST
+
+Post/send MIME data. See CURLOPT_MIMEPOST(3)
+
+## CURLOPT_MIME_OPTIONS
+
+Set MIME option flags. See CURLOPT_MIME_OPTIONS(3)
+
+## CURLOPT_MAXFILESIZE
+
+Maximum file size to get. See CURLOPT_MAXFILESIZE(3)
+
+## CURLOPT_MAXFILESIZE_LARGE
+
+Maximum file size to get. See CURLOPT_MAXFILESIZE_LARGE(3)
+
+## CURLOPT_TIMECONDITION
+
+Make a time conditional request. See CURLOPT_TIMECONDITION(3)
+
+## CURLOPT_TIMEVALUE
+
+Time value for the time conditional request. See CURLOPT_TIMEVALUE(3)
+
+## CURLOPT_TIMEVALUE_LARGE
+
+Time value for the time conditional request. See CURLOPT_TIMEVALUE_LARGE(3)
+
+# CONNECTION OPTIONS
+
+## CURLOPT_TIMEOUT
+
+Timeout for the entire request. See CURLOPT_TIMEOUT(3)
+
+## CURLOPT_TIMEOUT_MS
+
+Millisecond timeout for the entire request. See CURLOPT_TIMEOUT_MS(3)
+
+## CURLOPT_LOW_SPEED_LIMIT
+
+Low speed limit to abort transfer. See CURLOPT_LOW_SPEED_LIMIT(3)
+
+## CURLOPT_LOW_SPEED_TIME
+
+Time to be below the speed to trigger low speed abort. See CURLOPT_LOW_SPEED_TIME(3)
+
+## CURLOPT_MAX_SEND_SPEED_LARGE
+
+Cap the upload speed to this. See CURLOPT_MAX_SEND_SPEED_LARGE(3)
+
+## CURLOPT_MAX_RECV_SPEED_LARGE
+
+Cap the download speed to this. See CURLOPT_MAX_RECV_SPEED_LARGE(3)
+
+## CURLOPT_MAXCONNECTS
+
+Maximum number of connections in the connection pool. See CURLOPT_MAXCONNECTS(3)
+
+## CURLOPT_FRESH_CONNECT
+
+Use a new connection. CURLOPT_FRESH_CONNECT(3)
+
+## CURLOPT_FORBID_REUSE
+
+Prevent subsequent connections from reusing this. See CURLOPT_FORBID_REUSE(3)
+
+## CURLOPT_MAXAGE_CONN
+
+Limit the age (idle time) of connections for reuse. See CURLOPT_MAXAGE_CONN(3)
+
+## CURLOPT_MAXLIFETIME_CONN
+
+Limit the age (since creation) of connections for reuse. See
+CURLOPT_MAXLIFETIME_CONN(3)
+
+## CURLOPT_CONNECTTIMEOUT
+
+Timeout for the connection phase. See CURLOPT_CONNECTTIMEOUT(3)
+
+## CURLOPT_CONNECTTIMEOUT_MS
+
+Millisecond timeout for the connection phase. See CURLOPT_CONNECTTIMEOUT_MS(3)
+
+## CURLOPT_IPRESOLVE
+
+IP version to use. See CURLOPT_IPRESOLVE(3)
+
+## CURLOPT_CONNECT_ONLY
+
+Only connect, nothing else. See CURLOPT_CONNECT_ONLY(3)
+
+## CURLOPT_USE_SSL
+
+Use TLS/SSL. See CURLOPT_USE_SSL(3)
+
+## CURLOPT_RESOLVE
+
+Provide fixed/fake name resolves. See CURLOPT_RESOLVE(3)
+
+## CURLOPT_DNS_INTERFACE
+
+Bind name resolves to this interface. See CURLOPT_DNS_INTERFACE(3)
+
+## CURLOPT_DNS_LOCAL_IP4
+
+Bind name resolves to this IP4 address. See CURLOPT_DNS_LOCAL_IP4(3)
+
+## CURLOPT_DNS_LOCAL_IP6
+
+Bind name resolves to this IP6 address. See CURLOPT_DNS_LOCAL_IP6(3)
+
+## CURLOPT_DNS_SERVERS
+
+Preferred DNS servers. See CURLOPT_DNS_SERVERS(3)
+
+## CURLOPT_DNS_SHUFFLE_ADDRESSES
+
+Shuffle addresses before use. See CURLOPT_DNS_SHUFFLE_ADDRESSES(3)
+
+## CURLOPT_ACCEPTTIMEOUT_MS
+
+Timeout for waiting for the server's connect back to be accepted. See
+CURLOPT_ACCEPTTIMEOUT_MS(3)
+
+## CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS
+
+Timeout for happy eyeballs. See CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS(3)
+
+## CURLOPT_UPKEEP_INTERVAL_MS
+
+Sets the interval at which connection upkeep are performed. See
+CURLOPT_UPKEEP_INTERVAL_MS(3)
+
+# SSL and SECURITY OPTIONS
+
+## CURLOPT_SSLCERT
+
+Client cert. See CURLOPT_SSLCERT(3)
+
+## CURLOPT_SSLCERT_BLOB
+
+Client cert memory buffer. See CURLOPT_SSLCERT_BLOB(3)
+
+## CURLOPT_PROXY_SSLCERT
+
+Proxy client cert. See CURLOPT_PROXY_SSLCERT(3)
+
+## CURLOPT_PROXY_SSLCERT_BLOB
+
+Proxy client cert memory buffer. See CURLOPT_PROXY_SSLCERT_BLOB(3)
+
+## CURLOPT_SSLCERTTYPE
+
+Client cert type. See CURLOPT_SSLCERTTYPE(3)
+
+## CURLOPT_PROXY_SSLCERTTYPE
+
+Proxy client cert type. See CURLOPT_PROXY_SSLCERTTYPE(3)
+
+## CURLOPT_SSLKEY
+
+Client key. See CURLOPT_SSLKEY(3)
+
+## CURLOPT_SSLKEY_BLOB
+
+Client key memory buffer. See CURLOPT_SSLKEY_BLOB(3)
+
+## CURLOPT_PROXY_SSLKEY
+
+Proxy client key. See CURLOPT_PROXY_SSLKEY(3)
+
+## CURLOPT_PROXY_SSLKEY_BLOB
+
+Proxy client key. See CURLOPT_PROXY_SSLKEY_BLOB(3)
+
+## CURLOPT_SSLKEYTYPE
+
+Client key type. See CURLOPT_SSLKEYTYPE(3)
+
+## CURLOPT_PROXY_SSLKEYTYPE
+
+Proxy client key type. See CURLOPT_PROXY_SSLKEYTYPE(3)
+
+## CURLOPT_KEYPASSWD
+
+Client key password. See CURLOPT_KEYPASSWD(3)
+
+## CURLOPT_PROXY_KEYPASSWD
+
+Proxy client key password. See CURLOPT_PROXY_KEYPASSWD(3)
+
+## CURLOPT_SSL_EC_CURVES
+
+Set key exchange curves. See CURLOPT_SSL_EC_CURVES(3)
+
+## CURLOPT_SSL_ENABLE_ALPN
+
+Enable use of ALPN. See CURLOPT_SSL_ENABLE_ALPN(3)
+
+## CURLOPT_SSL_ENABLE_NPN
+
+**OBSOLETE** Enable use of NPN. See CURLOPT_SSL_ENABLE_NPN(3)
+
+## CURLOPT_SSLENGINE
+
+Use identifier with SSL engine. See CURLOPT_SSLENGINE(3)
+
+## CURLOPT_SSLENGINE_DEFAULT
+
+Default SSL engine. See CURLOPT_SSLENGINE_DEFAULT(3)
+
+## CURLOPT_SSL_FALSESTART
+
+Enable TLS False Start. See CURLOPT_SSL_FALSESTART(3)
+
+## CURLOPT_SSLVERSION
+
+SSL version to use. See CURLOPT_SSLVERSION(3)
+
+## CURLOPT_PROXY_SSLVERSION
+
+Proxy SSL version to use. See CURLOPT_PROXY_SSLVERSION(3)
+
+## CURLOPT_SSL_VERIFYHOST
+
+Verify the hostname in the SSL certificate. See CURLOPT_SSL_VERIFYHOST(3)
+
+## CURLOPT_DOH_SSL_VERIFYHOST
+
+Verify the hostname in the DoH (DNS-over-HTTPS) SSL certificate. See
+CURLOPT_DOH_SSL_VERIFYHOST(3)
+
+## CURLOPT_PROXY_SSL_VERIFYHOST
+
+Verify the hostname in the proxy SSL certificate. See
+CURLOPT_PROXY_SSL_VERIFYHOST(3)
+
+## CURLOPT_SSL_VERIFYPEER
+
+Verify the SSL certificate. See CURLOPT_SSL_VERIFYPEER(3)
+
+## CURLOPT_DOH_SSL_VERIFYPEER
+
+Verify the DoH (DNS-over-HTTPS) SSL certificate. See
+CURLOPT_DOH_SSL_VERIFYPEER(3)
+
+## CURLOPT_PROXY_SSL_VERIFYPEER
+
+Verify the proxy SSL certificate. See CURLOPT_PROXY_SSL_VERIFYPEER(3)
+
+## CURLOPT_SSL_VERIFYSTATUS
+
+Verify the SSL certificate's status. See CURLOPT_SSL_VERIFYSTATUS(3)
+
+## CURLOPT_DOH_SSL_VERIFYSTATUS
+
+Verify the DoH (DNS-over-HTTPS) SSL certificate's status. See
+CURLOPT_DOH_SSL_VERIFYSTATUS(3)
+
+## CURLOPT_CAINFO
+
+CA cert bundle. See CURLOPT_CAINFO(3)
+
+## CURLOPT_CAINFO_BLOB
+
+CA cert bundle memory buffer. See CURLOPT_CAINFO_BLOB(3)
+
+## CURLOPT_PROXY_CAINFO
+
+Proxy CA cert bundle. See CURLOPT_PROXY_CAINFO(3)
+
+## CURLOPT_PROXY_CAINFO_BLOB
+
+Proxy CA cert bundle memory buffer. See CURLOPT_PROXY_CAINFO_BLOB(3)
+
+## CURLOPT_ISSUERCERT
+
+Issuer certificate. See CURLOPT_ISSUERCERT(3)
+
+## CURLOPT_ISSUERCERT_BLOB
+
+Issuer certificate memory buffer. See CURLOPT_ISSUERCERT_BLOB(3)
+
+## CURLOPT_PROXY_ISSUERCERT
+
+Proxy issuer certificate. See CURLOPT_PROXY_ISSUERCERT(3)
+
+## CURLOPT_PROXY_ISSUERCERT_BLOB
+
+Proxy issuer certificate memory buffer. See CURLOPT_PROXY_ISSUERCERT_BLOB(3)
+
+## CURLOPT_CAPATH
+
+Path to CA cert bundle. See CURLOPT_CAPATH(3)
+
+## CURLOPT_PROXY_CAPATH
+
+Path to proxy CA cert bundle. See CURLOPT_PROXY_CAPATH(3)
+
+## CURLOPT_CRLFILE
+
+Certificate Revocation List. See CURLOPT_CRLFILE(3)
+
+## CURLOPT_PROXY_CRLFILE
+
+Proxy Certificate Revocation List. See CURLOPT_PROXY_CRLFILE(3)
+
+## CURLOPT_CA_CACHE_TIMEOUT
+
+Timeout for CA cache. See CURLOPT_CA_CACHE_TIMEOUT(3)
+
+## CURLOPT_CERTINFO
+
+Extract certificate info. See CURLOPT_CERTINFO(3)
+
+## CURLOPT_PINNEDPUBLICKEY
+
+Set pinned SSL public key . See CURLOPT_PINNEDPUBLICKEY(3)
+
+## CURLOPT_PROXY_PINNEDPUBLICKEY
+
+Set the proxy's pinned SSL public key. See
+CURLOPT_PROXY_PINNEDPUBLICKEY(3)
+
+## CURLOPT_RANDOM_FILE
+
+**OBSOLETE** Provide source for entropy random data.
+See CURLOPT_RANDOM_FILE(3)
+
+## CURLOPT_EGDSOCKET
+
+**OBSOLETE** Identify EGD socket for entropy. See CURLOPT_EGDSOCKET(3)
+
+## CURLOPT_SSL_CIPHER_LIST
+
+Ciphers to use. See CURLOPT_SSL_CIPHER_LIST(3)
+
+## CURLOPT_PROXY_SSL_CIPHER_LIST
+
+Proxy ciphers to use. See CURLOPT_PROXY_SSL_CIPHER_LIST(3)
+
+## CURLOPT_TLS13_CIPHERS
+
+TLS 1.3 cipher suites to use. See CURLOPT_TLS13_CIPHERS(3)
+
+## CURLOPT_PROXY_TLS13_CIPHERS
+
+Proxy TLS 1.3 cipher suites to use. See CURLOPT_PROXY_TLS13_CIPHERS(3)
+
+## CURLOPT_SSL_SESSIONID_CACHE
+
+Disable SSL session-id cache. See CURLOPT_SSL_SESSIONID_CACHE(3)
+
+## CURLOPT_SSL_OPTIONS
+
+Control SSL behavior. See CURLOPT_SSL_OPTIONS(3)
+
+## CURLOPT_PROXY_SSL_OPTIONS
+
+Control proxy SSL behavior. See CURLOPT_PROXY_SSL_OPTIONS(3)
+
+## CURLOPT_KRBLEVEL
+
+Kerberos security level. See CURLOPT_KRBLEVEL(3)
+
+## CURLOPT_GSSAPI_DELEGATION
+
+Disable GSS-API delegation. See CURLOPT_GSSAPI_DELEGATION(3)
+
+# SSH OPTIONS
+
+## CURLOPT_SSH_AUTH_TYPES
+
+SSH authentication types. See CURLOPT_SSH_AUTH_TYPES(3)
+
+## CURLOPT_SSH_COMPRESSION
+
+Enable SSH compression. See CURLOPT_SSH_COMPRESSION(3)
+
+## CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
+
+MD5 of host's public key. See CURLOPT_SSH_HOST_PUBLIC_KEY_MD5(3)
+
+## CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256
+
+SHA256 of host's public key. See CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256(3)
+
+## CURLOPT_SSH_PUBLIC_KEYFILE
+
+Filename of the public key. See CURLOPT_SSH_PUBLIC_KEYFILE(3)
+
+## CURLOPT_SSH_PRIVATE_KEYFILE
+
+Filename of the private key. See CURLOPT_SSH_PRIVATE_KEYFILE(3)
+
+## CURLOPT_SSH_KNOWNHOSTS
+
+Filename with known hosts. See CURLOPT_SSH_KNOWNHOSTS(3)
+
+## CURLOPT_SSH_KEYFUNCTION
+
+Callback for known hosts handling. See CURLOPT_SSH_KEYFUNCTION(3)
+
+## CURLOPT_SSH_KEYDATA
+
+Custom pointer to pass to ssh key callback. See CURLOPT_SSH_KEYDATA(3)
+
+## CURLOPT_SSH_HOSTKEYFUNCTION
+
+Callback for checking host key handling. See CURLOPT_SSH_HOSTKEYFUNCTION(3)
+
+## CURLOPT_SSH_HOSTKEYDATA
+
+Custom pointer to pass to ssh host key callback. See CURLOPT_SSH_HOSTKEYDATA(3)
+
+# WEBSOCKET
+
+## CURLOPT_WS_OPTIONS
+
+Set WebSocket options. See CURLOPT_WS_OPTIONS(3)
+
+# OTHER OPTIONS
+
+## CURLOPT_PRIVATE
+
+Private pointer to store. See CURLOPT_PRIVATE(3)
+
+## CURLOPT_SHARE
+
+Share object to use. See CURLOPT_SHARE(3)
+
+## CURLOPT_NEW_FILE_PERMS
+
+Mode for creating new remote files. See CURLOPT_NEW_FILE_PERMS(3)
+
+## CURLOPT_NEW_DIRECTORY_PERMS
+
+Mode for creating new remote directories. See CURLOPT_NEW_DIRECTORY_PERMS(3)
+
+## CURLOPT_QUICK_EXIT
+
+To be set by toplevel tools like "curl" to skip lengthy cleanups when they are
+about to call exit() anyway. See CURLOPT_QUICK_EXIT(3)
+
+# TELNET OPTIONS
+
+## CURLOPT_TELNETOPTIONS
+
+TELNET options. See CURLOPT_TELNETOPTIONS(3)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+*CURLE_OK* (zero) means that the option was set properly, non-zero means an
+error occurred as *<curl/curl.h>* defines. See the libcurl-errors(3) man page
+for the full list with descriptions.
+
+Strings passed on to libcurl must be shorter than 8000000 bytes, otherwise
+curl_easy_setopt(3) returns **CURLE_BAD_FUNCTION_ARGUMENT** (added in 7.65.0).
+
+**CURLE_BAD_FUNCTION_ARGUMENT** is returned when the argument to an option is
+invalid, like perhaps out of range.
+
+If you try to set an option that libcurl does not know about, perhaps because
+the library is too old to support it or the option was removed in a recent
+version, this function returns *CURLE_UNKNOWN_OPTION*. If support for the
+option was disabled at compile-time, it returns *CURLE_NOT_BUILT_IN*.
diff --git a/docs/libcurl/curl_easy_strerror.3 b/docs/libcurl/curl_easy_strerror.3
deleted file mode 100644
index 393ef420a..000000000
--- a/docs/libcurl/curl_easy_strerror.3
+++ /dev/null
@@ -1,56 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_easy_strerror 3 "26 Apr 2004" "libcurl" "libcurl"
-.SH NAME
-curl_easy_strerror - return string describing error code
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-const char *curl_easy_strerror(CURLcode errornum);
-.fi
-.SH DESCRIPTION
-The \fIcurl_easy_strerror(3)\fP function returns a string describing the
-CURLcode error code passed in the argument \fIerrornum\fP.
-
-Typically applications also appreciate \fICURLOPT_ERRORBUFFER(3)\fP for more
-specific error descriptions generated at runtime.
-.SH EXAMPLE
-.nf
- /* Perform the entire transfer */
- res = curl_easy_perform(curl);
- /* Check for errors */
- if(res != CURLE_OK)
- fprintf(stderr, "curl_easy_perform() failed: %s\\n",
- curl_easy_strerror(res));
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.12.0
-.SH RETURN VALUE
-A pointer to a null-terminated string.
-.SH "SEE ALSO"
-.BR libcurl-errors (3),
-.BR curl_multi_strerror (3),
-.BR curl_share_strerror (3),
-.BR curl_url_strerror (3)
diff --git a/docs/libcurl/curl_easy_strerror.md b/docs/libcurl/curl_easy_strerror.md
new file mode 100644
index 000000000..218601a44
--- /dev/null
+++ b/docs/libcurl/curl_easy_strerror.md
@@ -0,0 +1,59 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_strerror
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_strerror (3)
+ - curl_share_strerror (3)
+ - curl_url_strerror (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+curl_easy_strerror - return string describing error code
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const char *curl_easy_strerror(CURLcode errornum);
+~~~
+
+# DESCRIPTION
+
+The curl_easy_strerror(3) function returns a string describing the
+CURLcode error code passed in the argument *errornum*.
+
+Typically applications also appreciate CURLOPT_ERRORBUFFER(3) for more
+specific error descriptions generated at runtime.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ /* set options */
+ /* Perform the entire transfer */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.12.0
+
+# RETURN VALUE
+
+A pointer to a null-terminated string.
diff --git a/docs/libcurl/curl_easy_unescape.3 b/docs/libcurl/curl_easy_unescape.3
deleted file mode 100644
index 26bf7e126..000000000
--- a/docs/libcurl/curl_easy_unescape.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_unescape 3 "7 April 2006" "libcurl" "libcurl"
-.SH NAME
-curl_easy_unescape - URL decodes the given string
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_easy_unescape(CURL *curl, const char *input,
- int inlength, int *outlength);
-.fi
-.SH DESCRIPTION
-This function converts the URL encoded string \fBinput\fP to a "plain string"
-and returns that in an allocated memory area. All input characters that are URL
-encoded (%XX where XX is a two-digit hexadecimal number) are converted to their
-binary versions.
-
-If the \fBlength\fP argument is set to 0 (zero), \fIcurl_easy_unescape(3)\fP
-uses strlen() on \fBinput\fP to find out the size.
-
-If \fBoutlength\fP is non-NULL, the function writes the length of the returned
-string in the integer it points to. This allows proper handling even for
-strings containing %00. Since this is a pointer to an \fIint\fP type, it can
-only return a value up to \fIINT_MAX\fP so no longer string can be returned in
-this parameter.
-
-Since 7.82.0, the \fBcurl\fP parameter is ignored. Prior to that there was
-per-handle character conversion support for some old operating systems such as
-TPF, but it was otherwise ignored.
-
-You must \fIcurl_free(3)\fP the returned string when you are done with it.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- int decodelen;
- char *decoded = curl_easy_unescape(curl, "%63%75%72%6c", 12, &decodelen);
- if(decoded) {
- /* do not assume printf() works on the decoded data! */
- printf("Decoded: ");
- /* ... */
- curl_free(decoded);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.4 and replaces the old \fIcurl_unescape(3)\fP function.
-.SH RETURN VALUE
-A pointer to a null-terminated string or NULL if it failed.
-.SH "SEE ALSO"
-.BR curl_easy_escape (3),
-.BR curl_free (3)
diff --git a/docs/libcurl/curl_easy_unescape.md b/docs/libcurl/curl_easy_unescape.md
new file mode 100644
index 000000000..4f9262b34
--- /dev/null
+++ b/docs/libcurl/curl_easy_unescape.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_unescape
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_escape (3)
+ - curl_free (3)
+---
+
+# NAME
+
+curl_easy_unescape - URL decodes the given string
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_easy_unescape(CURL *curl, const char *input,
+ int inlength, int *outlength);
+~~~
+
+# DESCRIPTION
+
+This function converts the URL encoded string **input** to a "plain string"
+and returns that in an allocated memory area. All input characters that are URL
+encoded (%XX where XX is a two-digit hexadecimal number) are converted to their
+binary versions.
+
+If the **length** argument is set to 0 (zero), curl_easy_unescape(3)
+uses strlen() on **input** to find out the size.
+
+If **outlength** is non-NULL, the function writes the length of the returned
+string in the integer it points to. This allows proper handling even for
+strings containing %00. Since this is a pointer to an *int* type, it can
+only return a value up to *INT_MAX* so no longer string can be returned in
+this parameter.
+
+Since 7.82.0, the **curl** parameter is ignored. Prior to that there was
+per-handle character conversion support for some old operating systems such as
+TPF, but it was otherwise ignored.
+
+You must curl_free(3) the returned string when you are done with it.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ int decodelen;
+ char *decoded = curl_easy_unescape(curl, "%63%75%72%6c", 12, &decodelen);
+ if(decoded) {
+ /* do not assume printf() works on the decoded data! */
+ printf("Decoded: ");
+ /* ... */
+ curl_free(decoded);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.4 and replaces the old curl_unescape(3) function.
+
+# RETURN VALUE
+
+A pointer to a null-terminated string or NULL if it failed.
diff --git a/docs/libcurl/curl_easy_upkeep.3 b/docs/libcurl/curl_easy_upkeep.3
deleted file mode 100644
index ade0a5d46..000000000
--- a/docs/libcurl/curl_easy_upkeep.3
+++ /dev/null
@@ -1,81 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_easy_upkeep 3 "31 Oct 2018" "libcurl" "libcurl"
-.SH NAME
-curl_easy_upkeep - Perform any connection upkeep checks.
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_upkeep(CURL *handle);
-.fi
-.SH DESCRIPTION
-
-Some protocols have "connection upkeep" mechanisms. These mechanisms usually
-send some traffic on existing connections in order to keep them alive; this
-can prevent connections from being closed due to overzealous firewalls, for
-example.
-
-Currently the only protocol with a connection upkeep mechanism is HTTP/2: when
-the connection upkeep interval is exceeded and \fIcurl_easy_upkeep(3)\fP
-is called, an HTTP/2 PING frame is sent on the connection.
-
-This function must be explicitly called in order to perform the upkeep work.
-The connection upkeep interval is set with
-\fICURLOPT_UPKEEP_INTERVAL_MS(3)\fP.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- /* Make a connection to an HTTP/2 server. */
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Set the interval to 30000ms / 30s */
- curl_easy_setopt(curl, CURLOPT_UPKEEP_INTERVAL_MS, 30000L);
-
- curl_easy_perform(curl);
-
- /* Perform more work here. */
-
- /* While the connection is being held open, curl_easy_upkeep() can be
- called. If curl_easy_upkeep() is called and the time since the last
- upkeep exceeds the interval, then an HTTP/2 PING is sent. */
- curl_easy_upkeep(curl);
-
- /* Perform more work here. */
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.62.0.
-.SH RETURN VALUE
-On success, returns \fBCURLE_OK\fP.
-
-On failure, returns the appropriate error code.
-.SH SEE ALSO
-.BR CURLOPT_TCP_KEEPALIVE "(3), "
-.BR CURLOPT_TCP_KEEPIDLE "(3), "
diff --git a/docs/libcurl/curl_easy_upkeep.md b/docs/libcurl/curl_easy_upkeep.md
new file mode 100644
index 000000000..2ad89d3bb
--- /dev/null
+++ b/docs/libcurl/curl_easy_upkeep.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_easy_upkeep
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TCP_KEEPALIVE (3)
+ - CURLOPT_TCP_KEEPIDLE (3)
+---
+
+# NAME
+
+curl_easy_upkeep - Perform any connection upkeep checks.
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_upkeep(CURL *handle);
+~~~
+
+# DESCRIPTION
+
+Some protocols have "connection upkeep" mechanisms. These mechanisms usually
+send some traffic on existing connections in order to keep them alive; this
+can prevent connections from being closed due to overzealous firewalls, for
+example.
+
+Currently the only protocol with a connection upkeep mechanism is HTTP/2: when
+the connection upkeep interval is exceeded and curl_easy_upkeep(3)
+is called, an HTTP/2 PING frame is sent on the connection.
+
+This function must be explicitly called in order to perform the upkeep work.
+The connection upkeep interval is set with
+CURLOPT_UPKEEP_INTERVAL_MS(3).
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* Make a connection to an HTTP/2 server. */
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the interval to 30000ms / 30s */
+ curl_easy_setopt(curl, CURLOPT_UPKEEP_INTERVAL_MS, 30000L);
+
+ curl_easy_perform(curl);
+
+ /* Perform more work here. */
+
+ /* While the connection is being held open, curl_easy_upkeep() can be
+ called. If curl_easy_upkeep() is called and the time since the last
+ upkeep exceeds the interval, then an HTTP/2 PING is sent. */
+ curl_easy_upkeep(curl);
+
+ /* Perform more work here. */
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0.
+
+# RETURN VALUE
+
+On success, returns **CURLE_OK**.
+
+On failure, returns the appropriate error code.
diff --git a/docs/libcurl/curl_escape.3 b/docs/libcurl/curl_escape.3
deleted file mode 100644
index b379b7a6b..000000000
--- a/docs/libcurl/curl_escape.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_escape 3 "6 March 2002" "libcurl" "libcurl"
-.SH NAME
-curl_escape - URL encodes the given string
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_escape(const char *string, int length);
-.fi
-.SH DESCRIPTION
-Obsolete function. Use \fIcurl_easy_escape(3)\fP instead!
-
-This function converts the given input \fBstring\fP to a URL encoded string
-and return that as a new allocated string. All input characters that are not
-a-z, A-Z or 0-9 are converted to their "URL escaped" version (\fB%NN\fP where
-\fBNN\fP is a two-digit hexadecimal number).
-
-If the \fBlength\fP argument is set to 0, \fIcurl_escape(3)\fP uses strlen()
-on \fBstring\fP to find out the size.
-
-You must \fIcurl_free(3)\fP the returned string when you are done with it.
-.SH EXAMPLE
-.nf
-char *output = curl_escape("data to convert", 15);
-if(output) {
- printf("Encoded: %s\\n", output);
- curl_free(output);
-}
-.fi
-.SH AVAILABILITY
-Since 7.15.4, \fIcurl_easy_escape(3)\fP should be used. This function might be
-removed in a future release.
-.SH RETURN VALUE
-A pointer to a null-terminated string or NULL if it failed.
-.SH "SEE ALSO"
-.BR curl_unescape (3),
-.BR curl_free (3)
diff --git a/docs/libcurl/curl_escape.md b/docs/libcurl/curl_escape.md
new file mode 100644
index 000000000..e5e7e92b7
--- /dev/null
+++ b/docs/libcurl/curl_escape.md
@@ -0,0 +1,58 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_escape
+Section: 3
+Source: libcurl
+See-also:
+ - curl_free (3)
+ - curl_unescape (3)
+---
+
+# NAME
+
+curl_escape - URL encodes the given string
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_escape(const char *string, int length);
+~~~
+
+# DESCRIPTION
+
+Obsolete function. Use curl_easy_escape(3) instead!
+
+This function converts the given input **string** to a URL encoded string
+and return that as a new allocated string. All input characters that are not
+a-z, A-Z or 0-9 are converted to their "URL escaped" version (**%NN** where
+**NN** is a two-digit hexadecimal number).
+
+If the **length** argument is set to 0, curl_escape(3) uses strlen()
+on **string** to find out the size.
+
+You must curl_free(3) the returned string when you are done with it.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ char *output = curl_escape("data to convert", 15);
+ if(output) {
+ printf("Encoded: %s\n", output);
+ curl_free(output);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Since 7.15.4, curl_easy_escape(3) should be used. This function might be
+removed in a future release.
+
+# RETURN VALUE
+
+A pointer to a null-terminated string or NULL if it failed.
diff --git a/docs/libcurl/curl_formadd.3 b/docs/libcurl/curl_formadd.3
deleted file mode 100644
index b379d0acb..000000000
--- a/docs/libcurl/curl_formadd.3
+++ /dev/null
@@ -1,268 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_formadd 3 "24 June 2002" "libcurl" "libcurl"
-.SH NAME
-curl_formadd - add a section to a multipart form POST
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLFORMcode curl_formadd(struct curl_httppost **firstitem,
- struct curl_httppost **lastitem, ...);
-.fi
-.SH DESCRIPTION
-\fBThis function is deprecated.\fP Use \fIcurl_mime_init(3)\fP instead.
-
-curl_formadd() is used to append sections when building a multipart form
-post. Append one section at a time until you have added all the sections you
-want included and then you pass the \fIfirstitem\fP pointer as parameter to
-\fICURLOPT_HTTPPOST(3)\fP. \fIlastitem\fP is set after each
-\fIcurl_formadd(3)\fP call and on repeated invokes it should be left as set to
-allow repeated invokes to find the end of the list faster.
-
-After the \fIlastitem\fP pointer follow the real arguments.
-
-The pointers \fIfirstitem\fP and \fIlastitem\fP should both be pointing to
-NULL in the first call to this function. All list-data is allocated by the
-function itself. You must call \fIcurl_formfree(3)\fP on the \fIfirstitem\fP
-after the form post has been done to free the resources.
-
-Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
-You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
-
-First, there are some basics you need to understand about multipart form
-posts. Each part consists of at least a NAME and a CONTENTS part. If the part
-is made for file upload, there are also a stored CONTENT-TYPE and a FILENAME.
-Below, we discuss what options you use to set these properties in the parts
-you want to add to your post.
-
-The options listed first are for making normal parts. The options from
-\fICURLFORM_FILE\fP through \fICURLFORM_BUFFERLENGTH\fP are for file upload
-parts.
-.SH OPTIONS
-.IP CURLFORM_COPYNAME
-followed by a string which provides the \fIname\fP of this part. libcurl
-copies the string so your application does not need to keep it around after
-this function call. If the name is not null-terminated, you must set its
-length with \fBCURLFORM_NAMELENGTH\fP. The \fIname\fP is not allowed to
-contain zero-valued bytes. The copied data is freed by \fIcurl_formfree(3)\fP.
-.IP CURLFORM_PTRNAME
-followed by a string which provides the \fIname\fP of this part. libcurl uses
-the pointer and refer to the data in your application, so you must make sure
-it remains until curl no longer needs it. If the name is not null-terminated,
-you must set its length with \fBCURLFORM_NAMELENGTH\fP. The \fIname\fP is not
-allowed to contain zero-valued bytes.
-.IP CURLFORM_COPYCONTENTS
-followed by a pointer to the contents of this part, the actual data to send
-away. libcurl copies the provided data, so your application does not need to
-keep it around after this function call. If the data is not null terminated,
-or if you would like it to contain zero bytes, you must set the length of the
-name with \fBCURLFORM_CONTENTSLENGTH\fP. The copied data is freed by
-\fIcurl_formfree(3)\fP.
-.IP CURLFORM_PTRCONTENTS
-followed by a pointer to the contents of this part, the actual data to send
-away. libcurl uses the pointer and refer to the data in your application, so
-you must make sure it remains until curl no longer needs it. If the data is
-not null-terminated, or if you would like it to contain zero bytes, you must
-set its length with \fBCURLFORM_CONTENTSLENGTH\fP.
-.IP CURLFORM_CONTENTLEN
-followed by a curl_off_t value giving the length of the contents. Note that
-for \fICURLFORM_STREAM\fP contents, this option is mandatory.
-
-If you pass a 0 (zero) for this option, libcurl calls strlen() on the contents
-to figure out the size. If you really want to send a zero byte content then
-you must make sure strlen() on the data pointer returns zero.
-
-(Option added in 7.46.0)
-.IP CURLFORM_CONTENTSLENGTH
-(This option is deprecated. Use \fICURLFORM_CONTENTLEN\fP instead!)
-
-followed by a long giving the length of the contents. Note that for
-\fICURLFORM_STREAM\fP contents, this option is mandatory.
-
-If you pass a 0 (zero) for this option, libcurl calls strlen() on the contents
-to figure out the size. If you really want to send a zero byte content then
-you must make sure strlen() on the data pointer returns zero.
-.IP CURLFORM_FILECONTENT
-followed by a filename, causes that file to be read and its contents used
-as data in this part. This part does \fInot\fP automatically become a file
-upload part simply because its data was read from a file.
-
-The specified file needs to kept around until the associated transfer is done.
-.IP CURLFORM_FILE
-followed by a filename, makes this part a file upload part. It sets the
-\fIfilename\fP field to the basename of the provided filename, it reads the
-contents of the file and passes them as data and sets the content-type if the
-given file match one of the internally known file extensions. For
-\fBCURLFORM_FILE\fP the user may send one or more files in one part by
-providing multiple \fBCURLFORM_FILE\fP arguments each followed by the filename
-(and each \fICURLFORM_FILE\fP is allowed to have a
-\fICURLFORM_CONTENTTYPE\fP).
-
-The given upload file has to exist in its full in the file system already when
-the upload starts, as libcurl needs to read the correct file size beforehand.
-
-The specified file needs to kept around until the associated transfer is done.
-.IP CURLFORM_CONTENTTYPE
-is used in combination with \fICURLFORM_FILE\fP. Followed by a pointer to a
-string which provides the content-type for this part, possibly instead of an
-internally chosen one.
-.IP CURLFORM_FILENAME
-is used in combination with \fICURLFORM_FILE\fP. Followed by a pointer to a
-string, it tells libcurl to use the given string as the \fIfilename\fP in the
-file upload part instead of the actual file name.
-.IP CURLFORM_BUFFER
-is used for custom file upload parts without use of \fICURLFORM_FILE\fP. It
-tells libcurl that the file contents are already present in a buffer. The
-parameter is a string which provides the \fIfilename\fP field in the content
-header.
-.IP CURLFORM_BUFFERPTR
-is used in combination with \fICURLFORM_BUFFER\fP. The parameter is a pointer
-to the buffer to be uploaded. This buffer must not be freed until after
-\fIcurl_easy_cleanup(3)\fP is called. You must also use
-\fICURLFORM_BUFFERLENGTH\fP to set the number of bytes in the buffer.
-.IP CURLFORM_BUFFERLENGTH
-is used in combination with \fICURLFORM_BUFFER\fP. The parameter is a
-long which gives the length of the buffer.
-.IP CURLFORM_STREAM
-Tells libcurl to use the \fICURLOPT_READFUNCTION(3)\fP callback to get
-data. The parameter you pass to \fICURLFORM_STREAM\fP is the pointer passed on
-to the read callback's fourth argument. If you want the part to look like a
-file upload one, set the \fICURLFORM_FILENAME\fP parameter as well. Note that
-when using \fICURLFORM_STREAM\fP, \fICURLFORM_CONTENTSLENGTH\fP must also be
-set with the total expected length of the part unless the formpost is sent
-chunked encoded. (Option added in libcurl 7.18.2)
-.IP CURLFORM_ARRAY
-Another possibility to send options to curl_formadd() is the
-\fBCURLFORM_ARRAY\fP option, that passes a struct curl_forms array pointer as
-its value. Each curl_forms structure element has a \fICURLformoption\fP and a
-char pointer. The final element in the array must be a CURLFORM_END. All
-available options can be used in an array, except the CURLFORM_ARRAY option
-itself. The last argument in such an array must always be \fBCURLFORM_END\fP.
-.IP CURLFORM_CONTENTHEADER
-specifies extra headers for the form POST section. This takes a curl_slist
-prepared in the usual way using \fBcurl_slist_append\fP and appends the list
-of headers to those libcurl automatically generates. The list must exist while
-the POST occurs, if you free it before the post completes you may experience
-problems.
-
-When you have passed the \fIstruct curl_httppost\fP pointer to
-\fIcurl_easy_setopt(3)\fP (using the \fICURLOPT_HTTPPOST(3)\fP option), you
-must not free the list until after you have called \fIcurl_easy_cleanup(3)\fP
-for the curl handle.
-
-See example below.
-.SH EXAMPLE
-.nf
- struct curl_httppost *post = NULL;
- struct curl_httppost *last = NULL;
- char namebuffer[] = "name buffer";
- long namelength = strlen(namebuffer);
- char buffer[] = "test buffer";
- char htmlbuffer[] = "<HTML>test buffer</HTML>";
- long htmlbufferlength = strlen(htmlbuffer);
- struct curl_forms forms[3];
- char file1[] = "my-face.jpg";
- char file2[] = "your-face.jpg";
- /* add null character into htmlbuffer, to demonstrate that
- transfers of buffers containing null characters actually work
- */
- htmlbuffer[8] = '\\0';
-
- /* Add simple name/content section */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "name",
- CURLFORM_COPYCONTENTS, "content", CURLFORM_END);
-
- /* Add simple name/content/contenttype section */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "htmlcode",
- CURLFORM_COPYCONTENTS, "<HTML></HTML>",
- CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
-
- /* Add name/ptrcontent section */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "name_for_ptrcontent",
- CURLFORM_PTRCONTENTS, buffer, CURLFORM_END);
-
- /* Add ptrname/ptrcontent section */
- curl_formadd(&post, &last, CURLFORM_PTRNAME, namebuffer,
- CURLFORM_PTRCONTENTS, buffer, CURLFORM_NAMELENGTH,
- namelength, CURLFORM_END);
-
- /* Add name/ptrcontent/contenttype section */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "html_code_with_hole",
- CURLFORM_PTRCONTENTS, htmlbuffer,
- CURLFORM_CONTENTSLENGTH, htmlbufferlength,
- CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
-
- /* Add simple file section */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
- CURLFORM_FILE, "my-face.jpg", CURLFORM_END);
-
- /* Add file/contenttype section */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
- CURLFORM_FILE, "my-face.jpg",
- CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);
-
- /* Add two file section */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
- CURLFORM_FILE, "my-face.jpg",
- CURLFORM_FILE, "your-face.jpg", CURLFORM_END);
-
- /* Add two file section using CURLFORM_ARRAY */
- forms[0].option = CURLFORM_FILE;
- forms[0].value = file1;
- forms[1].option = CURLFORM_FILE;
- forms[1].value = file2;
- forms[2].option = CURLFORM_END;
-
- /* Add a buffer to upload */
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "name",
- CURLFORM_BUFFER, "data",
- CURLFORM_BUFFERPTR, record,
- CURLFORM_BUFFERLENGTH, record_length,
- CURLFORM_END);
-
- /* no option needed for the end marker */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
- CURLFORM_ARRAY, forms, CURLFORM_END);
- /* Add the content of a file as a normal post text value */
- curl_formadd(&post, &last, CURLFORM_COPYNAME, "filecontent",
- CURLFORM_FILECONTENT, ".bashrc", CURLFORM_END);
- /* Set the form info */
- curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
-.SH AVAILABILITY
-Deprecated in 7.56.0. Before this release, field names were allowed to
-contain zero-valued bytes. The pseudo-filename "-" to read stdin is
-discouraged although still supported, but data is not read before being
-actually sent: the effective data size can then not be automatically
-determined, resulting in a chunked encoding transfer. Backslashes and
-double quotes in field and file names are now escaped before transmission.
-.SH RETURN VALUE
-0 means everything was OK, non-zero means an error occurred corresponding
-to a CURL_FORMADD_* constant defined in
-.I <curl/curl.h>
-.SH "SEE ALSO"
-.BR curl_easy_setopt (3),
-.BR curl_formfree (3),
-.BR curl_mime_init (3)
diff --git a/docs/libcurl/curl_formadd.md b/docs/libcurl/curl_formadd.md
new file mode 100644
index 000000000..3793df8fa
--- /dev/null
+++ b/docs/libcurl/curl_formadd.md
@@ -0,0 +1,313 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_formadd
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_setopt (3)
+ - curl_formfree (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+curl_formadd - add a section to a multipart form POST
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLFORMcode curl_formadd(struct curl_httppost **firstitem,
+ struct curl_httppost **lastitem, ...);
+~~~
+
+# DESCRIPTION
+
+**This function is deprecated.** Use curl_mime_init(3) instead.
+
+curl_formadd() is used to append sections when building a multipart form
+post. Append one section at a time until you have added all the sections you
+want included and then you pass the *firstitem* pointer as parameter to
+CURLOPT_HTTPPOST(3). *lastitem* is set after each curl_formadd(3) call and
+on repeated invokes it should be left as set to allow repeated invokes to find
+the end of the list faster.
+
+After the *lastitem* pointer follow the real arguments.
+
+The pointers *firstitem* and *lastitem* should both be pointing to
+NULL in the first call to this function. All list-data is allocated by the
+function itself. You must call curl_formfree(3) on the *firstitem*
+after the form post has been done to free the resources.
+
+Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
+You can disable this header with CURLOPT_HTTPHEADER(3) as usual.
+
+First, there are some basics you need to understand about multipart form
+posts. Each part consists of at least a NAME and a CONTENTS part. If the part
+is made for file upload, there are also a stored CONTENT-TYPE and a FILENAME.
+Below, we discuss what options you use to set these properties in the parts
+you want to add to your post.
+
+The options listed first are for making normal parts. The options from
+*CURLFORM_FILE* through *CURLFORM_BUFFERLENGTH* are for file upload
+parts.
+
+# OPTIONS
+
+## CURLFORM_COPYNAME
+
+followed by a string which provides the *name* of this part. libcurl
+copies the string so your application does not need to keep it around after
+this function call. If the name is not null-terminated, you must set its
+length with **CURLFORM_NAMELENGTH**. The *name* is not allowed to
+contain zero-valued bytes. The copied data is freed by curl_formfree(3).
+
+## CURLFORM_PTRNAME
+
+followed by a string which provides the *name* of this part. libcurl uses the
+pointer and refer to the data in your application, so you must make sure it
+remains until curl no longer needs it. If the name is not null-terminated, you
+must set its length with **CURLFORM_NAMELENGTH**. The *name* is not allowed to
+contain zero-valued bytes.
+
+## CURLFORM_COPYCONTENTS
+
+followed by a pointer to the contents of this part, the actual data to send
+away. libcurl copies the provided data, so your application does not need to
+keep it around after this function call. If the data is not null terminated,
+or if you would like it to contain zero bytes, you must set the length of the
+name with **CURLFORM_CONTENTSLENGTH**. The copied data is freed by
+curl_formfree(3).
+
+## CURLFORM_PTRCONTENTS
+
+followed by a pointer to the contents of this part, the actual data to send
+away. libcurl uses the pointer and refer to the data in your application, so
+you must make sure it remains until curl no longer needs it. If the data is
+not null-terminated, or if you would like it to contain zero bytes, you must
+set its length with **CURLFORM_CONTENTSLENGTH**.
+
+## CURLFORM_CONTENTLEN
+
+followed by a curl_off_t value giving the length of the contents. Note that
+for *CURLFORM_STREAM* contents, this option is mandatory.
+
+If you pass a 0 (zero) for this option, libcurl calls strlen() on the contents
+to figure out the size. If you really want to send a zero byte content then
+you must make sure strlen() on the data pointer returns zero.
+
+(Option added in 7.46.0)
+
+## CURLFORM_CONTENTSLENGTH
+
+(This option is deprecated. Use *CURLFORM_CONTENTLEN* instead!)
+
+followed by a long giving the length of the contents. Note that for
+*CURLFORM_STREAM* contents, this option is mandatory.
+
+If you pass a 0 (zero) for this option, libcurl calls strlen() on the contents
+to figure out the size. If you really want to send a zero byte content then
+you must make sure strlen() on the data pointer returns zero.
+
+## CURLFORM_FILECONTENT
+
+followed by a filename, causes that file to be read and its contents used
+as data in this part. This part does *not* automatically become a file
+upload part simply because its data was read from a file.
+
+The specified file needs to kept around until the associated transfer is done.
+
+## CURLFORM_FILE
+
+followed by a filename, makes this part a file upload part. It sets the
+*filename* field to the basename of the provided filename, it reads the
+contents of the file and passes them as data and sets the content-type if the
+given file match one of the internally known file extensions. For
+**CURLFORM_FILE** the user may send one or more files in one part by
+providing multiple **CURLFORM_FILE** arguments each followed by the filename
+(and each *CURLFORM_FILE* is allowed to have a
+*CURLFORM_CONTENTTYPE*).
+
+The given upload file has to exist in its full in the file system already when
+the upload starts, as libcurl needs to read the correct file size beforehand.
+
+The specified file needs to kept around until the associated transfer is done.
+
+## CURLFORM_CONTENTTYPE
+
+is used in combination with *CURLFORM_FILE*. Followed by a pointer to a
+string which provides the content-type for this part, possibly instead of an
+internally chosen one.
+
+## CURLFORM_FILENAME
+
+is used in combination with *CURLFORM_FILE*. Followed by a pointer to a
+string, it tells libcurl to use the given string as the *filename* in the file
+upload part instead of the actual filename.
+
+## CURLFORM_BUFFER
+
+is used for custom file upload parts without use of *CURLFORM_FILE*. It
+tells libcurl that the file contents are already present in a buffer. The
+parameter is a string which provides the *filename* field in the content
+header.
+
+## CURLFORM_BUFFERPTR
+
+is used in combination with *CURLFORM_BUFFER*. The parameter is a pointer
+to the buffer to be uploaded. This buffer must not be freed until after
+curl_easy_cleanup(3) is called. You must also use
+*CURLFORM_BUFFERLENGTH* to set the number of bytes in the buffer.
+
+## CURLFORM_BUFFERLENGTH
+
+is used in combination with *CURLFORM_BUFFER*. The parameter is a
+long which gives the length of the buffer.
+
+## CURLFORM_STREAM
+
+Tells libcurl to use the CURLOPT_READFUNCTION(3) callback to get
+data. The parameter you pass to *CURLFORM_STREAM* is the pointer passed on
+to the read callback's fourth argument. If you want the part to look like a
+file upload one, set the *CURLFORM_FILENAME* parameter as well. Note that
+when using *CURLFORM_STREAM*, *CURLFORM_CONTENTSLENGTH* must also be
+set with the total expected length of the part unless the formpost is sent
+chunked encoded. (Option added in libcurl 7.18.2)
+
+## CURLFORM_ARRAY
+
+Another possibility to send options to curl_formadd() is the
+**CURLFORM_ARRAY** option, that passes a struct curl_forms array pointer as
+its value. Each curl_forms structure element has a *CURLformoption* and a
+char pointer. The final element in the array must be a CURLFORM_END. All
+available options can be used in an array, except the CURLFORM_ARRAY option
+itself. The last argument in such an array must always be **CURLFORM_END**.
+
+## CURLFORM_CONTENTHEADER
+
+specifies extra headers for the form POST section. This takes a curl_slist
+prepared in the usual way using **curl_slist_append** and appends the list
+of headers to those libcurl automatically generates. The list must exist while
+the POST occurs, if you free it before the post completes you may experience
+problems.
+
+When you have passed the *struct curl_httppost* pointer to
+curl_easy_setopt(3) (using the CURLOPT_HTTPPOST(3) option), you
+must not free the list until after you have called curl_easy_cleanup(3)
+for the curl handle.
+
+See example below.
+
+# EXAMPLE
+
+~~~c
+#include <string.h> /* for strlen */
+
+static const char record[]="data in a buffer";
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct curl_httppost *post = NULL;
+ struct curl_httppost *last = NULL;
+ char namebuffer[] = "name buffer";
+ long namelength = strlen(namebuffer);
+ char buffer[] = "test buffer";
+ char htmlbuffer[] = "<HTML>test buffer</HTML>";
+ long htmlbufferlength = strlen(htmlbuffer);
+ struct curl_forms forms[3];
+ char file1[] = "my-face.jpg";
+ char file2[] = "your-face.jpg";
+ /* add null character into htmlbuffer, to demonstrate that
+ transfers of buffers containing null characters actually work
+ */
+ htmlbuffer[8] = '\0';
+
+ /* Add simple name/content section */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "name",
+ CURLFORM_COPYCONTENTS, "content", CURLFORM_END);
+
+ /* Add simple name/content/contenttype section */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "htmlcode",
+ CURLFORM_COPYCONTENTS, "<HTML></HTML>",
+ CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
+
+ /* Add name/ptrcontent section */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "name_for_ptrcontent",
+ CURLFORM_PTRCONTENTS, buffer, CURLFORM_END);
+
+ /* Add ptrname/ptrcontent section */
+ curl_formadd(&post, &last, CURLFORM_PTRNAME, namebuffer,
+ CURLFORM_PTRCONTENTS, buffer, CURLFORM_NAMELENGTH,
+ namelength, CURLFORM_END);
+
+ /* Add name/ptrcontent/contenttype section */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "html_code_with_hole",
+ CURLFORM_PTRCONTENTS, htmlbuffer,
+ CURLFORM_CONTENTSLENGTH, htmlbufferlength,
+ CURLFORM_CONTENTTYPE, "text/html", CURLFORM_END);
+
+ /* Add simple file section */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
+ CURLFORM_FILE, "my-face.jpg", CURLFORM_END);
+
+ /* Add file/contenttype section */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "picture",
+ CURLFORM_FILE, "my-face.jpg",
+ CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);
+
+ /* Add two file section */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
+ CURLFORM_FILE, "my-face.jpg",
+ CURLFORM_FILE, "your-face.jpg", CURLFORM_END);
+
+ /* Add two file section using CURLFORM_ARRAY */
+ forms[0].option = CURLFORM_FILE;
+ forms[0].value = file1;
+ forms[1].option = CURLFORM_FILE;
+ forms[1].value = file2;
+ forms[2].option = CURLFORM_END;
+
+ /* Add a buffer to upload */
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "name",
+ CURLFORM_BUFFER, "data",
+ CURLFORM_BUFFERPTR, record,
+ CURLFORM_BUFFERLENGTH, sizeof(record),
+ CURLFORM_END);
+
+ /* no option needed for the end marker */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "pictures",
+ CURLFORM_ARRAY, forms, CURLFORM_END);
+ /* Add the content of a file as a normal post text value */
+ curl_formadd(&post, &last, CURLFORM_COPYNAME, "filecontent",
+ CURLFORM_FILECONTENT, ".bashrc", CURLFORM_END);
+ /* Set the form info */
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
+
+ curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+
+ curl_formfree(post);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Deprecated in 7.56.0. Before this release, field names were allowed to
+contain zero-valued bytes. The pseudo-filename "-" to read stdin is
+discouraged although still supported, but data is not read before being
+actually sent: the effective data size can then not be automatically
+determined, resulting in a chunked encoding transfer. Backslashes and
+double quotes in field and file names are now escaped before transmission.
+
+# RETURN VALUE
+
+0 means everything was OK, non-zero means an error occurred corresponding
+to a CURL_FORMADD_* constant defined in
+*<curl/curl.h>*
diff --git a/docs/libcurl/curl_formfree.3 b/docs/libcurl/curl_formfree.3
deleted file mode 100644
index cb0129da5..000000000
--- a/docs/libcurl/curl_formfree.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_formfree 3 "6 April 2001" "libcurl" "libcurl"
-.SH NAME
-curl_formfree - free a previously build multipart form post chain
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_formfree(struct curl_httppost *form);
-.fi
-.SH DESCRIPTION
-This function is deprecated. Do not use. See \fIcurl_mime_init(3)\fP instead!
-
-curl_formfree() is used to clean up data previously built/appended with
-\fIcurl_formadd(3)\fP. This must be called when the data has been used, which
-typically means after \fIcurl_easy_perform(3)\fP has been called.
-
-The pointer to free is the same pointer you passed to the
-\fICURLOPT_HTTPPOST(3)\fP option, which is the \fIfirstitem\fP pointer from
-the \fIcurl_formadd(3)\fP invoke(s).
-
-\fBform\fP is the pointer as returned from a previous call to
-\fIcurl_formadd(3)\fP and may be NULL.
-
-Passing in a NULL pointer in \fIform\fP makes this function return immediately
-with no action.
-.SH EXAMPLE
-.nf
- /* Fill in a file upload field */
- curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "file",
- CURLFORM_FILE, "nice-image.jpg",
- CURLFORM_END);
-
- curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
-
- curl_easy_perform(curl);
-
- /* then cleanup the formpost chain */
- curl_formfree(formpost);
-.fi
-.SH AVAILABILITY
-Deprecated in 7.56.0.
-.SH RETURN VALUE
-None
-.SH "SEE ALSO"
-.BR curl_formadd (3),
-.BR curl_mime_init (3),
-.BR curl_mime_free (3)
diff --git a/docs/libcurl/curl_formfree.md b/docs/libcurl/curl_formfree.md
new file mode 100644
index 000000000..d2f90c03f
--- /dev/null
+++ b/docs/libcurl/curl_formfree.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_formfree
+Section: 3
+Source: libcurl
+See-also:
+ - curl_formadd (3)
+ - curl_mime_free (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+curl_formfree - free a previously build multipart form post chain
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_formfree(struct curl_httppost *form);
+~~~
+
+# DESCRIPTION
+
+This function is deprecated. Do not use. See curl_mime_init(3) instead!
+
+curl_formfree() is used to clean up data previously built/appended with
+curl_formadd(3). This must be called when the data has been used, which
+typically means after curl_easy_perform(3) has been called.
+
+The pointer to free is the same pointer you passed to the
+CURLOPT_HTTPPOST(3) option, which is the *firstitem* pointer from
+the curl_formadd(3) invoke(s).
+
+**form** is the pointer as returned from a previous call to
+curl_formadd(3) and may be NULL.
+
+Passing in a NULL pointer in *form* makes this function return immediately
+with no action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct curl_httppost *formpost;
+ struct curl_httppost *lastptr;
+
+ /* Fill in a file upload field */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "file",
+ CURLFORM_FILE, "nice-image.jpg",
+ CURLFORM_END);
+
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+
+ curl_easy_perform(curl);
+
+ /* then cleanup the formpost chain */
+ curl_formfree(formpost);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Deprecated in 7.56.0.
+
+# RETURN VALUE
+
+None
diff --git a/docs/libcurl/curl_formget.3 b/docs/libcurl/curl_formget.3
deleted file mode 100644
index 0ce761013..000000000
--- a/docs/libcurl/curl_formget.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_formget 3 "20 June 2006" "libcurl" "libcurl"
-.SH NAME
-curl_formget - serialize a previously built multipart form POST chain
-.SH SYNOPSIS
-.nf
-.B #include <curl/curl.h>
-
-int curl_formget(struct curl_httppost * form, void *userp,
- curl_formget_callback append );
-.SH DESCRIPTION
-curl_formget() is used to serialize data previously built/appended with
-\fIcurl_formadd(3)\fP. Accepts a void pointer as second argument named
-\fIuserp\fP which is passed as the first argument to the curl_formget_callback
-function.
-
-.BI "typedef size_t (*curl_formget_callback)(void *" userp, " const char *" buf,
-.BI " size_t " len ");"
-
-The curl_formget_callback is invoked for each part of the HTTP POST chain. The
-character buffer passed to the callback must not be freed. The callback should
-return the buffer length passed to it on success.
-
-If the \fBCURLFORM_STREAM\fP option is used in the formpost, it prevents
-\fIcurl_formget(3)\fP from working until you have performed the actual HTTP
-request. This, because first then does libcurl known which actual read
-callback to use!
-.SH EXAMPLE
-.nf
- size_t print_httppost_callback(void *arg, const char *buf, size_t len)
- {
- fwrite(buf, len, 1, stdout);
- (*(size_t *) arg) += len;
- return len;
- }
-
- size_t print_httppost(struct curl_httppost *post)
- {
- size_t total_size = 0;
- if(curl_formget(post, &total_size, print_httppost_callback)) {
- return (size_t) -1;
- }
- return total_size;
- }
-.SH AVAILABILITY
-This function was added in libcurl 7.15.5. The form API is deprecated in
-libcurl 7.56.0.
-.SH RETURN VALUE
-0 means everything was OK, non-zero means an error occurred
-.SH "SEE ALSO"
-.BR curl_formadd (3),
-.BR curl_mime_init (3)
diff --git a/docs/libcurl/curl_formget.md b/docs/libcurl/curl_formget.md
new file mode 100644
index 000000000..7130ee937
--- /dev/null
+++ b/docs/libcurl/curl_formget.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_formget
+Section: 3
+Source: libcurl
+See-also:
+ - curl_formadd (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+curl_formget - serialize a previously built multipart form POST chain
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int curl_formget(struct curl_httppost * form, void *userp,
+ curl_formget_callback append);
+~~~
+
+# DESCRIPTION
+
+curl_formget() serializes data previously built with curl_formadd(3). It
+accepts a void pointer as second argument named *userp* which is passed as
+the first argument to the curl_formget_callback function.
+
+~~~c
+ typedef size_t (*curl_formget_callback)(void *userp, const char *buf,
+ size_t len);"
+~~~
+
+The curl_formget_callback is invoked for each part of the HTTP POST chain. The
+character buffer passed to the callback must not be freed. The callback should
+return the buffer length passed to it on success.
+
+If the **CURLFORM_STREAM** option is used in the formpost, it prevents
+curl_formget(3) from working until you have performed the actual HTTP
+request. This, because first then does libcurl known which actual read
+callback to use!
+
+# EXAMPLE
+
+~~~c
+size_t print_httppost_callback(void *arg, const char *buf, size_t len)
+{
+ fwrite(buf, len, 1, stdout);
+ (*(size_t *) arg) += len;
+ return len;
+}
+
+size_t print_httppost(struct curl_httppost *post)
+{
+ size_t total_size = 0;
+ if(curl_formget(post, &total_size, print_httppost_callback)) {
+ return (size_t) -1;
+ }
+ return total_size;
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.15.5. The form API is deprecated in
+libcurl 7.56.0.
+
+# RETURN VALUE
+
+0 means everything was OK, non-zero means an error occurred
diff --git a/docs/libcurl/curl_free.3 b/docs/libcurl/curl_free.3
deleted file mode 100644
index 9192b9303..000000000
--- a/docs/libcurl/curl_free.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_free 3 "12 Aug 2003" "libcurl" "libcurl"
-.SH NAME
-curl_free - reclaim memory that has been obtained through a libcurl call
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_free(void *ptr);
-.fi
-.SH DESCRIPTION
-curl_free reclaims memory that has been obtained through a libcurl call. Use
-\fIcurl_free(3)\fP instead of free() to avoid anomalies that can result from
-differences in memory management between your application and libcurl.
-
-Passing in a NULL pointer in \fIptr\fP makes this function return immediately
-with no action.
-.SH EXAMPLE
-.nf
- char *width = curl_getenv("COLUMNS");
- if(width) {
- /* it was set! */
- curl_free(width);
- }
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-None
-.SH "SEE ALSO"
-.BR curl_easy_escape (3),
-.BR curl_easy_unescape (3)
diff --git a/docs/libcurl/curl_free.md b/docs/libcurl/curl_free.md
new file mode 100644
index 000000000..696394055
--- /dev/null
+++ b/docs/libcurl/curl_free.md
@@ -0,0 +1,52 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_free
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_escape (3)
+ - curl_easy_unescape (3)
+---
+
+# NAME
+
+curl_free - reclaim memory that has been obtained through a libcurl call
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_free(void *ptr);
+~~~
+
+# DESCRIPTION
+
+curl_free reclaims memory that has been obtained through a libcurl call. Use
+curl_free(3) instead of free() to avoid anomalies that can result from
+differences in memory management between your application and libcurl.
+
+Passing in a NULL pointer in *ptr* makes this function return immediately
+with no action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ char *width = curl_getenv("COLUMNS");
+ if(width) {
+ /* it was set! */
+ curl_free(width);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+None
diff --git a/docs/libcurl/curl_getdate.3 b/docs/libcurl/curl_getdate.3
deleted file mode 100644
index 2f88fdb99..000000000
--- a/docs/libcurl/curl_getdate.3
+++ /dev/null
@@ -1,122 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-a.TH curl_getdate 3 "12 Aug 2005" "libcurl" "libcurl"
-.SH NAME
-curl_getdate - Convert a date string to number of seconds
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-time_t curl_getdate(char *datestring, time_t *now);
-.fi
-.SH DESCRIPTION
-\fIcurl_getdate(3)\fP returns the number of seconds since the Epoch, January
-1st 1970 00:00:00 in the UTC time zone, for the date and time that the
-\fIdatestring\fP parameter specifies. The \fInow\fP parameter is not used,
-pass a NULL there.
-
-This function works with valid dates and does not always detect and reject
-wrong dates, such as February 30.
-
-.SH PARSING DATES AND TIMES
-A "date" is a string containing several items separated by whitespace. The
-order of the items is immaterial. A date string may contain many flavors of
-items:
-.TP 0.8i
-.B calendar date items
-Can be specified several ways. Month names can only be three-letter English
-abbreviations, numbers can be zero-prefixed and the year may use 2 or 4
-digits. Examples: 06 Nov 1994, 06-Nov-94 and Nov-94 6.
-.TP
-.B time of the day items
-This string specifies the time on a given day. You must specify it with 6
-digits with two colons: HH:MM:SS. If there is no time given in a provided date
-string, 00:00:00 is assumed. Example: 18:19:21.
-.TP
-.B time zone items
-Specifies international time zone. There are a few acronyms supported, but in
-general you should instead use the specific relative time compared to
-UTC. Supported formats include: -1200, MST, +0100.
-.TP
-.B day of the week items
-Specifies a day of the week. Days of the week may be spelled out in full
-(using English): `Sunday', `Monday', etc or they may be abbreviated to their
-first three letters. This is usually not info that adds anything.
-.TP
-.B pure numbers
-If a decimal number of the form YYYYMMDD appears, then YYYY is read as the
-year, MM as the month number and DD as the day of the month, for the specified
-calendar date.
-.SH EXAMPLE
-.nf
- time_t t;
- t = curl_getdate("Sun, 06 Nov 1994 08:49:37 GMT", NULL);
- t = curl_getdate("Sunday, 06-Nov-94 08:49:37 GMT", NULL);
- t = curl_getdate("Sun Nov 6 08:49:37 1994", NULL);
- t = curl_getdate("06 Nov 1994 08:49:37 GMT", NULL);
- t = curl_getdate("06-Nov-94 08:49:37 GMT", NULL);
- t = curl_getdate("Nov 6 08:49:37 1994", NULL);
- t = curl_getdate("06 Nov 1994 08:49:37", NULL);
- t = curl_getdate("06-Nov-94 08:49:37", NULL);
- t = curl_getdate("1994 Nov 6 08:49:37", NULL);
- t = curl_getdate("GMT 08:49:37 06-Nov-94 Sunday", NULL);
- t = curl_getdate("94 6 Nov 08:49:37", NULL);
- t = curl_getdate("1994 Nov 6", NULL);
- t = curl_getdate("06-Nov-94", NULL);
- t = curl_getdate("Sun Nov 6 94", NULL);
- t = curl_getdate("1994.Nov.6", NULL);
- t = curl_getdate("Sun/Nov/6/94/GMT", NULL);
- t = curl_getdate("Sun, 06 Nov 1994 08:49:37 CET", NULL);
- t = curl_getdate("06 Nov 1994 08:49:37 EST", NULL);
- t = curl_getdate("Sun, 12 Sep 2004 15:05:58 -0700", NULL);
- t = curl_getdate("Sat, 11 Sep 2004 21:32:11 +0200", NULL);
- t = curl_getdate("20040912 15:05:58 -0700", NULL);
- t = curl_getdate("20040911 +0200", NULL);
-.fi
-.SH STANDARDS
-This parser handles date formats specified in RFC 822 (including the update in
-RFC 1123) using time zone name or time zone delta and RFC 850 (obsoleted by
-RFC 1036) and ANSI C's \fIasctime()\fP format.
-
-These formats are the only ones RFC 7231 says HTTP applications may use.
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-This function returns -1 when it fails to parse the date string. Otherwise it
-returns the number of seconds as described.
-
-On systems with a signed 32 bit time_t: if the year is larger than 2037 or
-less than 1903, this function returns -1.
-
-On systems with an unsigned 32 bit time_t: if the year is larger than 2106 or
-less than 1970, this function returns -1.
-
-On systems with 64 bit time_t: if the year is less than 1583, this function
-returns -1. (The Gregorian calendar was first introduced 1582 so no "real"
-dates in this way of doing dates existed before then.)
-.SH "SEE ALSO"
-.BR curl_easy_escape (3),
-.BR curl_easy_unescape (3),
-.BR CURLOPT_TIMECONDITION (3),
-.BR CURLOPT_TIMEVALUE (3)
diff --git a/docs/libcurl/curl_getdate.md b/docs/libcurl/curl_getdate.md
new file mode 100644
index 000000000..e4fbf0394
--- /dev/null
+++ b/docs/libcurl/curl_getdate.md
@@ -0,0 +1,128 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_getdate
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TIMECONDITION (3)
+ - CURLOPT_TIMEVALUE (3)
+ - curl_easy_escape (3)
+ - curl_easy_unescape (3)
+---
+
+# NAME
+
+curl_getdate - Convert a date string to number of seconds
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+time_t curl_getdate(const char *datestring, const time_t *now);
+~~~
+
+# DESCRIPTION
+
+curl_getdate(3) returns the number of seconds since the Epoch, January
+1st 1970 00:00:00 in the UTC time zone, for the date and time that the
+*datestring* parameter specifies. The *now* parameter is not used,
+pass a NULL there.
+
+This function works with valid dates and does not always detect and reject
+wrong dates, such as February 30.
+
+# PARSING DATES AND TIMES
+
+A "date" is a string containing several items separated by whitespace. The
+order of the items is immaterial. A date string may contain many flavors of
+items:
+
+## calendar date items
+
+Can be specified several ways. Month names can only be three-letter English
+abbreviations, numbers can be zero-prefixed and the year may use 2 or 4
+digits. Examples: 06 Nov 1994, 06-Nov-94 and Nov-94 6.
+
+## time of the day items
+
+This string specifies the time on a given day. You must specify it with 6
+digits with two colons: HH:MM:SS. If there is no time given in a provided date
+string, 00:00:00 is assumed. Example: 18:19:21.
+
+## time zone items
+
+Specifies international time zone. There are a few acronyms supported, but in
+general you should instead use the specific relative time compared to
+UTC. Supported formats include: -1200, MST, +0100.
+
+## day of the week items
+
+Specifies a day of the week. Days of the week may be spelled out in full
+(using English): `Sunday', `Monday', etc or they may be abbreviated to their
+first three letters. This is usually not info that adds anything.
+
+## pure numbers
+
+If a decimal number of the form YYYYMMDD appears, then YYYY is read as the
+year, MM as the month number and DD as the day of the month, for the specified
+calendar date.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ time_t t;
+ t = curl_getdate("Sun, 06 Nov 1994 08:49:37 GMT", NULL);
+ t = curl_getdate("Sunday, 06-Nov-94 08:49:37 GMT", NULL);
+ t = curl_getdate("Sun Nov 6 08:49:37 1994", NULL);
+ t = curl_getdate("06 Nov 1994 08:49:37 GMT", NULL);
+ t = curl_getdate("06-Nov-94 08:49:37 GMT", NULL);
+ t = curl_getdate("Nov 6 08:49:37 1994", NULL);
+ t = curl_getdate("06 Nov 1994 08:49:37", NULL);
+ t = curl_getdate("06-Nov-94 08:49:37", NULL);
+ t = curl_getdate("1994 Nov 6 08:49:37", NULL);
+ t = curl_getdate("GMT 08:49:37 06-Nov-94 Sunday", NULL);
+ t = curl_getdate("94 6 Nov 08:49:37", NULL);
+ t = curl_getdate("1994 Nov 6", NULL);
+ t = curl_getdate("06-Nov-94", NULL);
+ t = curl_getdate("Sun Nov 6 94", NULL);
+ t = curl_getdate("1994.Nov.6", NULL);
+ t = curl_getdate("Sun/Nov/6/94/GMT", NULL);
+ t = curl_getdate("Sun, 06 Nov 1994 08:49:37 CET", NULL);
+ t = curl_getdate("06 Nov 1994 08:49:37 EST", NULL);
+ t = curl_getdate("Sun, 12 Sep 2004 15:05:58 -0700", NULL);
+ t = curl_getdate("Sat, 11 Sep 2004 21:32:11 +0200", NULL);
+ t = curl_getdate("20040912 15:05:58 -0700", NULL);
+ t = curl_getdate("20040911 +0200", NULL);
+}
+~~~
+
+# STANDARDS
+
+This parser handles date formats specified in RFC 822 (including the update in
+RFC 1123) using time zone name or time zone delta and RFC 850 (obsoleted by
+RFC 1036) and ANSI C's *asctime()* format.
+
+These formats are the only ones RFC 7231 says HTTP applications may use.
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+This function returns -1 when it fails to parse the date string. Otherwise it
+returns the number of seconds as described.
+
+On systems with a signed 32 bit time_t: if the year is larger than 2037 or
+less than 1903, this function returns -1.
+
+On systems with an unsigned 32 bit time_t: if the year is larger than 2106 or
+less than 1970, this function returns -1.
+
+On systems with 64 bit time_t: if the year is less than 1583, this function
+returns -1. (The Gregorian calendar was first introduced 1582 so no "real"
+dates in this way of doing dates existed before then.)
diff --git a/docs/libcurl/curl_getenv.3 b/docs/libcurl/curl_getenv.3
deleted file mode 100644
index e74357f8a..000000000
--- a/docs/libcurl/curl_getenv.3
+++ /dev/null
@@ -1,57 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_getenv 3 "30 April 2004" "libcurl" "libcurl"
-.SH NAME
-curl_getenv - return value for environment name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_getenv(const char *name);
-.fi
-.SH DESCRIPTION
-curl_getenv() is a portable wrapper for the getenv() function, meant to
-emulate its behavior and provide an identical interface for all operating
-systems libcurl builds on (including win32).
-
-You must \fIcurl_free(3)\fP the returned string when you are done with it.
-.SH EXAMPLE
-.nf
- char *width = curl_getenv("COLUMNS");
- if(width) {
- /* it was set! */
- curl_free(width);
- }
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-A pointer to a null-terminated string or NULL if it failed to find the
-specified name.
-.SH NOTE
-Under unix operating systems, there is no point in returning an allocated
-memory, although other systems does not work properly if this is not done. The
-unix implementation thus suffers slightly from the drawbacks of other systems.
-.SH "SEE ALSO"
-.BR getenv (3C)
diff --git a/docs/libcurl/curl_getenv.md b/docs/libcurl/curl_getenv.md
new file mode 100644
index 000000000..dbf326d11
--- /dev/null
+++ b/docs/libcurl/curl_getenv.md
@@ -0,0 +1,57 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_getenv
+Section: 3
+Source: libcurl
+See-also:
+ - getenv (3C)
+---
+
+# NAME
+
+curl_getenv - return value for environment name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_getenv(const char *name);
+~~~
+
+# DESCRIPTION
+
+curl_getenv() is a portable wrapper for the getenv() function, meant to
+emulate its behavior and provide an identical interface for all operating
+systems libcurl builds on (including win32).
+
+You must curl_free(3) the returned string when you are done with it.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ char *width = curl_getenv("COLUMNS");
+ if(width) {
+ /* it was set! */
+ curl_free(width);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+A pointer to a null-terminated string or NULL if it failed to find the
+specified name.
+
+# NOTE
+
+Under unix operating systems, there is no point in returning an allocated
+memory, although other systems does not work properly if this is not done. The
+unix implementation thus suffers slightly from the drawbacks of other systems.
diff --git a/docs/libcurl/curl_global_cleanup.3 b/docs/libcurl/curl_global_cleanup.3
deleted file mode 100644
index b40949411..000000000
--- a/docs/libcurl/curl_global_cleanup.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_global_cleanup 3 "17 Feb 2006" "libcurl" "libcurl"
-.SH NAME
-curl_global_cleanup - global libcurl cleanup
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_global_cleanup(void);
-.fi
-.SH DESCRIPTION
-This function releases resources acquired by \fIcurl_global_init(3)\fP.
-
-You should call \fIcurl_global_cleanup(3)\fP once for each call you make to
-\fIcurl_global_init(3)\fP, after you are done using libcurl.
-
-This function is thread-safe since libcurl 7.84.0 if
-\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
-(most platforms).
-
-If this is not thread-safe, you must not call this function when any other
-thread in the program (i.e. a thread sharing the same memory) is running.
-This does not just mean no other thread that is using libcurl. Because
-\fIcurl_global_cleanup(3)\fP calls functions of other libraries that are
-similarly thread unsafe, it could conflict with any other thread that uses
-these other libraries.
-
-See the description in \fIlibcurl(3)\fP of global environment requirements for
-details of how to use this function.
-.SH CAUTION
-\fIcurl_global_cleanup(3)\fP does not block waiting for any libcurl-created
-threads to terminate (such as threads used for name resolving). If a module
-containing libcurl is dynamically unloaded while libcurl-created threads are
-still running then your program may crash or other corruption may occur. We
-recommend you do not run libcurl from any module that may be unloaded
-dynamically. This behavior may be addressed in the future.
-.SH EXAMPLE
-.nf
- curl_global_init(CURL_GLOBAL_DEFAULT);
-
- /* use libcurl, then before exiting... */
-
- curl_global_cleanup();
-.fi
-.SH AVAILABILITY
-Added in 7.8
-.SH RETURN VALUE
-None
-.SH "SEE ALSO"
-.BR curl_global_init (3),
-.BR libcurl (3),
-.BR libcurl-thread (3)
diff --git a/docs/libcurl/curl_global_cleanup.md b/docs/libcurl/curl_global_cleanup.md
new file mode 100644
index 000000000..5502e718d
--- /dev/null
+++ b/docs/libcurl/curl_global_cleanup.md
@@ -0,0 +1,74 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_global_cleanup
+Section: 3
+Source: libcurl
+See-also:
+ - curl_global_init (3)
+ - libcurl (3)
+ - libcurl-thread (3)
+---
+
+# NAME
+
+curl_global_cleanup - global libcurl cleanup
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_global_cleanup(void);
+~~~
+
+# DESCRIPTION
+
+This function releases resources acquired by curl_global_init(3).
+
+You should call curl_global_cleanup(3) once for each call you make to
+curl_global_init(3), after you are done using libcurl.
+
+This function is thread-safe since libcurl 7.84.0 if
+curl_version_info(3) has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms).
+
+If this is not thread-safe, you must not call this function when any other
+thread in the program (i.e. a thread sharing the same memory) is running.
+This does not just mean no other thread that is using libcurl. Because
+curl_global_cleanup(3) calls functions of other libraries that are
+similarly thread unsafe, it could conflict with any other thread that uses
+these other libraries.
+
+See the description in libcurl(3) of global environment requirements for
+details of how to use this function.
+
+# CAUTION
+
+curl_global_cleanup(3) does not block waiting for any libcurl-created
+threads to terminate (such as threads used for name resolving). If a module
+containing libcurl is dynamically unloaded while libcurl-created threads are
+still running then your program may crash or other corruption may occur. We
+recommend you do not run libcurl from any module that may be unloaded
+dynamically. This behavior may be addressed in the future.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+
+ /* use libcurl, then before exiting... */
+
+ curl_global_cleanup();
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.8
+
+# RETURN VALUE
+
+None
diff --git a/docs/libcurl/curl_global_init.3 b/docs/libcurl/curl_global_init.3
deleted file mode 100644
index 74658c633..000000000
--- a/docs/libcurl/curl_global_init.3
+++ /dev/null
@@ -1,121 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_global_init 3 "11 May 2004" "libcurl" "libcurl"
-.SH NAME
-curl_global_init - Global libcurl initialization
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_global_init(long flags);
-.fi
-.SH DESCRIPTION
-This function sets up the program environment that libcurl needs. Think of it
-as an extension of the library loader.
-
-This function must be called at least once within a program (a program is all
-the code that shares a memory space) before the program calls any other
-function in libcurl. The environment it sets up is constant for the life of
-the program and is the same for every program, so multiple calls have the same
-effect as one call.
-
-The flags option is a bit pattern that tells libcurl exactly what features to
-init, as described below. Set the desired bits by ORing the values together.
-In normal operation, you must specify CURL_GLOBAL_ALL. Do not use any other
-value unless you are familiar with it and mean to control internal operations
-of libcurl.
-
-This function is thread-safe since libcurl 7.84.0 if
-\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
-(most platforms).
-
-If this is not thread-safe, you must not call this function when any other
-thread in the program (i.e. a thread sharing the same memory) is running.
-This does not just mean no other thread that is using libcurl. Because
-\fIcurl_global_init(3)\fP calls functions of other libraries that are
-similarly thread unsafe, it could conflict with any other thread that uses
-these other libraries.
-
-If you are initializing libcurl from a Windows DLL you should not initialize
-it from \fIDllMain\fP or a static initializer because Windows holds the loader
-lock during that time and it could cause a deadlock.
-
-See the description in \fIlibcurl(3)\fP of global environment requirements for
-details of how to use this function.
-.SH FLAGS
-.IP CURL_GLOBAL_ALL
-Initialize everything possible. This sets all known bits except
-\fBCURL_GLOBAL_ACK_EINTR\fP.
-
-.IP CURL_GLOBAL_SSL
-(This flag's presence or absence serves no meaning since 7.57.0. The
-description below is for older libcurl versions.)
-
-Initialize SSL.
-
-The implication here is that if this bit is not set, the initialization of the
-SSL layer needs to be done by the application or at least outside of
-libcurl. The exact procedure how to do SSL initialization depends on the TLS
-backend libcurl uses.
-
-Doing TLS based transfers without having the TLS layer initialized may lead to
-unexpected behaviors.
-.IP CURL_GLOBAL_WIN32
-Initialize the Win32 socket libraries.
-
-The implication here is that if this bit is not set, the initialization of
-winsock has to be done by the application or you risk getting undefined
-behaviors. This option exists for when the initialization is handled outside
-of libcurl so there is no need for libcurl to do it again.
-.IP CURL_GLOBAL_NOTHING
-Initialize nothing extra. This sets no bit.
-.IP CURL_GLOBAL_DEFAULT
-A sensible default. It initializes both SSL and Win32. Right now, this equals
-the functionality of the \fBCURL_GLOBAL_ALL\fP mask.
-.IP CURL_GLOBAL_ACK_EINTR
-This bit has no point since 7.69.0 but its behavior is instead the default.
-
-Before 7.69.0: when this flag is set, curl acknowledges EINTR condition when
-connecting or when waiting for data. Otherwise, curl waits until full timeout
-elapses. (Added in 7.30.0)
-.SH EXAMPLE
-.nf
- curl_global_init(CURL_GLOBAL_DEFAULT);
-
- /* use libcurl, then before exiting... */
-
- curl_global_cleanup();
-.fi
-.SH AVAILABILITY
-Added in 7.8
-.SH RETURN VALUE
-If this function returns non-zero, something went wrong and you cannot use the
-other curl functions.
-.SH "SEE ALSO"
-.BR curl_easy_init (3),
-.BR curl_global_cleanup (3),
-.BR curl_global_init_mem (3),
-.BR curl_global_sslset (3),
-.BR curl_global_trace (3),
-.BR libcurl (3)
diff --git a/docs/libcurl/curl_global_init.md b/docs/libcurl/curl_global_init.md
new file mode 100644
index 000000000..5c00e862d
--- /dev/null
+++ b/docs/libcurl/curl_global_init.md
@@ -0,0 +1,131 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_global_init
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_init (3)
+ - curl_global_cleanup (3)
+ - curl_global_init_mem (3)
+ - curl_global_sslset (3)
+ - curl_global_trace (3)
+ - libcurl (3)
+---
+
+# NAME
+
+curl_global_init - Global libcurl initialization
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_global_init(long flags);
+~~~
+
+# DESCRIPTION
+
+This function sets up the program environment that libcurl needs. Think of it
+as an extension of the library loader.
+
+This function must be called at least once within a program (a program is all
+the code that shares a memory space) before the program calls any other
+function in libcurl. The environment it sets up is constant for the life of
+the program and is the same for every program, so multiple calls have the same
+effect as one call.
+
+The flags option is a bit pattern that tells libcurl exactly what features to
+init, as described below. Set the desired bits by ORing the values together.
+In normal operation, you must specify CURL_GLOBAL_ALL. Do not use any other
+value unless you are familiar with it and mean to control internal operations
+of libcurl.
+
+This function is thread-safe since libcurl 7.84.0 if
+curl_version_info(3) has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms).
+
+If this is not thread-safe, you must not call this function when any other
+thread in the program (i.e. a thread sharing the same memory) is running.
+This does not just mean no other thread that is using libcurl. Because
+curl_global_init(3) calls functions of other libraries that are
+similarly thread unsafe, it could conflict with any other thread that uses
+these other libraries.
+
+If you are initializing libcurl from a Windows DLL you should not initialize
+it from *DllMain* or a static initializer because Windows holds the loader
+lock during that time and it could cause a deadlock.
+
+See the description in libcurl(3) of global environment requirements for
+details of how to use this function.
+
+# FLAGS
+
+## CURL_GLOBAL_ALL
+
+Initialize everything possible. This sets all known bits except
+**CURL_GLOBAL_ACK_EINTR**.
+
+## CURL_GLOBAL_SSL
+
+(This flag's presence or absence serves no meaning since 7.57.0. The
+description below is for older libcurl versions.)
+
+Initialize SSL.
+
+The implication here is that if this bit is not set, the initialization of the
+SSL layer needs to be done by the application or at least outside of
+libcurl. The exact procedure how to do SSL initialization depends on the TLS
+backend libcurl uses.
+
+Doing TLS based transfers without having the TLS layer initialized may lead to
+unexpected behaviors.
+
+## CURL_GLOBAL_WIN32
+
+Initialize the Win32 socket libraries.
+
+The implication here is that if this bit is not set, the initialization of
+winsock has to be done by the application or you risk getting undefined
+behaviors. This option exists for when the initialization is handled outside
+of libcurl so there is no need for libcurl to do it again.
+
+## CURL_GLOBAL_NOTHING
+
+Initialize nothing extra. This sets no bit.
+
+## CURL_GLOBAL_DEFAULT
+
+A sensible default. It initializes both SSL and Win32. Right now, this equals
+the functionality of the **CURL_GLOBAL_ALL** mask.
+
+## CURL_GLOBAL_ACK_EINTR
+
+This bit has no point since 7.69.0 but its behavior is instead the default.
+
+Before 7.69.0: when this flag is set, curl acknowledges EINTR condition when
+connecting or when waiting for data. Otherwise, curl waits until full timeout
+elapses. (Added in 7.30.0)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+
+ /* use libcurl, then before exiting... */
+
+ curl_global_cleanup();
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.8
+
+# RETURN VALUE
+
+If this function returns non-zero, something went wrong and you cannot use the
+other curl functions.
diff --git a/docs/libcurl/curl_global_init_mem.3 b/docs/libcurl/curl_global_init_mem.3
deleted file mode 100644
index 99f0f963c..000000000
--- a/docs/libcurl/curl_global_init_mem.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_global_init_mem 3 "10 May 2004" "libcurl" "libcurl"
-.SH NAME
-curl_global_init_mem - Global libcurl initialization with memory callbacks
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_global_init_mem(long flags,
- curl_malloc_callback m,
- curl_free_callback f,
- curl_realloc_callback r,
- curl_strdup_callback s,
- curl_calloc_callback c);
-.fi
-.SH DESCRIPTION
-This function works exactly as \fIcurl_global_init(3)\fP with one addition: it
-allows the application to set callbacks to replace the otherwise used internal
-memory functions.
-
-If you are using libcurl from multiple threads or libcurl was built with the
-threaded resolver option then the callback functions must be thread safe. The
-threaded resolver is a common build option to enable (and in some cases the
-default) so we strongly urge you to make your callback functions thread safe.
-
-All callback arguments must be set to valid function pointers. The
-prototypes for the given callbacks must match these:
-.IP "void *malloc_callback(size_t size);"
-To replace malloc()
-.IP "void free_callback(void *ptr);"
-To replace free()
-.IP "void *realloc_callback(void *ptr, size_t size);"
-To replace realloc()
-.IP "char *strdup_callback(const char *str);"
-To replace strdup()
-.IP "void *calloc_callback(size_t nmemb, size_t size);"
-To replace calloc()
-.PP
-This function is otherwise the same as \fIcurl_global_init(3)\fP, please refer
-to that man page for documentation.
-.SH CAUTION
-Manipulating these gives considerable powers to the application to severely
-screw things up for libcurl. Take care!
-.SH EXAMPLE
-.nf
- curl_global_init_mem(CURL_GLOBAL_DEFAULT, curl_malloc_cb,
- curl_free_cb, curl_realloc_cb,
- curl_strdup_cb, curl_calloc_cb);
-.fi
-.SH AVAILABILITY
-Added in 7.12.0
-.SH RETURN VALUE
-CURLE_OK (0) means everything was OK, non-zero means an error occurred as
-\fI<curl/curl.h>\fP defines - see \fIlibcurl-errors(3)\fP.
-.SH "SEE ALSO"
-.BR curl_global_init (3),
-.BR curl_global_cleanup (3)
diff --git a/docs/libcurl/curl_global_init_mem.md b/docs/libcurl/curl_global_init_mem.md
new file mode 100644
index 000000000..3bf468f18
--- /dev/null
+++ b/docs/libcurl/curl_global_init_mem.md
@@ -0,0 +1,95 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_global_init_mem
+Section: 3
+Source: libcurl
+See-also:
+ - curl_global_cleanup (3)
+ - curl_global_init (3)
+---
+
+# NAME
+
+curl_global_init_mem - Global libcurl initialization with memory callbacks
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_global_init_mem(long flags,
+ curl_malloc_callback m,
+ curl_free_callback f,
+ curl_realloc_callback r,
+ curl_strdup_callback s,
+ curl_calloc_callback c);
+~~~
+
+# DESCRIPTION
+
+This function works exactly as curl_global_init(3) with one addition: it
+allows the application to set callbacks to replace the otherwise used internal
+memory functions.
+
+If you are using libcurl from multiple threads or libcurl was built with the
+threaded resolver option then the callback functions must be thread safe. The
+threaded resolver is a common build option to enable (and in some cases the
+default) so we strongly urge you to make your callback functions thread safe.
+
+All callback arguments must be set to valid function pointers. The
+prototypes for the given callbacks must match these:
+
+## void *malloc_callback(size_t size);
+
+To replace malloc()
+
+## void free_callback(void *ptr);
+
+To replace free()
+
+## void *realloc_callback(void *ptr, size_t size);
+
+To replace realloc()
+
+## char *strdup_callback(const char *str);
+
+To replace strdup()
+
+## void *calloc_callback(size_t nmemb, size_t size);
+
+To replace calloc()
+
+This function is otherwise the same as curl_global_init(3), please refer
+to that man page for documentation.
+
+# CAUTION
+
+Manipulating these gives considerable powers to the application to severely
+screw things up for libcurl. Take care!
+
+# EXAMPLE
+
+~~~c
+extern void *malloc_cb(size_t);
+extern void free_cb(void *);
+extern void *realloc_cb(void *, size_t);
+extern char *strdup_cb(const char *);
+extern void *calloc_cb(size_t, size_t);
+
+int main(void)
+{
+ curl_global_init_mem(CURL_GLOBAL_DEFAULT, malloc_cb,
+ free_cb, realloc_cb,
+ strdup_cb, calloc_cb);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.12.0
+
+# RETURN VALUE
+
+CURLE_OK (0) means everything was OK, non-zero means an error occurred as
+*<curl/curl.h>* defines - see libcurl-errors(3).
diff --git a/docs/libcurl/curl_global_sslset.3 b/docs/libcurl/curl_global_sslset.3
deleted file mode 100644
index e1d5bdfb4..000000000
--- a/docs/libcurl/curl_global_sslset.3
+++ /dev/null
@@ -1,133 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_global_sslset 3 "15 July 2017" "libcurl" "libcurl"
-.SH NAME
-curl_global_sslset - Select SSL backend to use with libcurl
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef struct {
- curl_sslbackend id;
- const char *name;
-} curl_ssl_backend;
-
-typedef enum {
- CURLSSLBACKEND_NONE = 0,
- CURLSSLBACKEND_OPENSSL = 1, /* or one of its forks */
- CURLSSLBACKEND_GNUTLS = 2,
- CURLSSLBACKEND_NSS = 3,
- CURLSSLBACKEND_GSKIT = 5, /* deprecated */
- CURLSSLBACKEND_POLARSSL = 6, /* deprecated */
- CURLSSLBACKEND_WOLFSSL = 7,
- CURLSSLBACKEND_SCHANNEL = 8,
- CURLSSLBACKEND_SECURETRANSPORT = 9,
- CURLSSLBACKEND_AXTLS = 10, /* deprecated */
- CURLSSLBACKEND_MBEDTLS = 11,
- CURLSSLBACKEND_MESALINK = 12, /* deprecated */
- CURLSSLBACKEND_BEARSSL = 13,
- CURLSSLBACKEND_RUSTLS = 14
-} curl_sslbackend;
-
-CURLsslset curl_global_sslset(curl_sslbackend id,
- const char *name,
- curl_ssl_backend ***avail);
-.fi
-.SH DESCRIPTION
-This function configures at runtime which SSL backend to use with
-libcurl. This function can only be used to select an SSL backend once, and it
-must be called \fBbefore\fP \fIcurl_global_init(3)\fP.
-
-The backend can be identified by the \fIid\fP
-(e.g. \fBCURLSSLBACKEND_OPENSSL\fP). The backend can also be specified via the
-\fIname\fP parameter for a case insensitive match (passing
-\fBCURLSSLBACKEND_NONE\fP as \fIid\fP). If both \fIid\fP and \fIname\fP are
-specified, the \fIname\fP is ignored.
-
-If neither \fIid\fP nor \fPname\fP are specified, the function fails with
-\fBCURLSSLSET_UNKNOWN_BACKEND\fP and set the \fIavail\fP pointer to the
-NULL-terminated list of available backends. The available backends are those
-that this particular build of libcurl supports.
-
-Since libcurl 7.60.0, the \fIavail\fP pointer is always set to the list of
-alternatives if non-NULL.
-
-Upon success, the function returns \fBCURLSSLSET_OK\fP.
-
-If the specified SSL backend is not available, the function returns
-\fBCURLSSLSET_UNKNOWN_BACKEND\fP and sets the \fIavail\fP pointer to a
-NULL-terminated list of available SSL backends. In this case, you may call the
-function again to try to select a different backend.
-
-The SSL backend can be set only once. If it has already been set, a subsequent
-attempt to change it results in a \fBCURLSSLSET_TOO_LATE\fP getting returned.
-
-This function is thread-safe since libcurl 7.84.0 if
-\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
-(most platforms).
-
-If this is not thread-safe, you must not call this function when any other
-thread in the program (i.e. a thread sharing the same memory) is running.
-This does not just mean no other thread that is using libcurl.
-.SH OpenSSL
-The name "OpenSSL" is used for all versions of OpenSSL and its associated
-forks/flavors in this function. OpenSSL, BoringSSL, libressl, quictls and
-AmiSSL are all supported by libcurl, but in the eyes of
-\fIcurl_global_sslset(3)\fP they are all just "OpenSSL". They all mostly
-provide the same API.
-
-\fIcurl_version_info(3)\fP can return more specific info about the exact
-OpenSSL flavor and version number is use.
-.SH EXAMPLE
-.nf
- /* choose a specific backend */
- curl_global_sslset(CURLSSLBACKEND_WOLFSSL, NULL, NULL);
-
- /* list the available ones */
- const curl_ssl_backend **list;
- curl_global_sslset(CURLSSLBACKEND_NONE, NULL, &list);
-
- for(i = 0; list[i]; i++)
- printf("SSL backend #%d: '%s' (ID: %d)\\n",
- i, list[i]->name, list[i]->id);
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.56.0. Before this version, there was no
-support for choosing SSL backends at runtime.
-.SH RETURN VALUE
-If this function returns \fICURLSSLSET_OK\fP, the backend was successfully
-selected.
-
-If the chosen backend is unknown (or support for the chosen backend has not
-been compiled into libcurl), the function returns
-\fICURLSSLSET_UNKNOWN_BACKEND\fP.
-
-If the backend had been configured previously, or if \fIcurl_global_init(3)\fP
-has already been called, the function returns \fICURLSSLSET_TOO_LATE\fP.
-
-If this libcurl was built completely without SSL support, with no backends at
-all, this function returns \fICURLSSLSET_NO_BACKENDS\fP.
-.SH "SEE ALSO"
-.BR curl_global_init (3),
-.BR libcurl (3)
diff --git a/docs/libcurl/curl_global_sslset.md b/docs/libcurl/curl_global_sslset.md
new file mode 100644
index 000000000..6f50867a1
--- /dev/null
+++ b/docs/libcurl/curl_global_sslset.md
@@ -0,0 +1,138 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_global_sslset
+Section: 3
+Source: libcurl
+See-also:
+ - curl_global_init (3)
+ - libcurl (3)
+---
+
+# NAME
+
+curl_global_sslset - Select SSL backend to use with libcurl
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLsslset curl_global_sslset(curl_sslbackend id,
+ const char *name,
+ const curl_ssl_backend ***avail);
+~~~
+
+# DESCRIPTION
+
+This function configures at runtime which SSL backend to use with
+libcurl. This function can only be used to select an SSL backend once, and it
+must be called **before** curl_global_init(3).
+
+The backend can be identified by the *id*
+(e.g. **CURLSSLBACKEND_OPENSSL**). The backend can also be specified via the
+*name* parameter for a case insensitive match (passing
+**CURLSSLBACKEND_NONE** as *id*). If both *id* and *name* are
+specified, the *name* is ignored.
+
+If neither *id* nor *name* are specified, the function fails with
+**CURLSSLSET_UNKNOWN_BACKEND** and set the *avail* pointer to the
+NULL-terminated list of available backends. The available backends are those
+that this particular build of libcurl supports.
+
+Since libcurl 7.60.0, the *avail* pointer is always set to the list of
+alternatives if non-NULL.
+
+Upon success, the function returns **CURLSSLSET_OK**.
+
+If the specified SSL backend is not available, the function returns
+**CURLSSLSET_UNKNOWN_BACKEND** and sets the *avail* pointer to a
+NULL-terminated list of available SSL backends. In this case, you may call the
+function again to try to select a different backend.
+
+The SSL backend can be set only once. If it has already been set, a subsequent
+attempt to change it results in a **CURLSSLSET_TOO_LATE** getting returned.
+
+This function is thread-safe since libcurl 7.84.0 if
+curl_version_info(3) has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms).
+
+If this is not thread-safe, you must not call this function when any other
+thread in the program (i.e. a thread sharing the same memory) is running.
+This does not just mean no other thread that is using libcurl.
+
+# OpenSSL
+
+The name "OpenSSL" is used for all versions of OpenSSL and its associated
+forks/flavors in this function. OpenSSL, BoringSSL, libressl, quictls and
+AmiSSL are all supported by libcurl, but in the eyes of
+curl_global_sslset(3) they are all just "OpenSSL". They all mostly
+provide the same API.
+
+curl_version_info(3) can return more specific info about the exact
+OpenSSL flavor and version number is use.
+
+# struct
+
+~~~c
+typedef struct {
+ curl_sslbackend id;
+ const char *name;
+} curl_ssl_backend;
+
+typedef enum {
+ CURLSSLBACKEND_NONE = 0,
+ CURLSSLBACKEND_OPENSSL = 1, /* or one of its forks */
+ CURLSSLBACKEND_GNUTLS = 2,
+ CURLSSLBACKEND_NSS = 3,
+ CURLSSLBACKEND_GSKIT = 5, /* deprecated */
+ CURLSSLBACKEND_POLARSSL = 6, /* deprecated */
+ CURLSSLBACKEND_WOLFSSL = 7,
+ CURLSSLBACKEND_SCHANNEL = 8,
+ CURLSSLBACKEND_SECURETRANSPORT = 9,
+ CURLSSLBACKEND_AXTLS = 10, /* deprecated */
+ CURLSSLBACKEND_MBEDTLS = 11,
+ CURLSSLBACKEND_MESALINK = 12, /* deprecated */
+ CURLSSLBACKEND_BEARSSL = 13,
+ CURLSSLBACKEND_RUSTLS = 14
+} curl_sslbackend;
+~~~
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ int i;
+ /* choose a specific backend */
+ curl_global_sslset(CURLSSLBACKEND_WOLFSSL, NULL, NULL);
+
+ /* list the available ones */
+ const curl_ssl_backend **list;
+ curl_global_sslset(CURLSSLBACKEND_NONE, NULL, &list);
+
+ for(i = 0; list[i]; i++)
+ printf("SSL backend #%d: '%s' (ID: %d)\n",
+ i, list[i]->name, list[i]->id);
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.56.0. Before this version, there was no
+support for choosing SSL backends at runtime.
+
+# RETURN VALUE
+
+If this function returns *CURLSSLSET_OK*, the backend was successfully
+selected.
+
+If the chosen backend is unknown (or support for the chosen backend has not
+been compiled into libcurl), the function returns
+*CURLSSLSET_UNKNOWN_BACKEND*.
+
+If the backend had been configured previously, or if curl_global_init(3)
+has already been called, the function returns *CURLSSLSET_TOO_LATE*.
+
+If this libcurl was built completely without SSL support, with no backends at
+all, this function returns *CURLSSLSET_NO_BACKENDS*.
diff --git a/docs/libcurl/curl_global_trace.3 b/docs/libcurl/curl_global_trace.3
deleted file mode 100644
index 8f16bb4ab..000000000
--- a/docs/libcurl/curl_global_trace.3
+++ /dev/null
@@ -1,118 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_global_trace 3 "01 August 2023" "libcurl" "libcurl"
-.SH NAME
-curl_global_trace - Global libcurl logging configuration
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_global_trace(const char *config);
-.fi
-.SH DESCRIPTION
-This function configures the logging behavior, allowing to make some
-parts of curl more verbose or silent than others.
-
-This function may be called during the initialization phase of a program. It
-does not have to be. It can be called several times even, possibly overwriting
-settings of previous calls.
-
-Calling this function after transfers have been started is undefined. On
-some platforms/architectures it might take effect, on others not.
-
-This function is thread-safe since libcurl 8.3.0 if
-\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
-(most platforms).
-
-If this is not thread-safe, you must not call this function when any other
-thread in the program (i.e. a thread sharing the same memory) is running.
-This does not just mean no other thread that is using libcurl. Because
-\fIcurl_global_init(3)\fP may call functions of other libraries that are
-similarly thread unsafe, it could conflict with any other thread that uses
-these other libraries.
-
-If you are initializing libcurl from a Windows DLL you should not initialize
-it from \fIDllMain\fP or a static initializer because Windows holds the loader
-lock during that time and it could cause a deadlock.
-
-The \fIconfig\fP string is a list of comma-separated component names. Names
-are case-insensitive and unknown names are ignored. The special name "all"
-applies to all components. Names may be prefixed with '+' or '-' to enable
-or disable detailed logging for a component.
-
-The list of component names is not part of curl's public API. Names may be
-added or disappear in future versions of libcurl. Since unknown names are
-silently ignored, outdated log configurations does not cause errors when
-upgrading libcurl. Given that, some names can be expected to be fairly stable
-and are listed below for easy reference.
-
-Note that log configuration applies only to transfers where debug logging
-is enabled. See \fICURLOPT_VERBOSE(3)\fP or \fICURLOPT_DEBUGFUNCTION(3)\fP
-on how to control that.
-
-.SH TRACE COMPONENTS
-.IP tcp
-Tracing of TCP socket handling: connect, reads, writes.
-.IP ssl
-Tracing of SSL/TLS operations, whichever SSL backend is used in your build.
-.IP http/2
-Details about HTTP/2 handling: frames, events, I/O, etc.
-.IP http/3
-Details about HTTP/3 handling: connect, frames, events, I/O etc.
-.IP http-proxy
-Involved when transfers are tunneled through a HTTP proxy. "h1-proxy" or
-"h2-proxy" are also involved, depending on the HTTP version negotiated with
-the proxy.
-
-In order to find out all components involved in a transfer, run it with "all"
-configured. You can then see all names involved in your libcurl version in the
-trace.
-
-.SH EXAMPLE
-.nf
- /* log details of HTTP/2 and SSL handling */
- curl_global_trace("http/2,ssl");
-
- /* log all details, except SSL handling */
- curl_global_trace("all,-ssl");
-.fi
-
-Below is a trace sample where "http/2" was configured. The trace output
-of an enabled component appears at the beginning in brackets.
-.nf
-* [HTTP/2] [h2sid=1] cf_send(len=96) submit https://example.com/
-...
-* [HTTP/2] [h2sid=1] FRAME[HEADERS]
-* [HTTP/2] [h2sid=1] 249 header bytes
-...
-.fi
-
-.SH AVAILABILITY
-Added in 8.3
-.SH RETURN VALUE
-If this function returns non-zero, something went wrong and the configuration
-may not have any effects or may only been applied partially.
-.SH "SEE ALSO"
-.BR curl_global_init (3),
-.BR libcurl (3)
diff --git a/docs/libcurl/curl_global_trace.md b/docs/libcurl/curl_global_trace.md
new file mode 100644
index 000000000..c9168352a
--- /dev/null
+++ b/docs/libcurl/curl_global_trace.md
@@ -0,0 +1,124 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_global_trace
+Section: 3
+Source: libcurl
+See-also:
+ - curl_global_init (3)
+ - libcurl (3)
+---
+
+# NAME
+
+curl_global_trace - Global libcurl logging configuration
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_global_trace(const char *config);
+~~~
+
+# DESCRIPTION
+
+This function configures the logging behavior, allowing to make some
+parts of curl more verbose or silent than others.
+
+This function may be called during the initialization phase of a program. It
+does not have to be. It can be called several times even, possibly overwriting
+settings of previous calls.
+
+Calling this function after transfers have been started is undefined. On
+some platforms/architectures it might take effect, on others not.
+
+This function is thread-safe since libcurl 8.3.0 if
+curl_version_info(3) has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms).
+
+If this is not thread-safe, you must not call this function when any other
+thread in the program (i.e. a thread sharing the same memory) is running.
+This does not just mean no other thread that is using libcurl. Because
+curl_global_init(3) may call functions of other libraries that are
+similarly thread unsafe, it could conflict with any other thread that uses
+these other libraries.
+
+If you are initializing libcurl from a Windows DLL you should not initialize
+it from *DllMain* or a static initializer because Windows holds the loader
+lock during that time and it could cause a deadlock.
+
+The *config* string is a list of comma-separated component names. Names
+are case-insensitive and unknown names are ignored. The special name "all"
+applies to all components. Names may be prefixed with '+' or '-' to enable
+or disable detailed logging for a component.
+
+The list of component names is not part of curl's public API. Names may be
+added or disappear in future versions of libcurl. Since unknown names are
+silently ignored, outdated log configurations does not cause errors when
+upgrading libcurl. Given that, some names can be expected to be fairly stable
+and are listed below for easy reference.
+
+Note that log configuration applies only to transfers where debug logging
+is enabled. See CURLOPT_VERBOSE(3) or CURLOPT_DEBUGFUNCTION(3)
+on how to control that.
+
+# TRACE COMPONENTS
+
+## tcp
+
+Tracing of TCP socket handling: connect, reads, writes.
+
+## ssl
+
+Tracing of SSL/TLS operations, whichever SSL backend is used in your build.
+
+## http/2
+
+Details about HTTP/2 handling: frames, events, I/O, etc.
+
+## http/3
+
+Details about HTTP/3 handling: connect, frames, events, I/O etc.
+
+## http-proxy
+
+Involved when transfers are tunneled through an HTTP proxy. "h1-proxy" or
+"h2-proxy" are also involved, depending on the HTTP version negotiated with
+the proxy.
+
+In order to find out all components involved in a transfer, run it with "all"
+configured. You can then see all names involved in your libcurl version in the
+trace.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* log details of HTTP/2 and SSL handling */
+ curl_global_trace("http/2,ssl");
+
+ /* log all details, except SSL handling */
+ curl_global_trace("all,-ssl");
+}
+~~~
+
+Below is a trace sample where "http/2" was configured. The trace output
+of an enabled component appears at the beginning in brackets.
+~~~
+* [HTTP/2] [h2sid=1] cf_send(len=96) submit https://example.com/
+...
+* [HTTP/2] [h2sid=1] FRAME[HEADERS]
+* [HTTP/2] [h2sid=1] 249 header bytes
+...
+~~~
+
+# AVAILABILITY
+
+Added in 8.3
+
+# RETURN VALUE
+
+If this function returns non-zero, something went wrong and the configuration
+may not have any effects or may only been applied partially.
diff --git a/docs/libcurl/curl_mime_addpart.3 b/docs/libcurl/curl_mime_addpart.3
deleted file mode 100644
index 34d365b10..000000000
--- a/docs/libcurl/curl_mime_addpart.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_addpart 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_addpart - append a new empty part to a mime structure
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-curl_mimepart *curl_mime_addpart(curl_mime *mime);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_addpart(3)\fP creates and appends a new empty part to the given
-mime structure and returns a handle to it. The returned part handle can
-subsequently be populated using functions from the mime API.
-
-\fImime\fP is the handle of the mime structure in which the new part must be
-appended.
-.SH EXAMPLE
-.nf
- curl_mime *mime;
- curl_mimepart *part;
-
- /* create a mime handle */
- mime = curl_mime_init(easy);
-
- /* add a part */
- part = curl_mime_addpart(mime);
-
- /* continue and set name + data to the part */
- curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
- curl_mime_name(part, "data");
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-A mime part structure handle, or NULL upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_data (3),
-.BR curl_mime_data_cb (3),
-.BR curl_mime_encoder (3),
-.BR curl_mime_filedata (3),
-.BR curl_mime_filename (3),
-.BR curl_mime_headers (3),
-.BR curl_mime_init (3),
-.BR curl_mime_name (3),
-.BR curl_mime_subparts (3),
-.BR curl_mime_type (3)
diff --git a/docs/libcurl/curl_mime_addpart.md b/docs/libcurl/curl_mime_addpart.md
new file mode 100644
index 000000000..f641abbcf
--- /dev/null
+++ b/docs/libcurl/curl_mime_addpart.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_addpart
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_data (3)
+ - curl_mime_data_cb (3)
+ - curl_mime_encoder (3)
+ - curl_mime_filedata (3)
+ - curl_mime_filename (3)
+ - curl_mime_headers (3)
+ - curl_mime_init (3)
+ - curl_mime_name (3)
+ - curl_mime_subparts (3)
+ - curl_mime_type (3)
+---
+
+# NAME
+
+curl_mime_addpart - append a new empty part to a mime structure
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+curl_mimepart *curl_mime_addpart(curl_mime *mime);
+~~~
+
+# DESCRIPTION
+
+curl_mime_addpart(3) creates and appends a new empty part to the given
+mime structure and returns a handle to it. The returned part handle can
+subsequently be populated using functions from the mime API.
+
+*mime* is the handle of the mime structure in which the new part must be
+appended.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* create a mime handle */
+ mime = curl_mime_init(curl);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* continue and set name + data to the part */
+ curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
+ curl_mime_name(part, "data");
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+A mime part structure handle, or NULL upon failure.
diff --git a/docs/libcurl/curl_mime_data.3 b/docs/libcurl/curl_mime_data.3
deleted file mode 100644
index baeb281b2..000000000
--- a/docs/libcurl/curl_mime_data.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_data 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_data - set a mime part's body data from memory
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_data(curl_mimepart *part, const char *data,
- size_t datasize);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_data(3)\fP sets a mime part's body content from memory data.
-
-\fIpart\fP is the mime part to assign contents to, created with
-\fIcurl_mime_addpart(3)\fP.
-
-\fIdata\fP points to the data that gets copied by this function. The storage
-may safely be reused after the call.
-
-\fIdatasize\fP is the number of bytes \fIdata\fP points to. It can be set to
-\fICURL_ZERO_TERMINATED\fP to indicate \fIdata\fP is a null-terminated
-character string.
-
-Setting a part's contents multiple times is valid: only the value set by the
-last call is retained. It is possible to unassign part's contents by setting
-\fIdata\fP to NULL.
-
-Setting large data is memory consuming: one might consider using
-\fIcurl_mime_data_cb(3)\fP in such a case.
-.SH EXAMPLE
-.nf
- curl_mime *mime;
- curl_mimepart *part;
-
- /* create a mime handle */
- mime = curl_mime_init(easy);
-
- /* add a part */
- part = curl_mime_addpart(mime);
-
- /* add data to the part */
- curl_mime_data(part, "raw contents to send", CURL_ZERO_TERMINATED);
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_data_cb (3),
-.BR curl_mime_name (3),
-.BR curl_mime_type (3)
diff --git a/docs/libcurl/curl_mime_data.md b/docs/libcurl/curl_mime_data.md
new file mode 100644
index 000000000..15a1d2707
--- /dev/null
+++ b/docs/libcurl/curl_mime_data.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_data
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_data_cb (3)
+ - curl_mime_name (3)
+ - curl_mime_type (3)
+---
+
+# NAME
+
+curl_mime_data - set a mime part's body data from memory
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_data(curl_mimepart *part, const char *data,
+ size_t datasize);
+~~~
+
+# DESCRIPTION
+
+curl_mime_data(3) sets a mime part's body content from memory data.
+
+*part* is the mime part to assign contents to, created with
+curl_mime_addpart(3).
+
+*data* points to the data that gets copied by this function. The storage
+may safely be reused after the call.
+
+*datasize* is the number of bytes *data* points to. It can be set to
+*CURL_ZERO_TERMINATED* to indicate *data* is a null-terminated
+character string.
+
+Setting a part's contents multiple times is valid: only the value set by the
+last call is retained. It is possible to unassign part's contents by setting
+*data* to NULL.
+
+Setting large data is memory consuming: one might consider using
+curl_mime_data_cb(3) in such a case.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* create a mime handle */
+ mime = curl_mime_init(curl);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* add data to the part */
+ curl_mime_data(part, "raw contents to send", CURL_ZERO_TERMINATED);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mime_data_cb.3 b/docs/libcurl/curl_mime_data_cb.3
deleted file mode 100644
index 03e6bd86d..000000000
--- a/docs/libcurl/curl_mime_data_cb.3
+++ /dev/null
@@ -1,168 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_data_cb 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_data_cb - set a callback-based data source for a mime part's body
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-size_t readfunc(char *buffer, size_t size, size_t nitems, void *arg);
-
-int seekfunc(void *arg, curl_off_t offset, int origin);
-
-void freefunc(void *arg);
-
-CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
- curl_read_callback readfunc,
- curl_seek_callback seekfunc,
- curl_free_callback freefunc, void *arg);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_data_cb(3)\fP sets the data source of a mime part's body content
-from a data read callback function.
-
-\fIpart\fP is the part's to assign contents to.
-
-\fIreadfunc\fP is a pointer to a data read callback function, with a signature
-as shown by the above prototype. It may not be set to NULL.
-
-\fIseekfunc\fP is a pointer to a seek callback function, with a signature as
-shown by the above prototype. This function is used when resending data (i.e.:
-after a redirect); this pointer may be set to NULL, in which case a resend
-might not be not possible.
-
-\fIfreefunc\fP is a pointer to a user resource freeing callback function, with
-a signature as shown by the above prototype. If no resource is to be freed, it
-may safely be set to NULL. This function is called upon mime structure
-freeing.
-
-\fIarg\fP is a user defined argument to callback functions.
-
-The read callback function gets called by libcurl as soon as it needs to
-read data in order to send it to the peer - like if you ask it to upload or
-post data to the server. The data area pointed at by the pointer \fIbuffer\fP
-should be filled up with at most \fIsize\fP multiplied with \fInitems\fP number
-of bytes by your function.
-
-Your read function must then return the actual number of bytes that it stored
-in that memory area. Returning 0 signals 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 have said you intend to upload N bytes
-and yet you upload less than N bytes), you may experience that the server
-"hangs" waiting for the rest of the data that does not come.
-
-The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current
-operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error
-code from the transfer.
-
-The callback can return \fICURL_READFUNC_PAUSE\fP to cause reading from this
-connection to pause. See \fIcurl_easy_pause(3)\fP for further details.
-
-The seek function gets called by libcurl to rewind input stream data or to
-seek to a certain position. The function shall work like fseek(3) or lseek(3)
-and it gets SEEK_SET, SEEK_CUR or SEEK_END as argument for \fIorigin\fP,
-although libcurl currently only passes SEEK_SET.
-
-The callback function must return \fICURL_SEEKFUNC_OK\fP on success,
-\fICURL_SEEKFUNC_FAIL\fP to cause the upload operation to fail or
-\fICURL_SEEKFUNC_CANTSEEK\fP to indicate that while the seek failed, libcurl
-is free to work around the problem if possible. The latter can sometimes be
-done by instead reading from the input or similar.
-
-Care must be taken if the part is bound to a curl easy handle that is later
-duplicated: the \fIarg\fP pointer argument is also duplicated, resulting in
-the pointed item to be shared between the original and the copied handle. In
-particular, special attention should be given to the \fIfreefunc\fP procedure
-code since it then gets called twice with the same argument.
-.SH EXAMPLE
-Sending a huge data string causes the same amount of memory to be allocated:
-to avoid overhead resources consumption, one might want to use a callback
-source to avoid data duplication. In this case, original data must be retained
-until after the transfer terminates.
-.nf
-
-char hugedata[512000];
-
-struct ctl {
- char *buffer;
- curl_off_t size;
- curl_off_t position;
-};
-
-size_t read_callback(char *buffer, size_t size, size_t nitems, void *arg)
-{
- struct ctl *p = (struct ctl *) arg;
- curl_off_t sz = p->size - p->position;
-
- nitems *= size;
- if(sz > nitems)
- sz = nitems;
- if(sz)
- memcpy(buffer, p->buffer + p->position, sz);
- p->position += sz;
- return sz;
-}
-
-int seek_callback(void *arg, curl_off_t offset, int origin)
-{
- struct ctl *p = (struct ctl *) arg;
-
- switch(origin) {
- case SEEK_END:
- offset += p->size;
- break;
- case SEEK_CUR:
- offset += p->position;
- break;
- }
-
- if(offset < 0)
- return CURL_SEEKFUNC_FAIL;
- p->position = offset;
- return CURL_SEEKFUNC_OK;
-}
-
- CURL *easy = curl_easy_init();
- curl_mime *mime = curl_mime_init(easy);
- curl_mimepart *part = curl_mime_addpart(mime);
- struct ctl hugectl;
-
- hugectl.buffer = hugedata;
- hugectl.size = sizeof hugedata;
- hugectl.position = 0;
- curl_mime_data_cb(part, hugectl.size, read_callback, seek_callback, NULL,
- &hugectl);
-
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_easy_duphandle (3),
-.BR curl_mime_addpart (3),
-.BR curl_mime_data (3),
-.BR curl_mime_name (3)
diff --git a/docs/libcurl/curl_mime_data_cb.md b/docs/libcurl/curl_mime_data_cb.md
new file mode 100644
index 000000000..bd3c77ac5
--- /dev/null
+++ b/docs/libcurl/curl_mime_data_cb.md
@@ -0,0 +1,168 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_data_cb
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_duphandle (3)
+ - curl_mime_addpart (3)
+ - curl_mime_data (3)
+ - curl_mime_name (3)
+---
+
+# NAME
+
+curl_mime_data_cb - set a callback-based data source for a mime part's body
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+size_t readfunc(char *buffer, size_t size, size_t nitems, void *arg);
+
+int seekfunc(void *arg, curl_off_t offset, int origin);
+
+void freefunc(void *arg);
+
+CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
+ curl_read_callback readfunc,
+ curl_seek_callback seekfunc,
+ curl_free_callback freefunc, void *arg);
+~~~
+
+# DESCRIPTION
+
+curl_mime_data_cb(3) sets the data source of a mime part's body content
+from a data read callback function.
+
+*part* is the part's to assign contents to.
+
+*readfunc* is a pointer to a data read callback function, with a signature
+as shown by the above prototype. It may not be set to NULL.
+
+*seekfunc* is a pointer to a seek callback function, with a signature as
+shown by the above prototype. This function is used when resending data (i.e.:
+after a redirect); this pointer may be set to NULL, in which case a resend
+might not be not possible.
+
+*freefunc* is a pointer to a user resource freeing callback function, with
+a signature as shown by the above prototype. If no resource is to be freed, it
+may safely be set to NULL. This function is called upon mime structure
+freeing.
+
+*arg* is a user defined argument to callback functions.
+
+The read callback function gets called by libcurl as soon as it needs to
+read data in order to send it to the peer - like if you ask it to upload or
+post data to the server. The data area pointed at by the pointer *buffer*
+should be filled up with at most *size* multiplied with *nitems* number
+of bytes by your function.
+
+Your read function must then return the actual number of bytes that it stored
+in that memory area. Returning 0 signals 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 have said you intend to upload N bytes
+and yet you upload less than N bytes), you may experience that the server
+"hangs" waiting for the rest of the data that does not come.
+
+The read callback may return *CURL_READFUNC_ABORT* to stop the current
+operation immediately, resulting in a *CURLE_ABORTED_BY_CALLBACK* error
+code from the transfer.
+
+The callback can return *CURL_READFUNC_PAUSE* to cause reading from this
+connection to pause. See curl_easy_pause(3) for further details.
+
+The seek function gets called by libcurl to rewind input stream data or to
+seek to a certain position. The function shall work like fseek(3) or lseek(3)
+and it gets SEEK_SET, SEEK_CUR or SEEK_END as argument for *origin*,
+although libcurl currently only passes SEEK_SET.
+
+The callback function must return *CURL_SEEKFUNC_OK* on success,
+*CURL_SEEKFUNC_FAIL* to cause the upload operation to fail or
+*CURL_SEEKFUNC_CANTSEEK* to indicate that while the seek failed, libcurl
+is free to work around the problem if possible. The latter can sometimes be
+done by instead reading from the input or similar.
+
+Care must be taken if the part is bound to a curl easy handle that is later
+duplicated: the *arg* pointer argument is also duplicated, resulting in
+the pointed item to be shared between the original and the copied handle. In
+particular, special attention should be given to the *freefunc* procedure
+code since it then gets called twice with the same argument.
+
+# EXAMPLE
+
+Sending a huge data string causes the same amount of memory to be allocated:
+to avoid overhead resources consumption, one might want to use a callback
+source to avoid data duplication. In this case, original data must be retained
+until after the transfer terminates.
+~~~c
+#include <string.h> /* for memcpy */
+char hugedata[512000];
+
+struct ctl {
+ char *buffer;
+ curl_off_t size;
+ curl_off_t position;
+};
+
+size_t read_callback(char *buffer, size_t size, size_t nitems, void *arg)
+{
+ struct ctl *p = (struct ctl *) arg;
+ curl_off_t sz = p->size - p->position;
+
+ nitems *= size;
+ if(sz > nitems)
+ sz = nitems;
+ if(sz)
+ memcpy(buffer, p->buffer + p->position, sz);
+ p->position += sz;
+ return sz;
+}
+
+int seek_callback(void *arg, curl_off_t offset, int origin)
+{
+ struct ctl *p = (struct ctl *) arg;
+
+ switch(origin) {
+ case SEEK_END:
+ offset += p->size;
+ break;
+ case SEEK_CUR:
+ offset += p->position;
+ break;
+ }
+
+ if(offset < 0)
+ return CURL_SEEKFUNC_FAIL;
+ p->position = offset;
+ return CURL_SEEKFUNC_OK;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_mime *mime = curl_mime_init(curl);
+ curl_mimepart *part = curl_mime_addpart(mime);
+ struct ctl hugectl;
+
+ hugectl.buffer = hugedata;
+ hugectl.size = sizeof(hugedata);
+ hugectl.position = 0;
+ curl_mime_data_cb(part, hugectl.size, read_callback, seek_callback, NULL,
+ &hugectl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mime_encoder.3 b/docs/libcurl/curl_mime_encoder.3
deleted file mode 100644
index 7e61d93d2..000000000
--- a/docs/libcurl/curl_mime_encoder.3
+++ /dev/null
@@ -1,99 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_encoder 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_encoder - set a mime part's encoder and content transfer encoding
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding);
-.fi
-.SH DESCRIPTION
-curl_mime_encoder() requests a mime part's content to be encoded before being
-transmitted.
-
-\fIpart\fP is the part's handle to assign an encoder.
-\fIencoding\fP is a pointer to a 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.
-
-Setting a part's encoder multiple times is valid: only the value set by the
-last call is retained.
-
-Upon multipart rendering, the part's content is encoded according to the
-pertaining scheme and a corresponding \fI"Content-Transfer-Encoding"\fP header
-is added to the part.
-
-Supported encoding schemes are:
-.br
-"\fIbinary\fP": the data is left unchanged, the header is added.
-.br
-"\fI8bit\fP": header added, no data change.
-.br
-"\fI7bit\fP": the data is unchanged, but is each byte is checked
-to be a 7-bit value; if not, a read error occurs.
-.br
-"\fIbase64\fP": Data is converted to base64 encoding, then split in
-CRLF-terminated lines of at most 76 characters.
-.br
-"\fIquoted-printable\fP": data is encoded in quoted printable lines of
-at most 76 characters. Since the resulting size of the final data cannot be
-determined prior to reading the original data, it is left as unknown, causing
-chunked transfer in HTTP. For the same reason, this encoder may not be used
-with IMAP. This encoder targets text data that is mostly ASCII and should
-not be used with other types of data.
-
-If the original data is already encoded in such a scheme, a custom
-\fIContent-Transfer-Encoding\fP header should be added with
-\fIcurl_mime_headers(3)\fP instead of setting a part encoder.
-
-Encoding should not be applied to multiparts, thus the use of this function on
-a part with content set with \fIcurl_mime_subparts(3)\fP is strongly
-discouraged.
-.SH EXAMPLE
-.nf
- curl_mime *mime;
- curl_mimepart *part;
-
- /* create a mime handle */
- mime = curl_mime_init(easy);
-
- /* add a part */
- part = curl_mime_addpart(mime);
-
- /* send a file */
- curl_mime_filedata(part, "image.png");
-
- /* encode file data in base64 for transfer */
- curl_mime_encoder(part, "base64");
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_headers (3),
-.BR curl_mime_subparts (3)
diff --git a/docs/libcurl/curl_mime_encoder.md b/docs/libcurl/curl_mime_encoder.md
new file mode 100644
index 000000000..85dc3ac11
--- /dev/null
+++ b/docs/libcurl/curl_mime_encoder.md
@@ -0,0 +1,100 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_encoder
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_headers (3)
+ - curl_mime_subparts (3)
+---
+
+# NAME
+
+curl_mime_encoder - set a mime part's encoder and content transfer encoding
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding);
+~~~
+
+# DESCRIPTION
+
+curl_mime_encoder() requests a mime part's content to be encoded before being
+transmitted.
+
+*part* is the part's handle to assign an encoder.
+*encoding* 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.
+
+Setting a part's encoder multiple times is valid: only the value set by the
+last call is retained.
+
+Upon multipart rendering, the part's content is encoded according to the
+pertaining scheme and a corresponding *"Content-Transfer-Encoding"* header
+is added to the part.
+
+Supported encoding schemes are:
+
+"*binary*": the data is left unchanged, the header is added.
+
+"*8bit*": header added, no data change.
+
+"*7bit*": the data is unchanged, but is each byte is checked
+to be a 7-bit value; if not, a read error occurs.
+
+"*base64*": Data is converted to base64 encoding, then split in
+CRLF-terminated lines of at most 76 characters.
+
+"*quoted-printable*": data is encoded in quoted printable lines of
+at most 76 characters. Since the resulting size of the final data cannot be
+determined prior to reading the original data, it is left as unknown, causing
+chunked transfer in HTTP. For the same reason, this encoder may not be used
+with IMAP. This encoder targets text data that is mostly ASCII and should
+not be used with other types of data.
+
+If the original data is already encoded in such a scheme, a custom
+*Content-Transfer-Encoding* header should be added with
+curl_mime_headers(3) instead of setting a part encoder.
+
+Encoding should not be applied to multiparts, thus the use of this function on
+a part with content set with curl_mime_subparts(3) is strongly
+discouraged.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* create a mime handle */
+ mime = curl_mime_init(curl);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send a file */
+ curl_mime_filedata(part, "image.png");
+
+ /* encode file data in base64 for transfer */
+ curl_mime_encoder(part, "base64");
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mime_filedata.3 b/docs/libcurl/curl_mime_filedata.3
deleted file mode 100644
index 085ebbf0c..000000000
--- a/docs/libcurl/curl_mime_filedata.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_filedata 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_filedata - set a mime part's body data from a file contents
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_filedata(curl_mimepart *part,
- const char *filename);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_filedata(3)\fP sets a mime part's body content from the named
-file's contents. This is an alternative to \fIcurl_mime_data(3)\fP for setting
-data to a mime part.
-
-\fIpart\fP is the part's to assign contents to.
-
-\fIfilename\fP points to the 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
-overridden by a subsequent call to \fIcurl_mime_filename(3)\fP.
-
-The contents of the file is read during the file transfer in a streaming
-manner to allow huge files to get transferred without using much memory. It
-therefore requires that the file is kept intact during the entire request.
-
-If the file size cannot be determined before actually reading it (such as for
-a character device or named pipe), the whole mime structure containing the
-part is transferred using chunks by HTTP but is rejected by IMAP.
-
-Setting a part's contents multiple times is valid: only the value set by the
-last call is retained.
-.SH EXAMPLE
-.nf
- curl_mime *mime;
- curl_mimepart *part;
-
- /* create a mime handle */
- mime = curl_mime_init(easy);
-
- /* add a part */
- part = curl_mime_addpart(mime);
-
- /* send data from this file */
- curl_mime_filedata(part, "image.png");
-
- /* set name */
- curl_mime_name(part, "data");
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure. CURLE_READ_ERROR is only an
-indication that the file is not yet readable: it can be safely ignored at
-this time, but the file must be made readable before the pertaining
-easy handle is performed.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_data (3),
-.BR curl_mime_filename (3),
-.BR curl_mime_name (3)
diff --git a/docs/libcurl/curl_mime_filedata.md b/docs/libcurl/curl_mime_filedata.md
new file mode 100644
index 000000000..07704120e
--- /dev/null
+++ b/docs/libcurl/curl_mime_filedata.md
@@ -0,0 +1,88 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_filedata
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_data (3)
+ - curl_mime_filename (3)
+ - curl_mime_name (3)
+---
+
+# NAME
+
+curl_mime_filedata - set a mime part's body data from a file contents
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_filedata(curl_mimepart *part,
+ const char *filename);
+~~~
+
+# DESCRIPTION
+
+curl_mime_filedata(3) sets a mime part's body content from the named
+file's contents. This is an alternative to curl_mime_data(3) for setting
+data to a mime part.
+
+*part* is the part's to assign contents to.
+
+*filename* 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 filename is set to the base name of the
+given *filename* if it is a valid named file. This can be undone or
+overridden by a subsequent call to curl_mime_filename(3).
+
+The contents of the file is read during the file transfer in a streaming
+manner to allow huge files to get transferred without using much memory. It
+therefore requires that the file is kept intact during the entire request.
+
+If the file size cannot be determined before actually reading it (such as for
+a character device or named pipe), the whole mime structure containing the
+part is transferred using chunks by HTTP but is rejected by IMAP.
+
+Setting a part's contents multiple times is valid: only the value set by the
+last call is retained.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* create a mime handle */
+ mime = curl_mime_init(curl);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send data from this file */
+ curl_mime_filedata(part, "image.png");
+
+ /* set name */
+ curl_mime_name(part, "data");
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure. CURLE_READ_ERROR is only an
+indication that the file is not yet readable: it can be safely ignored at
+this time, but the file must be made readable before the pertaining
+easy handle is performed.
diff --git a/docs/libcurl/curl_mime_filename.3 b/docs/libcurl/curl_mime_filename.3
deleted file mode 100644
index 1241dfb77..000000000
--- a/docs/libcurl/curl_mime_filename.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_filename 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_filename - set a mime part's remote file name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_filename(curl_mimepart *part,
- const char *filename);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_filename(3)\fP sets a mime part's remote file name. When remote
-file name is set, content data is processed as a file, whatever is the part's
-content source. A part's remote file name is transmitted to the server in the
-associated Content-Disposition generated header.
-
-\fIpart\fP is the part's handle to assign the remote file name to.
-
-\fIfilename\fP points to the 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
-name multiple times is valid: only the value set by the last call is retained.
-.SH EXAMPLE
-.nf
- curl_mime *mime;
- curl_mimepart *part;
-
- /* create a mime handle */
- mime = curl_mime_init(easy);
-
- /* add a part */
- part = curl_mime_addpart(mime);
-
- /* send image data from memory */
- curl_mime_data(part, imagebuf, imagebuf_len);
-
- /* set a file name to make it look like a file upload */
- curl_mime_filename(part, "image.png");
-
- /* set name */
- curl_mime_name(part, "data");
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_data (3),
-.BR curl_mime_filedata (3)
diff --git a/docs/libcurl/curl_mime_filename.md b/docs/libcurl/curl_mime_filename.md
new file mode 100644
index 000000000..4fb6b0d51
--- /dev/null
+++ b/docs/libcurl/curl_mime_filename.md
@@ -0,0 +1,79 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_filename
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_data (3)
+ - curl_mime_filedata (3)
+---
+
+# NAME
+
+curl_mime_filename - set a mime part's remote file name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_filename(curl_mimepart *part,
+ const char *filename);
+~~~
+
+# DESCRIPTION
+
+curl_mime_filename(3) sets a mime part's remote filename. When remote
+filename is set, content data is processed as a file, whatever is the part's
+content source. A part's remote filename is transmitted to the server in the
+associated Content-Disposition generated header.
+
+*part* is the part's handle to assign the remote filename to.
+
+*filename* points to the null-terminated filename string; it may be set
+to NULL to remove a previously attached remote filename.
+
+The remote filename string is copied into the part, thus the associated
+storage may safely be released or reused after call. Setting a part's file
+name multiple times is valid: only the value set by the last call is retained.
+
+# EXAMPLE
+
+~~~c
+
+static char imagebuf[]="imagedata";
+
+int main(void)
+{
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* create a mime handle */
+ mime = curl_mime_init(curl);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send image data from memory */
+ curl_mime_data(part, imagebuf, sizeof(imagebuf));
+
+ /* set a file name to make it look like a file upload */
+ curl_mime_filename(part, "image.png");
+
+ /* set name */
+ curl_mime_name(part, "data");
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mime_free.3 b/docs/libcurl/curl_mime_free.3
deleted file mode 100644
index 8d4d32862..000000000
--- a/docs/libcurl/curl_mime_free.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_free 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_free - free a previously built mime structure
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_mime_free(curl_mime *mime);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_free(3)\fP is used to clean up data previously built/appended
-with \fIcurl_mime_addpart(3)\fP and other mime-handling functions. This must
-be called when the data has been used, which typically means after
-\fIcurl_easy_perform(3)\fP has been called.
-
-The handle to free is the one you passed to the \fICURLOPT_MIMEPOST(3)\fP
-option: attached sub part mime structures must not be explicitly freed as they
-are by the top structure freeing.
-
-\fBmime\fP is the handle as returned from a previous call to
-\fIcurl_mime_init(3)\fP and may be NULL.
-
-Passing in a NULL pointer in \fImime\fP makes this function return immediately
-with no action.
-.SH EXAMPLE
-.nf
- /* Build the mime message. */
- mime = curl_mime_init(curl);
-
- /* ... */
-
- /* Free multipart message. */
- curl_mime_free(mime);
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-None
-.SH "SEE ALSO"
-.BR curl_free (3),
-.BR curl_mime_init (3)
diff --git a/docs/libcurl/curl_mime_free.md b/docs/libcurl/curl_mime_free.md
new file mode 100644
index 000000000..5aa5b6aa1
--- /dev/null
+++ b/docs/libcurl/curl_mime_free.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_free
+Section: 3
+Source: libcurl
+See-also:
+ - curl_free (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+curl_mime_free - free a previously built mime structure
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_mime_free(curl_mime *mime);
+~~~
+
+# DESCRIPTION
+
+curl_mime_free(3) is used to clean up data previously built/appended
+with curl_mime_addpart(3) and other mime-handling functions. This must
+be called when the data has been used, which typically means after
+curl_easy_perform(3) has been called.
+
+The handle to free is the one you passed to the CURLOPT_MIMEPOST(3)
+option: attached sub part mime structures must not be explicitly freed as they
+are by the top structure freeing.
+
+**mime** is the handle as returned from a previous call to
+curl_mime_init(3) and may be NULL.
+
+Passing in a NULL pointer in *mime* makes this function return immediately
+with no action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* Build the mime message. */
+ curl_mime *mime = curl_mime_init(curl);
+
+ /* send off the transfer */
+
+ /* Free multipart message. */
+ curl_mime_free(mime);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+None
diff --git a/docs/libcurl/curl_mime_headers.3 b/docs/libcurl/curl_mime_headers.3
deleted file mode 100644
index e25ebef87..000000000
--- a/docs/libcurl/curl_mime_headers.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_headers 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_headers - set a mime part's custom headers
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_headers(curl_mimepart *part,
- struct curl_slist *headers, int take_ownership);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_headers(3)\fP sets a mime part's custom headers.
-
-\fIpart\fP is the part's handle to assign the custom headers list to.
-
-\fIheaders\fP is the head of a list of custom headers; it may be set to NULL
-to remove a previously attached custom header list.
-
-\fItake_ownership\fP: when non-zero, causes the list to be freed upon
-replacement or mime structure deletion; in this case the list must not be
-freed explicitly.
-
-Setting a part's custom headers list multiple times is valid: only the value
-set by the last call is retained.
-.SH EXAMPLE
-.nf
- struct curl_slist *headers = NULL;
-
- headers = curl_slist_append(headers, "Custom-Header: mooo");
-
- /* use these headers, please take ownership */
- curl_mime_headers(part, headers, TRUE);
-
- /* pass on this data */
- curl_mime_data(part, "12345679", CURL_ZERO_TERMINATED);
-
- /* set name */
- curl_mime_name(part, "numbers");
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_name (3)
-
diff --git a/docs/libcurl/curl_mime_headers.md b/docs/libcurl/curl_mime_headers.md
new file mode 100644
index 000000000..4f6421abd
--- /dev/null
+++ b/docs/libcurl/curl_mime_headers.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_headers
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_name (3)
+---
+
+# NAME
+
+curl_mime_headers - set a mime part's custom headers
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_headers(curl_mimepart *part,
+ struct curl_slist *headers, int take_ownership);
+~~~
+
+# DESCRIPTION
+
+curl_mime_headers(3) sets a mime part's custom headers.
+
+*part* is the part's handle to assign the custom headers list to.
+
+*headers* is the head of a list of custom headers; it may be set to NULL
+to remove a previously attached custom header list.
+
+*take_ownership*: when non-zero, causes the list to be freed upon
+replacement or mime structure deletion; in this case the list must not be
+freed explicitly.
+
+Setting a part's custom headers list multiple times is valid: only the value
+set by the last call is retained.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct curl_slist *headers = NULL;
+ CURL *easy = curl_easy_init();
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ headers = curl_slist_append(headers, "Custom-Header: mooo");
+
+ mime = curl_mime_init(easy);
+ part = curl_mime_addpart(mime);
+
+ /* use these headers in the part, takes ownership */
+ curl_mime_headers(part, headers, 1);
+
+ /* pass on this data */
+ curl_mime_data(part, "12345679", CURL_ZERO_TERMINATED);
+
+ /* set name */
+ curl_mime_name(part, "numbers");
+
+ /* Post and send it. */
+ curl_easy_setopt(easy, CURLOPT_MIMEPOST, mime);
+ curl_easy_setopt(easy, CURLOPT_URL, "https://example.com");
+ curl_easy_perform(easy);
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mime_init.3 b/docs/libcurl/curl_mime_init.3
deleted file mode 100644
index b48de436f..000000000
--- a/docs/libcurl/curl_mime_init.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_init 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_init - create a mime handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-curl_mime *curl_mime_init(CURL *easy_handle);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_init(3)\fP creates a handle to a new empty mime structure.
-This mime structure can be subsequently filled using the mime API, then
-attached to some easy handle using option \fICURLOPT_MIMEPOST(3)\fP within
-a \fIcurl_easy_setopt(3)\fP call or added as a multipart in another mime
-handle's part using \fIcurl_mime_subparts(3)\fP.
-
-\fIeasy_handle\fP is used for part separator randomization and error
-reporting. Since 7.87.0, it does not need to be the final target handle.
-
-Using a mime handle is the recommended way to post an HTTP form, format and
-send a multi-part email with SMTP or upload such an email to an IMAP server.
-.SH EXAMPLE
-.nf
- CURL *easy = curl_easy_init();
- curl_mime *mime;
- curl_mimepart *part;
-
- /* Build an HTTP form with a single field named "data", */
- mime = curl_mime_init(easy);
- part = curl_mime_addpart(mime);
- curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
- curl_mime_name(part, "data");
-
- /* Post and send it. */
- curl_easy_setopt(easy, CURLOPT_MIMEPOST, mime);
- curl_easy_setopt(easy, CURLOPT_URL, "https://example.com");
- curl_easy_perform(easy);
-
- /* Clean-up. */
- curl_easy_cleanup(easy);
- curl_mime_free(mime);
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-A mime struct handle, or NULL upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_free (3),
-.BR curl_mime_subparts (3),
-.BR CURLOPT_MIMEPOST (3)
diff --git a/docs/libcurl/curl_mime_init.md b/docs/libcurl/curl_mime_init.md
new file mode 100644
index 000000000..0811bb3d8
--- /dev/null
+++ b/docs/libcurl/curl_mime_init.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_init
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MIMEPOST (3)
+ - curl_mime_addpart (3)
+ - curl_mime_free (3)
+ - curl_mime_subparts (3)
+---
+
+# NAME
+
+curl_mime_init - create a mime handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+curl_mime *curl_mime_init(CURL *easy_handle);
+~~~
+
+# DESCRIPTION
+
+curl_mime_init(3) creates a handle to a new empty mime structure.
+This mime structure can be subsequently filled using the mime API, then
+attached to some easy handle using option CURLOPT_MIMEPOST(3) within
+a curl_easy_setopt(3) call or added as a multipart in another mime
+handle's part using curl_mime_subparts(3).
+
+*easy_handle* is used for part separator randomization and error
+reporting. Since 7.87.0, it does not need to be the final target handle.
+
+Using a mime handle is the recommended way to post an HTTP form, format and
+send a multi-part email with SMTP or upload such an email to an IMAP server.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *easy = curl_easy_init();
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* Build an HTTP form with a single field named "data", */
+ mime = curl_mime_init(easy);
+ part = curl_mime_addpart(mime);
+ curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
+ curl_mime_name(part, "data");
+
+ /* Post and send it. */
+ curl_easy_setopt(easy, CURLOPT_MIMEPOST, mime);
+ curl_easy_setopt(easy, CURLOPT_URL, "https://example.com");
+ curl_easy_perform(easy);
+
+ /* Clean-up. */
+ curl_easy_cleanup(easy);
+ curl_mime_free(mime);
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+A mime struct handle, or NULL upon failure.
diff --git a/docs/libcurl/curl_mime_name.3 b/docs/libcurl/curl_mime_name.3
deleted file mode 100644
index a4ddeb83a..000000000
--- a/docs/libcurl/curl_mime_name.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_name 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_name - set a mime part's name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_name(curl_mimepart *part, const char *name);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_name(3)\fP sets a mime part's name. This is the way HTTP form
-fields are named.
-
-\fIpart\fP is the part's handle to assign a name to.
-
-\fIname\fP points to the 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 multiple times
-is valid: only the value set by the last call is retained. It is possible to
-reset the name of a part by setting \fIname\fP to NULL.
-.SH EXAMPLE
-.nf
- curl_mime *mime;
- curl_mimepart *part;
-
- /* create a mime handle */
- mime = curl_mime_init(easy);
-
- /* add a part */
- part = curl_mime_addpart(mime);
-
- /* give the part a name */
- curl_mime_name(part, "shoe_size");
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_data (3),
-.BR curl_mime_type (3)
diff --git a/docs/libcurl/curl_mime_name.md b/docs/libcurl/curl_mime_name.md
new file mode 100644
index 000000000..bd2503397
--- /dev/null
+++ b/docs/libcurl/curl_mime_name.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_name
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_data (3)
+ - curl_mime_type (3)
+---
+
+# NAME
+
+curl_mime_name - set a mime part's name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_name(curl_mimepart *part, const char *name);
+~~~
+
+# DESCRIPTION
+
+curl_mime_name(3) sets a mime part's name. This is the way HTTP form
+fields are named.
+
+*part* is the part's handle to assign a name to.
+
+*name* 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 multiple times
+is valid: only the value set by the last call is retained. It is possible to
+reset the name of a part by setting *name* to NULL.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* create a mime handle */
+ mime = curl_mime_init(curl);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* give the part a name */
+ curl_mime_name(part, "shoe_size");
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mime_subparts.3 b/docs/libcurl/curl_mime_subparts.3
deleted file mode 100644
index 45bc62c86..000000000
--- a/docs/libcurl/curl_mime_subparts.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_subparts 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_subparts - set sub-parts of a multipart mime part
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_subparts(3)\fP sets a multipart mime part's content from a mime
-structure.
-
-\fIpart\fP is a handle to the multipart part.
-
-\fIsubparts\fP is a mime structure handle holding the sub-parts. After
-\fIcurl_mime_subparts(3)\fP succeeds, the mime structure handle belongs to the
-multipart part and must not be freed explicitly. It may however be updated by
-subsequent calls to mime API functions.
-
-Setting a part's contents multiple times is valid: only the value set by the
-last call is retained. It is possible to unassign previous part's contents by
-setting \fIsubparts\fP to NULL.
-.SH EXAMPLE
-.nf
- /* The inline part is an alternative proposing the html and the text
- versions of the email. */
- alt = curl_mime_init(curl);
-
- /* HTML message. */
- part = curl_mime_addpart(alt);
- curl_mime_data(part, inline_html, CURL_ZERO_TERMINATED);
- curl_mime_type(part, "text/html");
-
- /* Text message. */
- part = curl_mime_addpart(alt);
- curl_mime_data(part, inline_text, CURL_ZERO_TERMINATED);
-
- /* Create the inline part. */
- part = curl_mime_addpart(mime);
- curl_mime_subparts(part, alt);
- curl_mime_type(part, "multipart/alternative");
- slist = curl_slist_append(NULL, "Content-Disposition: inline");
- curl_mime_headers(part, slist, 1);
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_init (3)
diff --git a/docs/libcurl/curl_mime_subparts.md b/docs/libcurl/curl_mime_subparts.md
new file mode 100644
index 000000000..4136a1b2a
--- /dev/null
+++ b/docs/libcurl/curl_mime_subparts.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_subparts
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+curl_mime_subparts - set sub-parts of a multipart mime part
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts);
+~~~
+
+# DESCRIPTION
+
+curl_mime_subparts(3) sets a multipart mime part's content from a mime
+structure.
+
+*part* is a handle to the multipart part.
+
+*subparts* is a mime structure handle holding the sub-parts. After
+curl_mime_subparts(3) succeeds, the mime structure handle belongs to the
+multipart part and must not be freed explicitly. It may however be updated by
+subsequent calls to mime API functions.
+
+Setting a part's contents multiple times is valid: only the value set by the
+last call is retained. It is possible to unassign previous part's contents by
+setting *subparts* to NULL.
+
+# EXAMPLE
+
+~~~c
+
+static char *inline_html = "<title>example</title>";
+static char *inline_text = "once upon the time";
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct curl_slist *slist;
+
+ /* The inline part is an alternative proposing the html and the text
+ versions of the email. */
+ curl_mime *alt = curl_mime_init(curl);
+ curl_mimepart *part;
+
+ /* HTML message. */
+ part = curl_mime_addpart(alt);
+ curl_mime_data(part, inline_html, CURL_ZERO_TERMINATED);
+ curl_mime_type(part, "text/html");
+
+ /* Text message. */
+ part = curl_mime_addpart(alt);
+ curl_mime_data(part, inline_text, CURL_ZERO_TERMINATED);
+
+ /* Create the inline part. */
+ part = curl_mime_addpart(alt);
+ curl_mime_subparts(part, alt);
+ curl_mime_type(part, "multipart/alternative");
+ slist = curl_slist_append(NULL, "Content-Disposition: inline");
+ curl_mime_headers(part, slist, 1);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mime_type.3 b/docs/libcurl/curl_mime_type.3
deleted file mode 100644
index 74d7d9416..000000000
--- a/docs/libcurl/curl_mime_type.3
+++ /dev/null
@@ -1,85 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_mime_type 3 "22 August 2017" "libcurl" "libcurl"
-.SH NAME
-curl_mime_type - set a mime part's content type
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
-.fi
-.SH DESCRIPTION
-\fIcurl_mime_type(3)\fP sets a mime part's content type.
-
-\fIpart\fP is the part's handle to assign the content type to.
-
-\fImimetype\fP points to the 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
-safely be released or reused after call. Setting a part's type multiple times
-is valid: only the value set by the last call is retained.
-
-In the absence of a mime type and if needed by the protocol specifications,
-a default mime type is determined by the context:
-.br
-- If set as a custom header, use this value.
-.br
-- application/form-data for an HTTP form post.
-.br
-- If a remote file name is set, the mime type is taken from the file name
-extension, or application/octet-stream by default.
-.br
-- For a multipart part, multipart/mixed.
-.br
-- text/plain in other cases.
-.SH EXAMPLE
-.nf
- curl_mime *mime;
- curl_mimepart *part;
-
- /* create a mime handle */
- mime = curl_mime_init(easy);
-
- /* add a part */
- part = curl_mime_addpart(mime);
-
- /* get data from this file */
- curl_mime_filedata(part, "image.png");
-
- /* content-type for this part */
- curl_mime_type(part, "image/png");
-
- /* set name */
- curl_mime_name(part, "image");
-.fi
-.SH AVAILABILITY
-As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
-.SH RETURN VALUE
-CURLE_OK or a CURL error code upon failure.
-.SH "SEE ALSO"
-.BR curl_mime_addpart (3),
-.BR curl_mime_data (3),
-.BR curl_mime_name (3)
diff --git a/docs/libcurl/curl_mime_type.md b/docs/libcurl/curl_mime_type.md
new file mode 100644
index 000000000..3970ad88e
--- /dev/null
+++ b/docs/libcurl/curl_mime_type.md
@@ -0,0 +1,86 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_mime_type
+Section: 3
+Source: libcurl
+See-also:
+ - curl_mime_addpart (3)
+ - curl_mime_data (3)
+ - curl_mime_name (3)
+---
+
+# NAME
+
+curl_mime_type - set a mime part's content type
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
+~~~
+
+# DESCRIPTION
+
+curl_mime_type(3) sets a mime part's content type.
+
+*part* is the part's handle to assign the content type to.
+
+*mimetype* 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
+safely be released or reused after call. Setting a part's type multiple times
+is valid: only the value set by the last call is retained.
+
+In the absence of a mime type and if needed by the protocol specifications,
+a default mime type is determined by the context:
+
+- If set as a custom header, use this value.
+
+- application/form-data for an HTTP form post.
+
+- If a remote filename is set, the mime type is taken from the file name
+extension, or application/octet-stream by default.
+
+- For a multipart part, multipart/mixed.
+
+- text/plain in other cases.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* create a mime handle */
+ mime = curl_mime_init(curl);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* get data from this file */
+ curl_mime_filedata(part, "image.png");
+
+ /* content-type for this part */
+ curl_mime_type(part, "image/png");
+
+ /* set name */
+ curl_mime_name(part, "image");
+}
+}
+~~~
+
+# AVAILABILITY
+
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+
+# RETURN VALUE
+
+CURLE_OK or a CURL error code upon failure.
diff --git a/docs/libcurl/curl_mprintf.3 b/docs/libcurl/curl_mprintf.3
deleted file mode 100644
index c7e0a35dd..000000000
--- a/docs/libcurl/curl_mprintf.3
+++ /dev/null
@@ -1,254 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_printf 3 "30 April 2004" "libcurl" "libcurl"
-.SH NAME
-curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
-curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
-curl_mvsprintf - formatted output conversion
-.SH SYNOPSIS
-.nf
-#include <curl/mprintf.h>
-
-int curl_mprintf(const char *format, ...);
-int curl_mfprintf(FILE *fd, const char *format, ...);
-int curl_msprintf(char *buffer, const char *format, ...);
-int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...);
-int curl_mvprintf(const char *format, va_list args);
-int curl_mvfprintf(FILE *fd, const char *format, va_list args);
-int curl_mvsprintf(char *buffer, const char *format, va_list args);
-int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
- va_list args);
-char *curl_maprintf(const char *format , ...);
-char *curl_mvaprintf(const char *format, va_list args);
-.fi
-.SH DESCRIPTION
-These functions produce output according to the format string and given
-arguments. They are mostly clones of the well-known C-style functions but
-there are slight differences in behavior.
-
-We discourage users from using any of these functions in new applications.
-
-Functions in the curl_mprintf() family produce output according to a format as
-described below. The functions \fBcurl_mprintf()\fP and \fBcurl_mvprintf()\fP
-write output to stdout, the standard output stream; \fBcurl_mfprintf()\fP and
-\fBcurl_mvfprintf()\fP write output to the given output stream;
-\fBcurl_msprintf()\fP, \fBcurl_msnprintf()\fP, \fBcurl_mvsprintf()\fP, and
-\fBcurl_mvsnprintf()\fP write to the character string \fBbuffer\fP.
-
-The functions \fBcurl_msnprintf()\fP and \fBcurl_mvsnprintf()\fP write at most
-\fImaxlength\fP bytes (including the terminating null byte ('\\0')) to
-\fIbuffer\fP.
-
-The functions \fBcurl_mvprintf()\fP, \fBcurl_mvfprintf()\fP,
-\fBcurl_mvsprintf()\fP, \fBcurl_mvsnprintf()\fP are equivalent to the
-functions \fBcurl_mprintf()\fP, \fBcurl_mfprintf()\fP, \fBcurl_msprintf()\fP,
-\fBcurl_msnprintf()\fP, respectively, except that they are called with a
-\fIva_list\fP instead of a variable number of arguments. These functions do
-not call the \fIva_end\fP macro. Because they invoke the \fIva_arg\fP macro,
-the value of \fIap\fP is undefined after the call.
-
-The functions \fBcurl_maprintf()\fP and \fBcurl_mvaprintf()\fP return the
-output string as pointer to a newly allocated memory area. The returned string
-must be \fIcurl_free(3)\fPed by the receiver.
-
-All of these functions write the output under the control of a format string
-that specifies how subsequent arguments are converted for output.
-
-.SH FORMAT STRING
-The format string is composed of zero or more directives: ordinary characters
-(not %), which are copied unchanged to the output stream; and conversion
-specifications, each of which results in fetching zero or more subsequent
-arguments. Each conversion specification is introduced by the character %, and
-ends with a conversion specifier. In between there may be (in this order) zero
-or more \fIflags\fP, an optional minimum \fIfield width\fP, an optional
-\fIprecision\fP and an optional \fIlength modifier\fP.
-
-.SH "The $ modifier"
-The arguments must correspond properly with the conversion specifier. By
-default, the arguments are used in the order given, where each '*' (see Field
-width and Precision below) and each conversion specifier asks for the next
-argument (and it is an error if insufficiently many arguments are given). One
-can also specify explicitly which argument is taken, at each place where an
-argument is required, by writing "%m$" instead of '%' and "*m$" instead
-of '*', where the decimal integer m denotes the position in the argument list
-of the desired argument, indexed starting from 1. Thus,
-.nf
- curl_mprintf("%*d", width, num);
-.fi
-and
-.nf
- curl_mprintf("%2$*1$d", width, num);
-.fi
-are equivalent. The second style allows repeated references to the same
-argument.
-
-If the style using '$' is used, it must be used throughout for all conversions
-taking an argument and all width and precision arguments, but it may be mixed
-with "%%" formats, which do not consume an argument. There may be no gaps in
-the numbers of arguments specified using '$'; for example, if arguments 1 and
-3 are specified, argument 2 must also be specified somewhere in the format
-string.
-
-.SH "Flag characters"
-The character % is followed by zero or more of the following flags:
-.TP
-.B #
-The value should be converted to its "alternate form".
-.TP
-.B 0
-The value should be zero padded.
-.TP
-.B -
-The converted value is to be left adjusted on the field boundary. (The
-default is right justification.) The converted value is padded on the right
-with blanks, rather than on the left with blanks or zeros. A '-' overrides a
-\&'0' if both are given.
-.TP
-.B ' '
-(a space) A blank should be left before a positive number (or empty string)
-produced by a signed conversion.
-.TP
-.B +
-A sign (+ or -) should always be placed before a number produced by a signed
-conversion. By default, a sign is used only for negative numbers. A '+'
-overrides a space if both are used.
-.SH "Field width"
-An optional decimal digit string (with nonzero first digit) specifying a
-minimum field width. If the converted value has fewer characters than the
-field width, it gets padded with spaces on the left (or right, if the
-left-adjustment flag has been given). Instead of a decimal digit string one
-may write "*" or "*m$" (for some decimal integer m) to specify that the field
-width is given in the next argument, or in the \fIm-th\fP argument,
-respectively, which must be of type int. A negative field width is taken as
-a '-' flag followed by a positive field width. In no case does a nonexistent
-or small field width cause truncation of a field; if the result of a
-conversion is wider than the field width, the field is expanded to contain the
-conversion result.
-.SH "Precision"
-An optional precision in the form of a period ('.') followed by an optional
-decimal digit string. Instead of a decimal digit string one may write "*" or
-"*m$" (for some decimal integer m) to specify that the precision is given in
-the next argument, or in the \fIm-th\fP argument, respectively, which must be of
-type int. If the precision is given as just '.', the precision is taken to be
-zero. A negative precision is taken as if the precision were omitted. This
-gives the minimum number of digits to appear for \fBd\fP, \fBi\fP, \fBo\fP,
-\fBu\fP, \fBx\fP, and \fBX\fP conversions, the number of digits to appear
-after the radix character for \fBa\fP, \fBA\fP, \fBe\fP, \fBE\fP, \fBf\fP, and
-\fBF\fP conversions, the maximum number of significant digits for \fBg\fP and
-\fBG\fP conversions, or the maximum number of characters to be printed from a
-string for \fBs\fP and \fBS\fP conversions.
-.SH "Length modifier"
-.TP
-.B h
-A following integer conversion corresponds to a \fIshort\fP or \fIunsigned
-short\fP argument.
-.TP
-.B l
-(ell) A following integer conversion corresponds to a \fIlong\fP or
-\fIunsigned long\fP argument, or a following n conversion corresponds to a
-pointer to a long argument
-.TP
-.B ll
-(ell-ell). A following integer conversion corresponds to a \fIlong long\fP or
-\fIunsigned long long\fP argument, or a following n conversion corresponds to
-a pointer to a long long argument.
-.TP
-.B q
-A synonym for \fBll\fP.
-.TP
-.B L
-A following a, A, e, E, f, F, g, or G conversion corresponds to a long double
-argument.
-.TP
-.B z
-A following integer conversion corresponds to a \fIsize_t\fP or \fIssize_t\fP
-argument.
-.SH "Conversion specifiers"
-A character that specifies the type of conversion to be applied. The
-conversion specifiers and their meanings are:
-.TP
-.B d, i
-The int argument is converted to signed decimal notation. The precision, if
-any, gives the minimum number of digits that must appear; if the converted
-value requires fewer digits, it is padded on the left with zeros. The default
-precision is 1. When 0 is printed with an explicit precision 0, the output is
-empty.
-.TP
-.B o, u, x, X
-The unsigned int argument is converted to unsigned octal (o), unsigned decimal
-(u), or unsigned hexadecimal (\fBx\fP and \fBX\fP) notation. The letters
-\fIabcdef\fP are used for \fBx\fP conversions; the letters \fIABCDEF\fP are
-used for \fBX\fP conversions. The precision, if any, gives the minimum number
-of digits that must appear; if the converted value requires fewer digits, it
-is padded on the left with zeros. The default precision is 1. When 0 is
-printed with an explicit precision 0, the output is empty.
-.TP
-.B e, E
-The double argument is rounded and output in the style \fB"[-]d.ddde±dd"\fP
-.TP
-.B f, F
-The double argument is rounded and output to decimal notation in the style
-\fB"[-]ddd.ddd"\fP.
-.TP
-.B g, G
-The double argument is converted in style f or e.
-.TP
-.B c
-The int argument is converted to an unsigned char, and the resulting character
-is written.
-.TP
-.B s
-The \fIconst char *\fP argument is expected to be a pointer to an array of
-character type (pointer to a string). Characters from the array are written up
-to (but not including) a terminating null byte. If a precision is specified,
-no more than the number specified are written. If a precision is given, no
-null byte need be present; if the precision is not specified, or is greater
-than the size of the array, the array must contain a terminating null byte.
-.TP
-.B p
-The \fIvoid *\fP pointer argument is printed in hexadecimal.
-.TP
-.B n
-The number of characters written so far is stored into the integer pointed to
-by the corresponding argument.
-.TP
-.B %
-A '%' is written. No argument is converted.
-.SH EXAMPLE
-.nf
- curl_mprintf("My name is %s\\n", name);
- curl_mprintf("Pi is almost %f\\n", 25/8);
-.fi
-.SH AVAILABILITY
-These functions might be removed from the public libcurl API in the future. Do
-not use them in new programs or projects.
-.SH RETURN VALUE
-The \fBcurl_maprintf\fP and \fBcurl_mvaprintf\fP functions return a pointer to
-a newly allocated string, or NULL if it failed.
-
-All other functions return the number of characters actually printed
-(excluding the null byte used to end output to strings). Note that this
-sometimes differ from how the POSIX versions of these functions work.
-.SH "SEE ALSO"
-.BR printf "(3), " sprintf "(3), " fprintf "(3), " vprintf "(3) "
diff --git a/docs/libcurl/curl_mprintf.md b/docs/libcurl/curl_mprintf.md
new file mode 100644
index 000000000..5aca9e3f6
--- /dev/null
+++ b/docs/libcurl/curl_mprintf.md
@@ -0,0 +1,288 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_printf
+Section: 3
+Source: libcurl
+See-also:
+ - fprintf (3)
+ - printf (3)
+ - sprintf (3)
+ - vprintf (3)
+---
+
+# NAME
+
+curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
+curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
+curl_mvsprintf - formatted output conversion
+
+# SYNOPSIS
+
+~~~c
+#include <curl/mprintf.h>
+
+int curl_mprintf(const char *format, ...);
+int curl_mfprintf(FILE *fd, const char *format, ...);
+int curl_msprintf(char *buffer, const char *format, ...);
+int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...);
+int curl_mvprintf(const char *format, va_list args);
+int curl_mvfprintf(FILE *fd, const char *format, va_list args);
+int curl_mvsprintf(char *buffer, const char *format, va_list args);
+int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
+ va_list args);
+char *curl_maprintf(const char *format , ...);
+char *curl_mvaprintf(const char *format, va_list args);
+~~~
+
+# DESCRIPTION
+
+These functions produce output according to the format string and given
+arguments. They are mostly clones of the well-known C-style functions but
+there are slight differences in behavior.
+
+We discourage users from using any of these functions in new applications.
+
+Functions in the curl_mprintf() family produce output according to a format as
+described below. The functions **curl_mprintf()** and **curl_mvprintf()**
+write output to stdout, the standard output stream; **curl_mfprintf()** and
+**curl_mvfprintf()** write output to the given output stream;
+**curl_msprintf()**, **curl_msnprintf()**, **curl_mvsprintf()**, and
+**curl_mvsnprintf()** write to the character string **buffer**.
+
+The functions **curl_msnprintf()** and **curl_mvsnprintf()** write at most
+*maxlength* bytes (including the terminating null byte ('0')) to
+*buffer*.
+
+The functions **curl_mvprintf()**, **curl_mvfprintf()**,
+**curl_mvsprintf()**, **curl_mvsnprintf()** are equivalent to the
+functions **curl_mprintf()**, **curl_mfprintf()**, **curl_msprintf()**,
+**curl_msnprintf()**, respectively, except that they are called with a
+*va_list* instead of a variable number of arguments. These functions do
+not call the *va_end* macro. Because they invoke the *va_arg* macro,
+the value of *ap* is undefined after the call.
+
+The functions **curl_maprintf()** and **curl_mvaprintf()** return the
+output string as pointer to a newly allocated memory area. The returned string
+must be curl_free(3)ed by the receiver.
+
+All of these functions write the output under the control of a format string
+that specifies how subsequent arguments are converted for output.
+
+# FORMAT STRING
+
+The format string is composed of zero or more directives: ordinary characters
+(not %), which are copied unchanged to the output stream; and conversion
+specifications, each of which results in fetching zero or more subsequent
+arguments. Each conversion specification is introduced by the character %, and
+ends with a conversion specifier. In between there may be (in this order) zero
+or more *flags*, an optional minimum *field width*, an optional
+*precision* and an optional *length modifier*.
+
+# The $ modifier
+
+The arguments must correspond properly with the conversion specifier. By
+default, the arguments are used in the order given, where each '*' (see Field
+width and Precision below) and each conversion specifier asks for the next
+argument (and it is an error if insufficiently many arguments are given). One
+can also specify explicitly which argument is taken, at each place where an
+argument is required, by writing "%m$" instead of '%' and "*m$" instead
+of '*', where the decimal integer m denotes the position in the argument list
+of the desired argument, indexed starting from 1. Thus,
+~~~c
+ curl_mprintf("%*d", width, num);
+~~~
+and
+~~~c
+ curl_mprintf("%2$*1$d", width, num);
+~~~
+are equivalent. The second style allows repeated references to the same
+argument.
+
+If the style using '$' is used, it must be used throughout for all conversions
+taking an argument and all width and precision arguments, but it may be mixed
+with "%%" formats, which do not consume an argument. There may be no gaps in
+the numbers of arguments specified using '$'; for example, if arguments 1 and
+3 are specified, argument 2 must also be specified somewhere in the format
+string.
+
+# Flag characters
+
+The character % is followed by zero or more of the following flags:
+
+## #
+
+The value should be converted to its "alternate form".
+
+## 0
+
+The value should be zero padded.
+
+## -
+
+The converted value is to be left adjusted on the field boundary. (The default
+is right justification.) The converted value is padded on the right with
+blanks, rather than on the left with blanks or zeros. A '-' overrides a &'0'
+if both are given.
+
+## (space)
+
+(a space: ' ') A blank should be left before a positive number (or empty
+string) produced by a signed conversion.
+
+## +
+
+A sign (+ or -) should always be placed before a number produced by a signed
+conversion. By default, a sign is used only for negative numbers. A '+'
+overrides a space if both are used.
+
+# Field width
+
+An optional decimal digit string (with nonzero first digit) specifying a
+minimum field width. If the converted value has fewer characters than the
+field width, it gets padded with spaces on the left (or right, if the
+left-adjustment flag has been given). Instead of a decimal digit string one
+may write "*" or "*m$" (for some decimal integer m) to specify that the field
+width is given in the next argument, or in the *m-th* argument,
+respectively, which must be of type int. A negative field width is taken as
+a '-' flag followed by a positive field width. In no case does a nonexistent
+or small field width cause truncation of a field; if the result of a
+conversion is wider than the field width, the field is expanded to contain the
+conversion result.
+
+# Precision
+
+An optional precision in the form of a period ('.') followed by an optional
+decimal digit string. Instead of a decimal digit string one may write "*" or
+"*m$" (for some decimal integer m) to specify that the precision is given in
+the next argument, or in the *m-th* argument, respectively, which must be of
+type int. If the precision is given as just '.', the precision is taken to be
+zero. A negative precision is taken as if the precision were omitted. This
+gives the minimum number of digits to appear for **d**, **i**, **o**,
+**u**, **x**, and **X** conversions, the number of digits to appear
+after the radix character for **a**, **A**, **e**, **E**, **f**, and
+**F** conversions, the maximum number of significant digits for **g** and
+**G** conversions, or the maximum number of characters to be printed from a
+string for **s** and **S** conversions.
+
+# Length modifier
+
+## h
+
+A following integer conversion corresponds to a *short* or *unsigned short*
+argument.
+
+## l
+
+(ell) A following integer conversion corresponds to a *long* or
+*unsigned long* argument, or a following n conversion corresponds to a
+pointer to a long argument
+
+## ll
+
+(ell-ell). A following integer conversion corresponds to a *long long* or
+*unsigned long long* argument, or a following n conversion corresponds to
+a pointer to a long long argument.
+
+## q
+
+A synonym for **ll**.
+
+## L
+
+A following a, A, e, E, f, F, g, or G conversion corresponds to a long double
+argument.
+
+## z
+
+A following integer conversion corresponds to a *size_t* or *ssize_t*
+argument.
+
+# Conversion specifiers
+
+A character that specifies the type of conversion to be applied. The
+conversion specifiers and their meanings are:
+
+## d, i
+
+The int argument is converted to signed decimal notation. The precision, if
+any, gives the minimum number of digits that must appear; if the converted
+value requires fewer digits, it is padded on the left with zeros. The default
+precision is 1. When 0 is printed with an explicit precision 0, the output is
+empty.
+
+## o, u, x, X
+
+The unsigned int argument is converted to unsigned octal (o), unsigned decimal
+(u), or unsigned hexadecimal (**x** and **X**) notation. The letters
+*abcdef* are used for **x** conversions; the letters *ABCDEF* are
+used for **X** conversions. The precision, if any, gives the minimum number
+of digits that must appear; if the converted value requires fewer digits, it
+is padded on the left with zeros. The default precision is 1. When 0 is
+printed with an explicit precision 0, the output is empty.
+
+## e, E
+
+The double argument is rounded and output in the style **"[-]d.ddde±dd"**
+
+## f, F
+
+The double argument is rounded and output to decimal notation in the style
+**"[-]ddd.ddd"**.
+
+## g, G
+
+The double argument is converted in style f or e.
+
+## c
+
+The int argument is converted to an unsigned char, and the resulting character
+is written.
+
+## s
+
+The *const char ** argument is expected to be a pointer to an array of
+character type (pointer to a string). Characters from the array are written up
+to (but not including) a terminating null byte. If a precision is specified,
+no more than the number specified are written. If a precision is given, no
+null byte need be present; if the precision is not specified, or is greater
+than the size of the array, the array must contain a terminating null byte.
+
+## p
+
+The *void ** pointer argument is printed in hexadecimal.
+
+## n
+
+The number of characters written so far is stored into the integer pointed to
+by the corresponding argument.
+
+## %
+
+A '%' symbol is written. No argument is converted.
+
+# EXAMPLE
+
+~~~c
+const char *name = "John";
+
+int main(void)
+{
+ curl_mprintf("My name is %s\n", name);
+ curl_mprintf("Pi is almost %f\n", (double)25.0/8);
+}
+~~~
+
+# AVAILABILITY
+
+These functions might be removed from the public libcurl API in the future. Do
+not use them in new programs or projects.
+
+# RETURN VALUE
+
+The **curl_maprintf** and **curl_mvaprintf** functions return a pointer to
+a newly allocated string, or NULL if it failed.
+
+All other functions return the number of characters actually printed
+(excluding the null byte used to end output to strings). Note that this
+sometimes differ from how the POSIX versions of these functions work.
diff --git a/docs/libcurl/curl_multi_add_handle.3 b/docs/libcurl/curl_multi_add_handle.3
deleted file mode 100644
index f53673bd5..000000000
--- a/docs/libcurl/curl_multi_add_handle.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_add_handle 3 "4 March 2002" "libcurl" "libcurl"
-.SH NAME
-curl_multi_add_handle - add an easy handle to a multi session
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle);
-.fi
-.SH DESCRIPTION
-Adds the \fIeasy handle\fP to the \fImulti_handle\fP.
-
-While an easy handle is added to a multi stack, you cannot and you must not
-use \fIcurl_easy_perform(3)\fP on that handle. After having removed the easy
-handle from the multi stack again, it is perfectly fine to use it with the
-easy interface again.
-
-If the easy handle is not set to use a shared (\fICURLOPT_SHARE(3)\fP) cache,
-it is made to use a DNS cache that is shared between all easy handles within
-the multi handle when \fIcurl_multi_add_handle(3)\fP is called.
-
-When an easy interface is added to a multi handle, it is set to use a shared
-connection cache owned by the multi handle. Removing and adding new easy
-handles does not affect the pool of connections or the ability to do
-connection reuse.
-
-If you have \fICURLMOPT_TIMERFUNCTION(3)\fP set in the multi handle (as you
-should if you are working event-based with \fIcurl_multi_socket_action(3)\fP
-and friends), that callback is called from within this function to ask for an
-updated timer so that your main event loop gets the activity on this handle to
-get started.
-
-The easy handle remains added to the multi handle until you remove it again
-with \fIcurl_multi_remove_handle(3)\fP - even when a transfer with that
-specific easy handle is completed.
-
-You should remove the easy handle from the multi stack before you terminate
-first the easy handle and then the multi handle:
-
-1 - \fIcurl_multi_remove_handle(3)\fP
-
-2 - \fIcurl_easy_cleanup(3)\fP
-
-3 - \fIcurl_multi_cleanup(3)\fP
-.SH EXAMPLE
-.nf
- /* init a multi stack */
- multi_handle = curl_multi_init();
-
- /* add individual transfers */
- curl_multi_add_handle(multi_handle, http_handle);
- curl_multi_add_handle(multi_handle, http_handle2);
-.fi
-.SH AVAILABILITY
-Added in 7.9.6
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code.
-.SH "SEE ALSO"
-.BR curl_multi_cleanup (3),
-.BR curl_multi_get_handles (3),
-.BR curl_multi_init (3),
-.BR curl_multi_setopt (3),
-.BR curl_multi_socket_action (3)
diff --git a/docs/libcurl/curl_multi_add_handle.md b/docs/libcurl/curl_multi_add_handle.md
new file mode 100644
index 000000000..3d6ba81fb
--- /dev/null
+++ b/docs/libcurl/curl_multi_add_handle.md
@@ -0,0 +1,88 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_add_handle
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_cleanup (3)
+ - curl_multi_get_handles (3)
+ - curl_multi_init (3)
+ - curl_multi_setopt (3)
+ - curl_multi_socket_action (3)
+---
+
+# NAME
+
+curl_multi_add_handle - add an easy handle to a multi session
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *easy_handle);
+~~~
+
+# DESCRIPTION
+
+Adds the *easy handle* to the *multi_handle*.
+
+While an easy handle is added to a multi stack, you cannot and you must not
+use curl_easy_perform(3) on that handle. After having removed the easy
+handle from the multi stack again, it is perfectly fine to use it with the
+easy interface again.
+
+If the easy handle is not set to use a shared (CURLOPT_SHARE(3)) cache,
+it is made to use a DNS cache that is shared between all easy handles within
+the multi handle when curl_multi_add_handle(3) is called.
+
+When an easy interface is added to a multi handle, it is set to use a shared
+connection cache owned by the multi handle. Removing and adding new easy
+handles does not affect the pool of connections or the ability to do
+connection reuse.
+
+If you have CURLMOPT_TIMERFUNCTION(3) set in the multi handle (as you
+should if you are working event-based with curl_multi_socket_action(3)
+and friends), that callback is called from within this function to ask for an
+updated timer so that your main event loop gets the activity on this handle to
+get started.
+
+The easy handle remains added to the multi handle until you remove it again
+with curl_multi_remove_handle(3) - even when a transfer with that
+specific easy handle is completed.
+
+You should remove the easy handle from the multi stack before you terminate
+first the easy handle and then the multi handle:
+
+1 - curl_multi_remove_handle(3)
+
+2 - curl_easy_cleanup(3)
+
+3 - curl_multi_cleanup(3)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* init a multi stack */
+ CURLM *multi = curl_multi_init();
+
+ /* create two easy handles */
+ CURL *http_handle = curl_easy_init();
+ CURL *http_handle2 = curl_easy_init();
+
+ /* add individual transfers */
+ curl_multi_add_handle(multi, http_handle);
+ curl_multi_add_handle(multi, http_handle2);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.6
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code.
diff --git a/docs/libcurl/curl_multi_assign.3 b/docs/libcurl/curl_multi_assign.3
deleted file mode 100644
index 78714aa8f..000000000
--- a/docs/libcurl/curl_multi_assign.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_assign 3 "9 Jul 2006" "libcurl" "libcurl"
-.SH NAME
-curl_multi_assign \- set data to associate with an internal socket
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_assign(CURLM *multi_handle, curl_socket_t sockfd,
- void *sockptr);
-.fi
-.SH DESCRIPTION
-This function creates an association in the multi handle between the given
-socket and a private pointer of the application. This is designed for
-\fIcurl_multi_socket_action(3)\fP uses.
-
-When set, the \fIsockptr\fP pointer is passed to all future socket callbacks
-for the specific \fIsockfd\fP socket.
-
-If the given \fIsockfd\fP is not already in use by libcurl, this function
-returns an error.
-
-libcurl only keeps one single pointer associated with a socket, so calling
-this function several times for the same socket makes the last set pointer get
-used.
-
-The idea here being that this association (socket to private pointer) is
-something that just about every application that uses this API needs and then
-libcurl can just as well do it since it already has the necessary
-functionality.
-
-It is acceptable to call this function from your multi callback functions.
-.SH EXAMPLE
-.nf
- /* make our struct pointer associated with socket fd */
- mc = curl_multi_assign(multi_handle, fd, ourstructp);
-.fi
-.SH AVAILABILITY
-Added in 7.15.5
-.SH RETURN VALUE
-The standard CURLMcode for multi interface error codes.
-.SH TYPICAL USAGE
-In a typical application you allocate a struct or at least use some kind of
-semi-dynamic data for each socket that we must wait for action on when using
-the \fIcurl_multi_socket_action(3)\fP approach.
-
-When our socket-callback gets called by libcurl and we get to know about yet
-another socket to wait for, we can use \fIcurl_multi_assign(3)\fP to point out
-the particular data so that when we get updates about this same socket again,
-we do not have to find the struct associated with this socket by ourselves.
-.SH "SEE ALSO"
-.BR curl_multi_setopt (3),
-.BR curl_multi_socket_action (3)
diff --git a/docs/libcurl/curl_multi_assign.md b/docs/libcurl/curl_multi_assign.md
new file mode 100644
index 000000000..3f01349cd
--- /dev/null
+++ b/docs/libcurl/curl_multi_assign.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_assign
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_setopt (3)
+ - curl_multi_socket_action (3)
+---
+
+# NAME
+
+curl_multi_assign - set data to associate with an internal socket
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_assign(CURLM *multi_handle, curl_socket_t sockfd,
+ void *sockptr);
+~~~
+
+# DESCRIPTION
+
+This function creates an association in the multi handle between the given
+socket and a private pointer of the application. This is designed for
+curl_multi_socket_action(3) uses.
+
+When set, the *sockptr* pointer is passed to all future socket callbacks
+for the specific *sockfd* socket.
+
+If the given *sockfd* is not already in use by libcurl, this function
+returns an error.
+
+libcurl only keeps one single pointer associated with a socket, so calling
+this function several times for the same socket makes the last set pointer get
+used.
+
+The idea here being that this association (socket to private pointer) is
+something that just about every application that uses this API needs and then
+libcurl can just as well do it since it already has the necessary
+functionality.
+
+It is acceptable to call this function from your multi callback functions.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *multi = curl_multi_init();
+ void *ourstructp; /* pointer to our data */
+ curl_socket_t fd; /* file descriptor to associate our data with */
+
+ /* make our struct pointer associated with socket fd */
+ CURLMcode mc = curl_multi_assign(multi, fd, ourstructp);
+ if(mc)
+ printf("error: %s\n", curl_multi_strerror(mc));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.5
+
+# RETURN VALUE
+
+The standard CURLMcode for multi interface error codes.
+
+# TYPICAL USAGE
+
+In a typical application you allocate a struct or at least use some kind of
+semi-dynamic data for each socket that we must wait for action on when using
+the curl_multi_socket_action(3) approach.
+
+When our socket-callback gets called by libcurl and we get to know about yet
+another socket to wait for, we can use curl_multi_assign(3) to point out
+the particular data so that when we get updates about this same socket again,
+we do not have to find the struct associated with this socket by ourselves.
diff --git a/docs/libcurl/curl_multi_cleanup.3 b/docs/libcurl/curl_multi_cleanup.3
deleted file mode 100644
index 8b41b78c4..000000000
--- a/docs/libcurl/curl_multi_cleanup.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_cleanup 3 "1 March 2002" "libcurl" "libcurl"
-.SH NAME
-curl_multi_cleanup - close down a multi session
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_cleanup(CURLM *multi_handle);
-.fi
-.SH DESCRIPTION
-Cleans up and removes a whole multi stack. It does not free or touch any
-individual easy handles in any way - they still need to be closed
-individually, using the usual \fIcurl_easy_cleanup(3)\fP way. The order of
-cleaning up should be:
-
-1 - \fIcurl_multi_remove_handle(3)\fP before any easy handles are cleaned up
-
-2 - \fIcurl_easy_cleanup(3)\fP can now be called independently since the easy
-handle is no longer connected to the multi handle
-
-3 - \fIcurl_multi_cleanup(3)\fP should be called when all easy handles are
-removed
-
-Passing in a NULL pointer in \fImulti_handle\fP makes this function return
-CURLM_BAD_HANDLE immediately with no other action.
-.SH EXAMPLE
-.nf
- /* when the multi transfer is done ... */
-
- /* remove all easy handles, then: */
- curl_multi_cleanup(multi_handle);
-.fi
-.SH AVAILABILITY
-Added in 7.9.6
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code. On success,
-CURLM_OK is returned.
-.SH "SEE ALSO"
-.BR curl_easy_cleanup (3),
-.BR curl_multi_get_handles (3),
-.BR curl_easy_init (3),
-.BR curl_multi_init (3)
-
diff --git a/docs/libcurl/curl_multi_cleanup.md b/docs/libcurl/curl_multi_cleanup.md
new file mode 100644
index 000000000..9aa64a85c
--- /dev/null
+++ b/docs/libcurl/curl_multi_cleanup.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_cleanup
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_cleanup (3)
+ - curl_easy_init (3)
+ - curl_multi_get_handles (3)
+ - curl_multi_init (3)
+---
+
+# NAME
+
+curl_multi_cleanup - close down a multi session
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_cleanup(CURLM *multi_handle);
+~~~
+
+# DESCRIPTION
+
+Cleans up and removes a whole multi stack. It does not free or touch any
+individual easy handles in any way - they still need to be closed
+individually, using the usual curl_easy_cleanup(3) way. The order of
+cleaning up should be:
+
+1 - curl_multi_remove_handle(3) before any easy handles are cleaned up
+
+2 - curl_easy_cleanup(3) can now be called independently since the easy
+handle is no longer connected to the multi handle
+
+3 - curl_multi_cleanup(3) should be called when all easy handles are
+removed
+
+Passing in a NULL pointer in *multi_handle* makes this function return
+CURLM_BAD_HANDLE immediately with no other action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *multi = curl_multi_init();
+
+ /* when the multi transfer is done ... */
+
+ /* remove all easy handles, then: */
+ curl_multi_cleanup(multi);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.6
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code. On success,
+CURLM_OK is returned.
diff --git a/docs/libcurl/curl_multi_fdset.3 b/docs/libcurl/curl_multi_fdset.3
deleted file mode 100644
index dbcb5b2b5..000000000
--- a/docs/libcurl/curl_multi_fdset.3
+++ /dev/null
@@ -1,105 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_fdset 3 "2 Jan 2006" "libcurl" "libcurl"
-.SH NAME
-curl_multi_fdset - extracts file descriptor information from a multi handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_fdset(CURLM *multi_handle,
- fd_set *read_fd_set,
- fd_set *write_fd_set,
- fd_set *exc_fd_set,
- int *max_fd);
-.ad
-.SH DESCRIPTION
-This function extracts file descriptor information from a given multi_handle.
-libcurl returns its \fIfd_set\fP sets. The application can use these to
-select() on, but be sure to \fIFD_ZERO\fP them before calling this function as
-\fIcurl_multi_fdset(3)\fP only adds its own descriptors, it does not zero or
-otherwise remove any others. The \fIcurl_multi_perform(3)\fP function should
-be called as soon as one of them is ready to be read from or written to.
-
-If the \fIread_fd_set\fP argument is not a null pointer, it points to an
-object of type \fBfd_set\fP that on returns specifies the file descriptors to
-be checked for being ready to read.
-
-If the \fIwrite_fd_set\fP argument is not a null pointer, it points to an
-object of type \fBfd_set\fP that on return specifies the file descriptors to
-be checked for being ready to write.
-
-If the \fIexc_fd_set\fP argument is not a null pointer, it points to an object
-of type \fBfd_set\fP that on return specifies the file descriptors to be
-checked for error conditions pending.
-
-If no file descriptors are set by libcurl, \fImax_fd\fP contain -1 when this
-function returns. Otherwise it contains the highest descriptor number libcurl
-set. When libcurl returns -1 in \fImax_fd\fP, it is because libcurl currently
-does something that is not possible for your application to monitor with a
-socket and unfortunately you can then not know exactly when the current action
-is completed using select(). You then need to wait a while before you proceed
-and call \fIcurl_multi_perform(3)\fP anyway. How long to wait? Unless
-\fIcurl_multi_timeout(3)\fP gives you a lower number, we suggest 100
-milliseconds or so, but you may want to test it out in your own particular
-conditions to find a suitable value.
-
-When doing select(), you should use \fIcurl_multi_timeout(3)\fP to figure out
-how long to wait for action. Call \fIcurl_multi_perform(3)\fP even if no
-activity has been seen on the \fBfd_sets\fP after the timeout expires as
-otherwise internal retries and timeouts may not work as you would think and
-want.
-
-If one of the sockets used by libcurl happens to be larger than what can be
-set in an \fBfd_set\fP, which on POSIX systems means that the file descriptor
-is larger than \fBFD_SETSIZE\fP, then libcurl tries to not set it. Setting a
-too large file descriptor in an \fBfd_set\fP implies an out of bounds write
-which can cause crashes, or worse. The effect of NOT storing it might possibly
-save you from the crash, but makes your program NOT wait for sockets it should
-wait for...
-.SH EXAMPLE
-.nf
- /* get file descriptors from the transfers */
- mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
-
- if(mc != CURLM_OK) {
- fprintf(stderr, "curl_multi_fdset() failed, code %d.\\n", mc);
- break;
- }
-
- /* wait for activity on one of the sockets */
- rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
-.fi
-.SH AVAILABILITY
-Added in 7.9.6
-.SH RETURN VALUE
-\fBCURLMcode\fP type, general libcurl multi interface error code. See
-\fIlibcurl-errors(3)\fP
-.SH "SEE ALSO"
-.BR curl_multi_cleanup (3),
-.BR curl_multi_init (3),
-.BR curl_multi_perform (3),
-.BR curl_multi_timeout (3),
-.BR curl_multi_wait (3),
-.BR select (2)
diff --git a/docs/libcurl/curl_multi_fdset.md b/docs/libcurl/curl_multi_fdset.md
new file mode 100644
index 000000000..37d5959d1
--- /dev/null
+++ b/docs/libcurl/curl_multi_fdset.md
@@ -0,0 +1,119 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_fdset
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_cleanup (3)
+ - curl_multi_init (3)
+ - curl_multi_perform (3)
+ - curl_multi_timeout (3)
+ - curl_multi_wait (3)
+ - select (2)
+---
+
+# NAME
+
+curl_multi_fdset - extracts file descriptor information from a multi handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_fdset(CURLM *multi_handle,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *exc_fd_set,
+ int *max_fd);
+~~~
+
+# DESCRIPTION
+
+This function extracts file descriptor information from a given multi_handle.
+libcurl returns its *fd_set* sets. The application can use these to
+select() on, but be sure to *FD_ZERO* them before calling this function as
+curl_multi_fdset(3) only adds its own descriptors, it does not zero or
+otherwise remove any others. The curl_multi_perform(3) function should
+be called as soon as one of them is ready to be read from or written to.
+
+The *read_fd_set* argument should point to an object of type **fd_set**
+that on returns specifies the file descriptors to be checked for being ready
+to read.
+
+The *write_fd_set* argument should point to an object of type **fd_set**
+that on return specifies the file descriptors to be checked for being ready to
+write.
+
+The *exc_fd_set* argument should point to an object of type **fd_set**
+that on return specifies the file descriptors to be checked for error
+conditions.
+
+If no file descriptors are set by libcurl, *max_fd* contain -1 when this
+function returns. Otherwise it contains the highest descriptor number libcurl
+set. When libcurl returns -1 in *max_fd*, it is because libcurl currently
+does something that is not possible for your application to monitor with a
+socket and unfortunately you can then not know exactly when the current action
+is completed using select(). You then need to wait a while before you proceed
+and call curl_multi_perform(3) anyway. How long to wait? Unless
+curl_multi_timeout(3) gives you a lower number, we suggest 100
+milliseconds or so, but you may want to test it out in your own particular
+conditions to find a suitable value.
+
+When doing select(), you should use curl_multi_timeout(3) to figure out
+how long to wait for action. Call curl_multi_perform(3) even if no
+activity has been seen on the **fd_sets** after the timeout expires as
+otherwise internal retries and timeouts may not work as you would think and
+want.
+
+If one of the sockets used by libcurl happens to be larger than what can be
+set in an **fd_set**, which on POSIX systems means that the file descriptor
+is larger than **FD_SETSIZE**, then libcurl tries to not set it. Setting a
+too large file descriptor in an **fd_set** implies an out of bounds write
+which can cause crashes, or worse. The effect of NOT storing it might possibly
+save you from the crash, but makes your program NOT wait for sockets it should
+wait for...
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ fd_set fdread;
+ fd_set fdwrite;
+ fd_set fdexcep;
+ int maxfd;
+ int rc;
+ CURLMcode mc;
+ struct timeval timeout = {1, 0};
+
+ CURLM *multi = curl_multi_init();
+
+ do {
+
+ /* call curl_multi_perform() */
+
+ /* get file descriptors from the transfers */
+ mc = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+ if(mc != CURLM_OK) {
+ fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+ break;
+ }
+
+ /* wait for activity on one of the sockets */
+ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+ } while(!mc);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.6
+
+# RETURN VALUE
+
+**CURLMcode** type, general libcurl multi interface error code. See
+libcurl-errors(3)
diff --git a/docs/libcurl/curl_multi_get_handles.3 b/docs/libcurl/curl_multi_get_handles.3
deleted file mode 100644
index 7ee6c734e..000000000
--- a/docs/libcurl/curl_multi_get_handles.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_get_handles 3 "28 August 2023" "libcurl" "libcurl"
-.SH NAME
-curl_multi_get_handles - returns all added easy handles
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURL **curl_multi_get_handles(CURLM *multi_handle);
-.fi
-.SH DESCRIPTION
-Returns an array with pointers to all added easy handles. The end of the list
-is marked with a NULL pointer.
-
-Even if there is not a single easy handle added, this still returns an array
-but with only a single NULL pointer entry.
-
-The returned array contains all the handles that are present at the time of
-the call. As soon as a handle has been removed from or a handle has been added
-to the multi handle after the handle array was returned, the two data points
-are out of sync.
-
-The order of the easy handles within the array is not guaranteed.
-
-The returned array must be freed with a call to \fIcurl_free(3)\fP after use.
-.SH EXAMPLE
-.nf
- /* init a multi stack */
- multi_handle = curl_multi_init();
-
- /* add a transfer */
- curl_multi_add_handle(multi_handle, http_handle);
-
- /* extract all added handles */
- CURL **list = curl_multi_get_handles(multi_handle);
-
- if(list) {
- /* remove all added handles */
- for(i = 0; list[i]; i++) {
- curl_multi_remove_handle(multi_handle, list[i]);
- }
- curl_free(list);
- }
-.fi
-.SH AVAILABILITY
-Added in 8.4.0
-.SH RETURN VALUE
-Returns NULL on failure. Otherwise it returns a pointer to an allocated array.
-.SH "SEE ALSO"
-.BR curl_multi_add_handle (3),
-.BR curl_multi_cleanup (3),
-.BR curl_multi_init (3),
-.BR curl_multi_remove_handle (3)
diff --git a/docs/libcurl/curl_multi_get_handles.md b/docs/libcurl/curl_multi_get_handles.md
new file mode 100644
index 000000000..0a7ff67ca
--- /dev/null
+++ b/docs/libcurl/curl_multi_get_handles.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_get_handles
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_add_handle (3)
+ - curl_multi_cleanup (3)
+ - curl_multi_init (3)
+ - curl_multi_remove_handle (3)
+---
+
+# NAME
+
+curl_multi_get_handles - returns all added easy handles
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURL **curl_multi_get_handles(CURLM *multi_handle);
+~~~
+
+# DESCRIPTION
+
+Returns an array with pointers to all added easy handles. The end of the list
+is marked with a NULL pointer.
+
+Even if there is not a single easy handle added, this still returns an array
+but with only a single NULL pointer entry.
+
+The returned array contains all the handles that are present at the time of
+the call. As soon as a handle has been removed from or a handle has been added
+to the multi handle after the handle array was returned, the two data points
+are out of sync.
+
+The order of the easy handles within the array is not guaranteed.
+
+The returned array must be freed with a call to curl_free(3) after use.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* init a multi stack */
+ CURLM *multi = curl_multi_init();
+ CURL *curl = curl_easy_init();
+
+ if(curl) {
+ /* add the transfer */
+ curl_multi_add_handle(multi, curl);
+
+ /* extract all added handles */
+ CURL **list = curl_multi_get_handles(multi);
+
+ if(list) {
+ int i;
+ /* remove all added handles */
+ for(i = 0; list[i]; i++) {
+ curl_multi_remove_handle(multi, list[i]);
+ }
+ curl_free(list);
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 8.4.0
+
+# RETURN VALUE
+
+Returns NULL on failure. Otherwise it returns a pointer to an allocated array.
diff --git a/docs/libcurl/curl_multi_info_read.3 b/docs/libcurl/curl_multi_info_read.3
deleted file mode 100644
index 2a15ad582..000000000
--- a/docs/libcurl/curl_multi_info_read.3
+++ /dev/null
@@ -1,100 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_info_read 3 "18 Dec 2004" "libcurl" "libcurl"
-.SH NAME
-curl_multi_info_read - read multi stack information
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
-.fi
-.SH DESCRIPTION
-Ask the multi handle if there are any messages from the individual
-transfers. Messages may include information such as an error code from the
-transfer or just the fact that a transfer is completed. More details on these
-should be written down as well.
-
-Repeated calls to this function returns a new struct each time, until a NULL
-is returned as a signal that there is no more to get at this point. The
-integer pointed to with \fImsgs_in_queue\fP contains the number of remaining
-messages after this function was called.
-
-When you fetch a message using this function, it is removed from the internal
-queue so calling this function again does not return the same message
-again. It instead returns new messages at each new invoke until the queue is
-emptied.
-
-\fBWARNING:\fP The data the returned pointer points to does not survive
-calling \fIcurl_multi_cleanup(3)\fP, \fIcurl_multi_remove_handle(3)\fP or
-\fIcurl_easy_cleanup(3)\fP.
-
-The \fICURLMsg\fP struct is simple and only contains basic information. If
-more involved information is wanted, the particular "easy handle" is present
-in that struct and can be used in subsequent regular
-\fIcurl_easy_getinfo(3)\fP calls (or similar):
-
-.nf
- struct CURLMsg {
- CURLMSG msg; /* what this message means */
- CURL *easy_handle; /* the handle it concerns */
- union {
- void *whatever; /* message-specific data */
- CURLcode result; /* return code for transfer */
- } data;
- };
-.fi
-When \fBmsg\fP is \fICURLMSG_DONE\fP, the message identifies a transfer that
-is done, and then \fBresult\fP contains the return code for the easy handle
-that just completed.
-
-At this point, there are no other \fBmsg\fP types defined.
-.SH EXAMPLE
-.nf
-struct CURLMsg *m;
-
-/* call curl_multi_perform or curl_multi_socket_action first, then loop
- through and check if there are any transfers that have completed */
-
-do {
- int msgq = 0;
- m = curl_multi_info_read(multi_handle, &msgq);
- if(m && (m->msg == CURLMSG_DONE)) {
- CURL *e = m->easy_handle;
- transfers--;
- curl_multi_remove_handle(multi_handle, e);
- curl_easy_cleanup(e);
- }
-} while(m);
-.fi
-.SH AVAILABILITY
-Added in 7.9.6
-.SH RETURN VALUE
-A pointer to a filled-in struct, or NULL if it failed or ran out of
-structs. It also writes the number of messages left in the queue (after this
-read) in the integer the second argument points to.
-.SH "SEE ALSO"
-.BR curl_multi_cleanup (3),
-.BR curl_multi_init (3),
-.BR curl_multi_perform (3)
diff --git a/docs/libcurl/curl_multi_info_read.md b/docs/libcurl/curl_multi_info_read.md
new file mode 100644
index 000000000..23d515d8f
--- /dev/null
+++ b/docs/libcurl/curl_multi_info_read.md
@@ -0,0 +1,102 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_info_read
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_cleanup (3)
+ - curl_multi_init (3)
+ - curl_multi_perform (3)
+---
+
+# NAME
+
+curl_multi_info_read - read multi stack information
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
+~~~
+
+# DESCRIPTION
+
+Ask the multi handle if there are any messages from the individual
+transfers. Messages may include information such as an error code from the
+transfer or just the fact that a transfer is completed. More details on these
+should be written down as well.
+
+Repeated calls to this function returns a new struct each time, until a NULL
+is returned as a signal that there is no more to get at this point. The
+integer pointed to with *msgs_in_queue* contains the number of remaining
+messages after this function was called.
+
+When you fetch a message using this function, it is removed from the internal
+queue so calling this function again does not return the same message
+again. It instead returns new messages at each new invoke until the queue is
+emptied.
+
+**WARNING:** The data the returned pointer points to does not survive
+calling curl_multi_cleanup(3), curl_multi_remove_handle(3) or
+curl_easy_cleanup(3).
+
+The *CURLMsg* struct is simple and only contains basic information. If
+more involved information is wanted, the particular "easy handle" is present
+in that struct and can be used in subsequent regular
+curl_easy_getinfo(3) calls (or similar):
+
+~~~c
+ struct CURLMsg {
+ CURLMSG msg; /* what this message means */
+ CURL *easy_handle; /* the handle it concerns */
+ union {
+ void *whatever; /* message-specific data */
+ CURLcode result; /* return code for transfer */
+ } data;
+ };
+~~~
+When **msg** is *CURLMSG_DONE*, the message identifies a transfer that
+is done, and then **result** contains the return code for the easy handle
+that just completed.
+
+At this point, there are no other **msg** types defined.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *multi = curl_multi_init();
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct CURLMsg *m;
+
+ /* call curl_multi_perform or curl_multi_socket_action first, then loop
+ through and check if there are any transfers that have completed */
+
+ do {
+ int msgq = 0;
+ m = curl_multi_info_read(multi, &msgq);
+ if(m && (m->msg == CURLMSG_DONE)) {
+ CURL *e = m->easy_handle;
+ /* m->data.result holds the error code for the transfer */
+ curl_multi_remove_handle(multi, e);
+ curl_easy_cleanup(e);
+ }
+ } while(m);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.6
+
+# RETURN VALUE
+
+A pointer to a filled-in struct, or NULL if it failed or ran out of
+structs. It also writes the number of messages left in the queue (after this
+read) in the integer the second argument points to.
diff --git a/docs/libcurl/curl_multi_init.3 b/docs/libcurl/curl_multi_init.3
deleted file mode 100644
index 5fe21b781..000000000
--- a/docs/libcurl/curl_multi_init.3
+++ /dev/null
@@ -1,58 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_init 3 "1 March 2002" "libcurl" "libcurl"
-.SH NAME
-curl_multi_init - create a multi handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLM *curl_multi_init();
-.fi
-.SH DESCRIPTION
-This function returns a pointer to a \fICURLM\fP handle to be used as input to
-all the other multi-functions, sometimes referred to as a multi handle in some
-places in the documentation. This init call MUST have a corresponding call to
-\fIcurl_multi_cleanup(3)\fP when the operation is complete.
-.SH EXAMPLE
-.nf
-/* init a multi stack */
-multi_handle = curl_multi_init();
-
-/* add individual transfers */
-curl_multi_add_handle(multi_handle, http_handle);
-curl_multi_add_handle(multi_handle, http_handle2);
-.fi
-.SH AVAILABILITY
-Added in 7.9.6
-.SH RETURN VALUE
-If this function returns NULL, something went wrong and you cannot use the
-other curl functions.
-.SH "SEE ALSO"
-.BR curl_multi_cleanup (3),
-.BR curl_multi_add_handle (3),
-.BR curl_multi_get_handles (3),
-.BR curl_global_init (3),
-.BR curl_easy_init (3)
-
diff --git a/docs/libcurl/curl_multi_init.md b/docs/libcurl/curl_multi_init.md
new file mode 100644
index 000000000..0e91b57c1
--- /dev/null
+++ b/docs/libcurl/curl_multi_init.md
@@ -0,0 +1,57 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_init
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_init (3)
+ - curl_global_init (3)
+ - curl_multi_add_handle (3)
+ - curl_multi_cleanup (3)
+ - curl_multi_get_handles (3)
+---
+
+# NAME
+
+curl_multi_init - create a multi handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLM *curl_multi_init();
+~~~
+
+# DESCRIPTION
+
+This function returns a pointer to a *CURLM* handle to be used as input to
+all the other multi-functions, sometimes referred to as a multi handle in some
+places in the documentation. This init call MUST have a corresponding call to
+curl_multi_cleanup(3) when the operation is complete.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* init a multi stack */
+ CURLM *multi = curl_multi_init();
+ CURL *curl = curl_easy_init();
+ CURL *curl2 = curl_easy_init();
+
+ /* add individual transfers */
+ curl_multi_add_handle(multi, curl);
+ curl_multi_add_handle(multi, curl2);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.6
+
+# RETURN VALUE
+
+If this function returns NULL, something went wrong and you cannot use the
+other curl functions.
diff --git a/docs/libcurl/curl_multi_perform.3 b/docs/libcurl/curl_multi_perform.3
deleted file mode 100644
index 49ad6e02c..000000000
--- a/docs/libcurl/curl_multi_perform.3
+++ /dev/null
@@ -1,102 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_perform 3 "1 March 2002" "libcurl" "libcurl"
-.SH NAME
-curl_multi_perform - reads/writes available data from easy handles
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles);
-.fi
-.SH DESCRIPTION
-This function performs transfers on all the added handles that need attention
-in a non-blocking fashion. The easy handles have previously been added to the
-multi handle with \fIcurl_multi_add_handle(3)\fP.
-
-When an application has found out there is data available for the multi_handle
-or a timeout has elapsed, the application should call this function to
-read/write whatever there is to read or write right now etc.
-\fIcurl_multi_perform(3)\fP returns as soon as the reads/writes are done. This
-function does not require that there actually is any data available for
-reading or that data can be written, it can be called just in case. It stores
-the number of handles that still transfer data in the second argument's
-integer-pointer.
-
-If the amount of \fIrunning_handles\fP is changed from the previous call (or
-is less than the amount of easy handles you have added to the multi handle),
-you know that there is one or more transfers less "running". You can then call
-\fIcurl_multi_info_read(3)\fP to get information about each individual
-completed transfer, and that returned info includes CURLcode and more. If an
-added handle fails quickly, it may never be counted as a running_handle. You
-could use \fIcurl_multi_info_read(3)\fP to track actual status of the added
-handles in that case.
-
-When \fIrunning_handles\fP is set to zero (0) on the return of this function,
-there is no longer any transfers in progress.
-
-When this function returns error, the state of all transfers are uncertain and
-they cannot be continued. \fIcurl_multi_perform(3)\fP should not be called
-again on the same multi handle after an error has been returned, unless first
-removing all the handles and adding new ones.
-.SH EXAMPLE
-.nf
-int still_running;
-do {
- CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
-
- if(!mc && still_running)
- /* wait for activity, timeout or "nothing" */
- mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);
-
- if(mc) {
- fprintf(stderr, "curl_multi_poll() failed, code %d.\\n", (int)mc);
- break;
- }
-
-/* if there are still transfers, loop! */
-} while(still_running);
-.fi
-.SH AVAILABILITY
-Added in 7.9.6
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code.
-
-This function returns errors regarding the whole multi stack. Problems on
-individual transfers may have occurred even when this function returns
-\fICURLM_OK\fP. Use \fIcurl_multi_info_read(3)\fP to figure out how individual
-transfers did.
-.SH "TYPICAL USAGE"
-Most applications use \fIcurl_multi_poll(3)\fP to make libcurl wait for
-activity on any of the ongoing transfers. As soon as one or more file
-descriptor has activity or the function times out, the application calls
-\fIcurl_multi_perform(3)\fP.
-.SH "SEE ALSO"
-.BR curl_multi_add_handle (3),
-.BR curl_multi_cleanup (3),
-.BR curl_multi_fdset (3),
-.BR curl_multi_info_read (3),
-.BR curl_multi_init (3),
-.BR curl_multi_wait (3),
-.BR libcurl-errors (3)
diff --git a/docs/libcurl/curl_multi_perform.md b/docs/libcurl/curl_multi_perform.md
new file mode 100644
index 000000000..ecad22edf
--- /dev/null
+++ b/docs/libcurl/curl_multi_perform.md
@@ -0,0 +1,107 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_perform
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_add_handle (3)
+ - curl_multi_cleanup (3)
+ - curl_multi_fdset (3)
+ - curl_multi_info_read (3)
+ - curl_multi_init (3)
+ - curl_multi_wait (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+curl_multi_perform - reads/writes available data from easy handles
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles);
+~~~
+
+# DESCRIPTION
+
+This function performs transfers on all the added handles that need attention
+in a non-blocking fashion. The easy handles have previously been added to the
+multi handle with curl_multi_add_handle(3).
+
+When an application has found out there is data available for the multi_handle
+or a timeout has elapsed, the application should call this function to
+read/write whatever there is to read or write right now etc.
+curl_multi_perform(3) returns as soon as the reads/writes are done. This
+function does not require that there actually is any data available for
+reading or that data can be written, it can be called just in case. It stores
+the number of handles that still transfer data in the second argument's
+integer-pointer.
+
+If the amount of *running_handles* is changed from the previous call (or
+is less than the amount of easy handles you have added to the multi handle),
+you know that there is one or more transfers less "running". You can then call
+curl_multi_info_read(3) to get information about each individual
+completed transfer, and that returned info includes CURLcode and more. If an
+added handle fails quickly, it may never be counted as a running_handle. You
+could use curl_multi_info_read(3) to track actual status of the added
+handles in that case.
+
+When *running_handles* is set to zero (0) on the return of this function,
+there is no longer any transfers in progress.
+
+When this function returns error, the state of all transfers are uncertain and
+they cannot be continued. curl_multi_perform(3) should not be called
+again on the same multi handle after an error has been returned, unless first
+removing all the handles and adding new ones.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ int still_running;
+ CURL *multi = curl_multi_init();
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_multi_add_handle(multi, curl);
+ do {
+ CURLMcode mc = curl_multi_perform(multi, &still_running);
+
+ if(!mc && still_running)
+ /* wait for activity, timeout or "nothing" */
+ mc = curl_multi_poll(multi, NULL, 0, 1000, NULL);
+
+ if(mc) {
+ fprintf(stderr, "curl_multi_poll() failed, code %d.\n", (int)mc);
+ break;
+ }
+
+ /* if there are still transfers, loop! */
+ } while(still_running);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.6
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code.
+
+This function returns errors regarding the whole multi stack. Problems on
+individual transfers may have occurred even when this function returns
+*CURLM_OK*. Use curl_multi_info_read(3) to figure out how individual
+transfers did.
+
+# TYPICAL USAGE
+
+Most applications use curl_multi_poll(3) to make libcurl wait for
+activity on any of the ongoing transfers. As soon as one or more file
+descriptor has activity or the function times out, the application calls
+curl_multi_perform(3).
diff --git a/docs/libcurl/curl_multi_poll.3 b/docs/libcurl/curl_multi_poll.3
deleted file mode 100644
index c70912316..000000000
--- a/docs/libcurl/curl_multi_poll.3
+++ /dev/null
@@ -1,121 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_poll 3 "29 Jul 2019" "libcurl" "libcurl"
-.SH NAME
-curl_multi_poll - polls on all easy handles in a multi handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_poll(CURLM *multi_handle,
- struct curl_waitfd extra_fds[],
- unsigned int extra_nfds,
- int timeout_ms,
- int *numfds);
-.ad
-.SH DESCRIPTION
-\fIcurl_multi_poll(3)\fP polls all file descriptors used by the curl easy
-handles contained in the given multi handle set. It blocks until activity is
-detected on at least one of the handles or \fItimeout_ms\fP has passed.
-Alternatively, if the multi handle has a pending internal timeout that has a
-shorter expiry time than \fItimeout_ms\fP, that shorter time is used instead
-to make sure timeout accuracy is reasonably kept.
-
-The calling application may pass additional curl_waitfd structures which are
-similar to \fIpoll(2)\fP's \fIpollfd\fP structure to be waited on in the same
-call.
-
-On completion, if \fInumfds\fP is non-NULL, it gets populated with the total
-number of file descriptors on which interesting events occurred. This number
-can include both libcurl internal descriptors as well as descriptors provided
-in \fIextra_fds\fP.
-
-The \fIcurl_multi_wakeup(3)\fP function can be used from another thread to
-wake up this function and return faster. This is one of the details
-that makes this function different than \fIcurl_multi_wait(3)\fP which cannot
-be woken up this way.
-
-If no extra file descriptors are provided and libcurl has no file descriptor
-to offer to wait for, this function instead waits during \fItimeout_ms\fP
-milliseconds (or shorter if an internal timer indicates so). This is the other
-detail that makes this function different than \fIcurl_multi_wait(3)\fP.
-
-This function is encouraged to be used instead of select(3) when using the
-multi interface to allow applications to easier circumvent the common problem
-with 1024 maximum file descriptors.
-.SH curl_waitfd
-.nf
-struct curl_waitfd {
- curl_socket_t fd;
- short events;
- short revents;
-};
-.fi
-.IP CURL_WAIT_POLLIN
-Bit flag to curl_waitfd.events indicating the socket should poll on read
-events such as new data received.
-.IP CURL_WAIT_POLLPRI
-Bit flag to curl_waitfd.events indicating the socket should poll on high
-priority read events such as out of band data.
-.IP CURL_WAIT_POLLOUT
-Bit flag to curl_waitfd.events indicating the socket should poll on write
-events such as the socket being clear to write without blocking.
-.SH EXAMPLE
-.nf
-CURL *easy_handle;
-CURLM *multi_handle;
-
-/* add the individual easy handle */
-curl_multi_add_handle(multi_handle, easy_handle);
-
-do {
- CURLMcode mc;
- int numfds;
-
- mc = curl_multi_perform(multi_handle, &still_running);
-
- if(mc == CURLM_OK) {
- /* wait for activity or timeout */
- mc = curl_multi_poll(multi_handle, NULL, 0, 1000, &numfds);
- }
-
- if(mc != CURLM_OK) {
- fprintf(stderr, "curl_multi failed, code %d.\\n", mc);
- break;
- }
-
-} while(still_running);
-
-curl_multi_remove_handle(multi_handle, easy_handle);
-.fi
-.SH AVAILABILITY
-Added in 7.66.0.
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code. See
-\fIlibcurl-errors(3)\fP
-.SH "SEE ALSO"
-.BR curl_multi_fdset (3),
-.BR curl_multi_perform (3),
-.BR curl_multi_wait (3),
-.BR curl_multi_wakeup (3)
diff --git a/docs/libcurl/curl_multi_poll.md b/docs/libcurl/curl_multi_poll.md
new file mode 100644
index 000000000..b239f2836
--- /dev/null
+++ b/docs/libcurl/curl_multi_poll.md
@@ -0,0 +1,128 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_poll
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_fdset (3)
+ - curl_multi_perform (3)
+ - curl_multi_wait (3)
+ - curl_multi_wakeup (3)
+---
+
+# NAME
+
+curl_multi_poll - polls on all easy handles in a multi handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_poll(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *numfds);
+~~~
+
+# DESCRIPTION
+
+curl_multi_poll(3) polls all file descriptors used by the curl easy
+handles contained in the given multi handle set. It blocks until activity is
+detected on at least one of the handles or *timeout_ms* has passed.
+Alternatively, if the multi handle has a pending internal timeout that has a
+shorter expiry time than *timeout_ms*, that shorter time is used instead
+to make sure timeout accuracy is reasonably kept.
+
+The calling application may pass additional curl_waitfd structures which are
+similar to *poll(2)*'s *pollfd* structure to be waited on in the same
+call.
+
+On completion, if *numfds* is non-NULL, it gets populated with the total
+number of file descriptors on which interesting events occurred. This number
+can include both libcurl internal descriptors as well as descriptors provided
+in *extra_fds*.
+
+The curl_multi_wakeup(3) function can be used from another thread to
+wake up this function and return faster. This is one of the details
+that makes this function different than curl_multi_wait(3) which cannot
+be woken up this way.
+
+If no extra file descriptors are provided and libcurl has no file descriptor
+to offer to wait for, this function instead waits during *timeout_ms*
+milliseconds (or shorter if an internal timer indicates so). This is the other
+detail that makes this function different than curl_multi_wait(3).
+
+This function is encouraged to be used instead of select(3) when using the
+multi interface to allow applications to easier circumvent the common problem
+with 1024 maximum file descriptors.
+
+# curl_waitfd
+
+~~~c
+struct curl_waitfd {
+ curl_socket_t fd;
+ short events;
+ short revents;
+};
+~~~
+
+## CURL_WAIT_POLLIN
+
+Bit flag to curl_waitfd.events indicating the socket should poll on read
+events such as new data received.
+
+## CURL_WAIT_POLLPRI
+
+Bit flag to curl_waitfd.events indicating the socket should poll on high
+priority read events such as out of band data.
+
+## CURL_WAIT_POLLOUT
+
+Bit flag to curl_waitfd.events indicating the socket should poll on write
+events such as the socket being clear to write without blocking.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *easy_handle;
+ CURLM *multi_handle;
+ int still_running = 0;
+
+ /* add the individual easy handle */
+ curl_multi_add_handle(multi_handle, easy_handle);
+
+ do {
+ CURLMcode mc;
+ int numfds;
+
+ mc = curl_multi_perform(multi_handle, &still_running);
+
+ if(mc == CURLM_OK) {
+ /* wait for activity or timeout */
+ mc = curl_multi_poll(multi_handle, NULL, 0, 1000, &numfds);
+ }
+
+ if(mc != CURLM_OK) {
+ fprintf(stderr, "curl_multi failed, code %d.\n", mc);
+ break;
+ }
+
+ } while(still_running);
+
+ curl_multi_remove_handle(multi_handle, easy_handle);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.66.0.
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code. See
+libcurl-errors(3)
diff --git a/docs/libcurl/curl_multi_remove_handle.3 b/docs/libcurl/curl_multi_remove_handle.3
deleted file mode 100644
index dccf75f92..000000000
--- a/docs/libcurl/curl_multi_remove_handle.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_remove_handle 3 "6 March 2002" "libcurl" "libcurl"
-.SH NAME
-curl_multi_remove_handle - remove an easy handle from a multi session
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURL *easy_handle);
-.fi
-.SH DESCRIPTION
-Removes a given \fIeasy_handle\fP from the \fImulti_handle\fP. This makes the
-specified easy handle be removed from this multi handle's control.
-
-When the easy handle has been removed from a multi stack, it is again
-perfectly legal to invoke \fIcurl_easy_perform(3)\fP on this easy handle.
-
-Removing an easy handle while being in use is perfectly legal and effectively
-halts the transfer in progress involving that easy handle. All other easy
-handles and transfers remain unaffected.
-
-It is fine to remove a handle at any time during a transfer, just not from
-within any libcurl callback function.
-
-Removing an easy handle from the multi handle before the corresponding
-transfer is complete might cause libcurl to close the connection - if the
-state of it and the internal protocol handler deem it necessary. Otherwise
-libcurl keeps the connection alive in the connection pool associated with the
-multi handle, ready to get reused for a future transfer using this multi
-handle.
-.SH EXAMPLE
-.nf
-/* when an easy handle has completed, remove it */
-msg = curl_multi_info_read(multi_handle, &queued);
-if(msg) {
- if(msg->msg == CURLMSG_DONE) {
- /* a transfer ended */
- fprintf(stderr, "Transfer completed\\n");
- curl_multi_remove_handle(multi_handle, msg->easy_handle);
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.9.6
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code.
-.SH "SEE ALSO"
-.BR curl_multi_add_handle (3),
-.BR curl_multi_cleanup (3),
-.BR curl_multi_init (3)
diff --git a/docs/libcurl/curl_multi_remove_handle.md b/docs/libcurl/curl_multi_remove_handle.md
new file mode 100644
index 000000000..bb8ee1c7d
--- /dev/null
+++ b/docs/libcurl/curl_multi_remove_handle.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_remove_handle
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_add_handle (3)
+ - curl_multi_cleanup (3)
+ - curl_multi_init (3)
+---
+
+# NAME
+
+curl_multi_remove_handle - remove an easy handle from a multi session
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURL *easy_handle);
+~~~
+
+# DESCRIPTION
+
+Removes a given *easy_handle* from the *multi_handle*. This makes the
+specified easy handle be removed from this multi handle's control.
+
+When the easy handle has been removed from a multi stack, it is again
+perfectly legal to invoke curl_easy_perform(3) on this easy handle.
+
+Removing an easy handle while being in use is perfectly legal and effectively
+halts the transfer in progress involving that easy handle. All other easy
+handles and transfers remain unaffected.
+
+It is fine to remove a handle at any time during a transfer, just not from
+within any libcurl callback function.
+
+Removing an easy handle from the multi handle before the corresponding
+transfer is complete might cause libcurl to close the connection - if the
+state of it and the internal protocol handler deem it necessary. Otherwise
+libcurl keeps the connection alive in the connection pool associated with the
+multi handle, ready to get reused for a future transfer using this multi
+handle.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *multi = curl_multi_init();
+ int queued = 0;
+
+ /* when an easy handle has completed, remove it */
+ CURLMsg *msg = curl_multi_info_read(multi, &queued);
+ if(msg) {
+ if(msg->msg == CURLMSG_DONE) {
+ /* a transfer ended */
+ fprintf(stderr, "Transfer completed\n");
+ curl_multi_remove_handle(multi, msg->easy_handle);
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.6
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code.
diff --git a/docs/libcurl/curl_multi_setopt.3 b/docs/libcurl/curl_multi_setopt.3
deleted file mode 100644
index f09765355..000000000
--- a/docs/libcurl/curl_multi_setopt.3
+++ /dev/null
@@ -1,91 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_setopt 3 "4 Nov 2014" "libcurl" "libcurl"
-.SH NAME
-curl_multi_setopt \- set options for a curl multi handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMoption option, param);
-.fi
-.SH DESCRIPTION
-\fIcurl_multi_setopt(3)\fP is used to tell a libcurl multi handle how to
-behave. By using the appropriate options to \fIcurl_multi_setopt(3)\fP, you
-can change libcurl's behavior when using that multi handle. All options are
-set with the \fIoption\fP followed by the parameter \fIparam\fP. That
-parameter can be a \fBlong\fP, a \fBfunction pointer\fP, an \fBobject
-pointer\fP or a \fBcurl_off_t\fP type, depending on what the specific option
-expects. Read this manual carefully as bad input values may cause libcurl to
-behave badly. You can only set one option in each function call.
-
-.SH OPTIONS
-.IP CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE
-See \fICURLMOPT_CHUNK_LENGTH_PENALTY_SIZE(3)\fP
-.IP CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE
-See \fICURLMOPT_CONTENT_LENGTH_PENALTY_SIZE(3)\fP
-.IP CURLMOPT_MAX_HOST_CONNECTIONS
-See \fICURLMOPT_MAX_HOST_CONNECTIONS(3)\fP
-.IP CURLMOPT_MAX_PIPELINE_LENGTH
-See \fICURLMOPT_MAX_PIPELINE_LENGTH(3)\fP
-.IP CURLMOPT_MAX_TOTAL_CONNECTIONS
-See \fICURLMOPT_MAX_TOTAL_CONNECTIONS(3)\fP
-.IP CURLMOPT_MAXCONNECTS
-See \fICURLMOPT_MAXCONNECTS(3)\fP
-.IP CURLMOPT_PIPELINING
-See \fICURLMOPT_PIPELINING(3)\fP
-.IP CURLMOPT_PIPELINING_SITE_BL
-See \fICURLMOPT_PIPELINING_SITE_BL(3)\fP
-.IP CURLMOPT_PIPELINING_SERVER_BL
-See \fICURLMOPT_PIPELINING_SERVER_BL(3)\fP
-.IP CURLMOPT_PUSHFUNCTION
-See \fICURLMOPT_PUSHFUNCTION(3)\fP
-.IP CURLMOPT_PUSHDATA
-See \fICURLMOPT_PUSHDATA(3)\fP
-.IP CURLMOPT_SOCKETFUNCTION
-See \fICURLMOPT_SOCKETFUNCTION(3)\fP
-.IP CURLMOPT_SOCKETDATA
-See \fICURLMOPT_SOCKETDATA(3)\fP
-.IP CURLMOPT_TIMERFUNCTION
-See \fICURLMOPT_TIMERFUNCTION(3)\fP
-.IP CURLMOPT_TIMERDATA
-See \fICURLMOPT_TIMERDATA(3)\fP
-.IP CURLMOPT_MAX_CONCURRENT_STREAMS
-See \fICURLMOPT_MAX_CONCURRENT_STREAMS(3)\fP
-.SH EXAMPLE
-.fi
- /* Limit the amount of simultaneous connections curl should allow: */
- curl_multi_setopt(handle, CURLMOPT_MAXCONNECTS, (long)MAX_PARALLEL);
-.nf
-.SH AVAILABILITY
-Added in 7.15.4
-.SH RETURN VALUE
-The standard CURLMcode for multi interface error codes. Note that it returns a
-CURLM_UNKNOWN_OPTION if you try setting an option that this version of libcurl
-does not know of.
-.SH "SEE ALSO"
-.BR curl_multi_cleanup (3),
-.BR curl_multi_info_read (3),
-.BR curl_multi_init (3),
-.BR curl_multi_socket (3)
diff --git a/docs/libcurl/curl_multi_setopt.md b/docs/libcurl/curl_multi_setopt.md
new file mode 100644
index 000000000..c0c8a3e6e
--- /dev/null
+++ b/docs/libcurl/curl_multi_setopt.md
@@ -0,0 +1,125 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_setopt
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_cleanup (3)
+ - curl_multi_info_read (3)
+ - curl_multi_init (3)
+ - curl_multi_socket (3)
+---
+
+# NAME
+
+curl_multi_setopt - set options for a curl multi handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMoption option, parameter);
+~~~
+
+# DESCRIPTION
+
+curl_multi_setopt(3) is used to tell a libcurl multi handle how to
+behave. By using the appropriate options to curl_multi_setopt(3), you
+can change libcurl's behavior when using that multi handle. All options are
+set with the *option* followed by the *parameter*. That parameter can
+be a **long**, a **function pointer**, an **object pointer** or a
+**curl_off_t** type, depending on what the specific option expects. Read
+this manual carefully as bad input values may cause libcurl to behave
+badly. You can only set one option in each function call.
+
+# OPTIONS
+
+## CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE
+
+See CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE(3)
+
+## CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE
+
+See CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE(3)
+
+## CURLMOPT_MAX_HOST_CONNECTIONS
+
+See CURLMOPT_MAX_HOST_CONNECTIONS(3)
+
+## CURLMOPT_MAX_PIPELINE_LENGTH
+
+See CURLMOPT_MAX_PIPELINE_LENGTH(3)
+
+## CURLMOPT_MAX_TOTAL_CONNECTIONS
+
+See CURLMOPT_MAX_TOTAL_CONNECTIONS(3)
+
+## CURLMOPT_MAXCONNECTS
+
+See CURLMOPT_MAXCONNECTS(3)
+
+## CURLMOPT_PIPELINING
+
+See CURLMOPT_PIPELINING(3)
+
+## CURLMOPT_PIPELINING_SITE_BL
+
+See CURLMOPT_PIPELINING_SITE_BL(3)
+
+## CURLMOPT_PIPELINING_SERVER_BL
+
+See CURLMOPT_PIPELINING_SERVER_BL(3)
+
+## CURLMOPT_PUSHFUNCTION
+
+See CURLMOPT_PUSHFUNCTION(3)
+
+## CURLMOPT_PUSHDATA
+
+See CURLMOPT_PUSHDATA(3)
+
+## CURLMOPT_SOCKETFUNCTION
+
+See CURLMOPT_SOCKETFUNCTION(3)
+
+## CURLMOPT_SOCKETDATA
+
+See CURLMOPT_SOCKETDATA(3)
+
+## CURLMOPT_TIMERFUNCTION
+
+See CURLMOPT_TIMERFUNCTION(3)
+
+## CURLMOPT_TIMERDATA
+
+See CURLMOPT_TIMERDATA(3)
+
+## CURLMOPT_MAX_CONCURRENT_STREAMS
+
+See CURLMOPT_MAX_CONCURRENT_STREAMS(3)
+
+# EXAMPLE
+
+~~~c
+
+#define MAX_PARALLEL 45
+
+int main(void)
+{
+ CURLM *multi;
+ /* Limit the amount of simultaneous connections curl should allow: */
+ curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)MAX_PARALLEL);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.4
+
+# RETURN VALUE
+
+The standard CURLMcode for multi interface error codes. Note that it returns a
+CURLM_UNKNOWN_OPTION if you try setting an option that this version of libcurl
+does not know of.
diff --git a/docs/libcurl/curl_multi_socket.3 b/docs/libcurl/curl_multi_socket.3
deleted file mode 100644
index 140776f3d..000000000
--- a/docs/libcurl/curl_multi_socket.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_socket 3 "9 Jul 2006" "libcurl" "libcurl"
-.SH NAME
-curl_multi_socket \- reads/writes available data
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t sockfd,
- int *running_handles);
-
-CURLMcode curl_multi_socket_all(CURLM *multi_handle,
- int *running_handles);
-.fi
-.SH DESCRIPTION
-These functions are deprecated. Do not use. See
-\fIcurl_multi_socket_action(3)\fP instead.
-
-At return, the integer \fBrunning_handles\fP points to contains the number of
-still running easy handles within the multi handle. When this number reaches
-zero, all transfers are complete/done. Note that when you call
-\fIcurl_multi_socket_action(3)\fP on a specific socket and the counter
-decreases by one, it DOES NOT necessarily mean that this exact socket/transfer
-is the one that completed. Use \fIcurl_multi_info_read(3)\fP to figure out
-which easy handle that completed.
-
-The \fIcurl_multi_socket_action(3)\fP functions inform the application about
-updates in the socket (file descriptor) status by doing none, one, or multiple
-calls to the socket callback function set with the
-\fICURLMOPT_SOCKETFUNCTION(3)\fP option to \fIcurl_multi_setopt(3)\fP. They
-update the status with changes since the previous time the callback was
-called.
-
-Get the timeout time by setting the \fICURLMOPT_TIMERFUNCTION(3)\fP option
-with \fIcurl_multi_setopt(3)\fP. Your application then gets called with
-information on how long to wait for socket actions at most before doing the
-timeout action: call the \fIcurl_multi_socket_action(3)\fP function with the
-\fBsockfd\fP argument set to CURL_SOCKET_TIMEOUT. You can also use the
-\fIcurl_multi_timeout(3)\fP function to poll the value at any given time, but
-for an event-based system using the callback is far better than relying on
-polling the timeout value.
-
-Usage of \fIcurl_multi_socket(3)\fP is deprecated, whereas the function is
-equivalent to \fIcurl_multi_socket_action(3)\fP with \fBev_bitmask\fP set to
-0.
-
-Force libcurl to (re-)check all its internal sockets and transfers instead of
-just a single one by calling \fIcurl_multi_socket_all(3)\fP. Note that there
-should not be any reason to use this function.
-.SH EXAMPLE
-.nf
-/* the event-library gets told when there activity on the socket 'fd',
- which we translate to a call to curl_multi_socket_action() */
-int running;
-rc = curl_multi_socket(multi_handle, fd, &running);
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.15.4, and is deemed stable since
-7.16.0.
-
-\fIcurl_multi_socket(3)\fP is deprecated, use
-\fIcurl_multi_socket_action(3)\fP instead!
-.SH "RETURN VALUE"
-CURLMcode type, general libcurl multi interface error code.
-
-The return code is for the whole multi stack. Problems still might have
-occurred on individual transfers even when one of these functions return OK.
-.SH "SEE ALSO"
-.BR curl_multi_cleanup (3),
-.BR curl_multi_init (3),
-.BR curl_multi_fdset (3),
-.BR curl_multi_info_read (3),
-.BR the hiperfifo.c example
diff --git a/docs/libcurl/curl_multi_socket.md b/docs/libcurl/curl_multi_socket.md
new file mode 100644
index 000000000..ff465c359
--- /dev/null
+++ b/docs/libcurl/curl_multi_socket.md
@@ -0,0 +1,95 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_socket
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_cleanup (3)
+ - curl_multi_fdset (3)
+ - curl_multi_info_read (3)
+ - curl_multi_init (3)
+ - the hiperfifo.c example
+---
+
+# NAME
+
+curl_multi_socket - reads/writes available data
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t sockfd,
+ int *running_handles);
+
+CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+ int *running_handles);
+~~~
+
+# DESCRIPTION
+
+These functions are deprecated. Do not use. See
+curl_multi_socket_action(3) instead.
+
+At return, the integer **running_handles** points to contains the number of
+still running easy handles within the multi handle. When this number reaches
+zero, all transfers are complete/done. Note that when you call
+curl_multi_socket_action(3) on a specific socket and the counter
+decreases by one, it DOES NOT necessarily mean that this exact socket/transfer
+is the one that completed. Use curl_multi_info_read(3) to figure out
+which easy handle that completed.
+
+The curl_multi_socket_action(3) functions inform the application about
+updates in the socket (file descriptor) status by doing none, one, or multiple
+calls to the socket callback function set with the
+CURLMOPT_SOCKETFUNCTION(3) option to curl_multi_setopt(3). They
+update the status with changes since the previous time the callback was
+called.
+
+Get the timeout time by setting the CURLMOPT_TIMERFUNCTION(3) option
+with curl_multi_setopt(3). Your application then gets called with
+information on how long to wait for socket actions at most before doing the
+timeout action: call the curl_multi_socket_action(3) function with the
+**sockfd** argument set to CURL_SOCKET_TIMEOUT. You can also use the
+curl_multi_timeout(3) function to poll the value at any given time, but
+for an event-based system using the callback is far better than relying on
+polling the timeout value.
+
+Usage of curl_multi_socket(3) is deprecated, whereas the function is
+equivalent to curl_multi_socket_action(3) with **ev_bitmask** set to
+0.
+
+Force libcurl to (re-)check all its internal sockets and transfers instead of
+just a single one by calling curl_multi_socket_all(3). Note that there
+should not be any reason to use this function.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* the event-library gets told when there activity on the socket 'fd',
+ which we translate to a call to curl_multi_socket_action() */
+ int running;
+ int rc;
+ int fd;
+ CURLM *multi;
+ rc = curl_multi_socket(multi, fd, &running);
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.15.4, and is deemed stable since
+7.16.0.
+
+curl_multi_socket(3) is deprecated, use
+curl_multi_socket_action(3) instead!
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code.
+
+The return code is for the whole multi stack. Problems still might have
+occurred on individual transfers even when one of these functions return OK.
diff --git a/docs/libcurl/curl_multi_socket_action.3 b/docs/libcurl/curl_multi_socket_action.3
deleted file mode 100644
index 265a9f85a..000000000
--- a/docs/libcurl/curl_multi_socket_action.3
+++ /dev/null
@@ -1,116 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_socket_action 3 "9 Jul 2006" "libcurl" "libcurl"
-.SH NAME
-curl_multi_socket_action \- reads/writes available data given an action
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_socket_action(CURLM *multi_handle,
- curl_socket_t sockfd,
- int ev_bitmask,
- int *running_handles);
-.fi
-.SH DESCRIPTION
-When the application has detected action on a socket handled by libcurl, it
-should call \fIcurl_multi_socket_action(3)\fP with the \fBsockfd\fP argument
-set to the socket with the action. When the events on a socket are known, they
-can be passed as an events bitmask \fBev_bitmask\fP by first setting
-\fBev_bitmask\fP to 0, and then adding using bitwise OR (|) any combination of
-events to be chosen from CURL_CSELECT_IN, CURL_CSELECT_OUT or
-CURL_CSELECT_ERR. When the events on a socket are unknown, pass 0 instead, and
-libcurl tests the descriptor internally. It is also permissible to pass
-CURL_SOCKET_TIMEOUT to the \fBsockfd\fP parameter in order to initiate the
-whole process or when a timeout occurs.
-
-At return, \fBrunning_handles\fP points to the number of running easy handles
-within the multi handle. When this number reaches zero, all transfers are
-complete/done. When you call \fIcurl_multi_socket_action(3)\fP on a specific
-socket and the counter decreases by one, it DOES NOT necessarily mean that
-this exact socket/transfer is the one that completed. Use
-\fIcurl_multi_info_read(3)\fP to figure out which easy handle that completed.
-
-The \fIcurl_multi_socket_action(3)\fP function informs the application about
-updates in the socket (file descriptor) status by doing none, one, or multiple
-calls to the socket callback function set with the
-\fICURLMOPT_SOCKETFUNCTION(3)\fP option to \fIcurl_multi_setopt(3)\fP. They
-update the status with changes since the previous time the callback was
-called.
-
-Get the timeout time by setting the \fICURLMOPT_TIMERFUNCTION(3)\fP option
-with \fIcurl_multi_setopt(3)\fP. Your application then gets called with
-information on how long to wait for socket actions at most before doing the
-timeout action: call the \fIcurl_multi_socket_action(3)\fP function with the
-\fBsockfd\fP argument set to CURL_SOCKET_TIMEOUT. You can also use the
-\fIcurl_multi_timeout(3)\fP function to poll the value at any given time, but
-for an event-based system using the callback is far better than relying on
-polling the timeout value.
-
-When this function returns error, the state of all transfers are uncertain and
-they cannot be continued. \fIcurl_multi_socket_action(3)\fP should not be
-called again on the same multi handle after an error has been returned, unless
-first removing all the handles and adding new ones.
-.SH "TYPICAL USAGE"
-1. Create a multi handle
-
-2. Set the socket callback with \fICURLMOPT_SOCKETFUNCTION(3)\fP
-
-3. Set the timeout callback with \fICURLMOPT_TIMERFUNCTION(3)\fP, to get to
-know what timeout value to use when waiting for socket activities.
-
-4. Add easy handles with curl_multi_add_handle()
-
-5. Provide some means to manage the sockets libcurl is using, so you can check
-them for activity. This can be done through your application code, or by way
-of an external library such as libevent or glib.
-
-6. Call curl_multi_socket_action(..., CURL_SOCKET_TIMEOUT, 0, ...)
-to kickstart everything. To get one or more callbacks called.
-
-7. Wait for activity on any of libcurl's sockets, use the timeout value your
-callback has been told.
-
-8, When activity is detected, call curl_multi_socket_action() for the
-socket(s) that got action. If no activity is detected and the timeout expires,
-call \fIcurl_multi_socket_action(3)\fP with \fICURL_SOCKET_TIMEOUT\fP.
-.SH EXAMPLE
-.nf
-/* the event-library gets told when there activity on the socket 'fd',
- which we translate to a call to curl_multi_socket_action() */
-int running;
-rc = curl_multi_socket_action(multi_handle, fd, EVENT,
- &running);
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.15.4, and is deemed stable since 7.16.0.
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code. See
-\fIlibcurl-errors(3)\fP
-.SH "SEE ALSO"
-.BR curl_multi_cleanup (3),
-.BR curl_multi_fdset (3),
-.BR curl_multi_info_read (3),
-.BR curl_multi_init (3),
-.BR the hiperfifo.c example
diff --git a/docs/libcurl/curl_multi_socket_action.md b/docs/libcurl/curl_multi_socket_action.md
new file mode 100644
index 000000000..8af17c83f
--- /dev/null
+++ b/docs/libcurl/curl_multi_socket_action.md
@@ -0,0 +1,120 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_socket_action
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_cleanup (3)
+ - curl_multi_fdset (3)
+ - curl_multi_info_read (3)
+ - curl_multi_init (3)
+ - the hiperfifo.c example
+---
+
+# NAME
+
+curl_multi_socket_action - reads/writes available data given an action
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_socket_action(CURLM *multi_handle,
+ curl_socket_t sockfd,
+ int ev_bitmask,
+ int *running_handles);
+~~~
+
+# DESCRIPTION
+
+When the application has detected action on a socket handled by libcurl, it
+should call curl_multi_socket_action(3) with the **sockfd** argument
+set to the socket with the action. When the events on a socket are known, they
+can be passed as an events bitmask **ev_bitmask** by first setting
+**ev_bitmask** to 0, and then adding using bitwise OR (|) any combination of
+events to be chosen from CURL_CSELECT_IN, CURL_CSELECT_OUT or
+CURL_CSELECT_ERR. When the events on a socket are unknown, pass 0 instead, and
+libcurl tests the descriptor internally. It is also permissible to pass
+CURL_SOCKET_TIMEOUT to the **sockfd** parameter in order to initiate the
+whole process or when a timeout occurs.
+
+At return, **running_handles** points to the number of running easy handles
+within the multi handle. When this number reaches zero, all transfers are
+complete/done. When you call curl_multi_socket_action(3) on a specific
+socket and the counter decreases by one, it DOES NOT necessarily mean that
+this exact socket/transfer is the one that completed. Use
+curl_multi_info_read(3) to figure out which easy handle that completed.
+
+The curl_multi_socket_action(3) function informs the application about
+updates in the socket (file descriptor) status by doing none, one, or multiple
+calls to the socket callback function set with the
+CURLMOPT_SOCKETFUNCTION(3) option to curl_multi_setopt(3). They
+update the status with changes since the previous time the callback was
+called.
+
+Get the timeout time by setting the CURLMOPT_TIMERFUNCTION(3) option
+with curl_multi_setopt(3). Your application then gets called with
+information on how long to wait for socket actions at most before doing the
+timeout action: call the curl_multi_socket_action(3) function with the
+**sockfd** argument set to CURL_SOCKET_TIMEOUT. You can also use the
+curl_multi_timeout(3) function to poll the value at any given time, but
+for an event-based system using the callback is far better than relying on
+polling the timeout value.
+
+When this function returns error, the state of all transfers are uncertain and
+they cannot be continued. curl_multi_socket_action(3) should not be
+called again on the same multi handle after an error has been returned, unless
+first removing all the handles and adding new ones.
+
+# TYPICAL USAGE
+
+1. Create a multi handle
+
+2. Set the socket callback with CURLMOPT_SOCKETFUNCTION(3)
+
+3. Set the timeout callback with CURLMOPT_TIMERFUNCTION(3), to get to
+know what timeout value to use when waiting for socket activities.
+
+4. Add easy handles with curl_multi_add_handle()
+
+5. Provide some means to manage the sockets libcurl is using, so you can check
+them for activity. This can be done through your application code, or by way
+of an external library such as libevent or glib.
+
+6. Call curl_multi_socket_action(..., CURL_SOCKET_TIMEOUT, 0, ...)
+to kickstart everything. To get one or more callbacks called.
+
+7. Wait for activity on any of libcurl's sockets, use the timeout value your
+callback has been told.
+
+8, When activity is detected, call curl_multi_socket_action() for the
+socket(s) that got action. If no activity is detected and the timeout expires,
+call curl_multi_socket_action(3) with *CURL_SOCKET_TIMEOUT*.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* the event-library gets told when there activity on the socket 'fd',
+ which we translate to a call to curl_multi_socket_action() */
+ int running;
+ CURLM *multi; /* the stack we work with */
+ int fd; /* the descriptor that had action */
+ int bitmask; /* what activity that happened */
+ CURLMcode mc = curl_multi_socket_action(multi, fd, bitmask, &running);
+ if(mc)
+ printf("error: %s\n", curl_multi_strerror(mc));
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.15.4, and is deemed stable since 7.16.0.
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code. See
+libcurl-errors(3)
diff --git a/docs/libcurl/curl_multi_socket_all.3 b/docs/libcurl/curl_multi_socket_all.3
deleted file mode 100644
index 428dd06f9..000000000
--- a/docs/libcurl/curl_multi_socket_all.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/curl_multi_socket.3
diff --git a/docs/libcurl/curl_multi_socket_all.md b/docs/libcurl/curl_multi_socket_all.md
new file mode 100644
index 000000000..ff465c359
--- /dev/null
+++ b/docs/libcurl/curl_multi_socket_all.md
@@ -0,0 +1,95 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_socket
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_cleanup (3)
+ - curl_multi_fdset (3)
+ - curl_multi_info_read (3)
+ - curl_multi_init (3)
+ - the hiperfifo.c example
+---
+
+# NAME
+
+curl_multi_socket - reads/writes available data
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t sockfd,
+ int *running_handles);
+
+CURLMcode curl_multi_socket_all(CURLM *multi_handle,
+ int *running_handles);
+~~~
+
+# DESCRIPTION
+
+These functions are deprecated. Do not use. See
+curl_multi_socket_action(3) instead.
+
+At return, the integer **running_handles** points to contains the number of
+still running easy handles within the multi handle. When this number reaches
+zero, all transfers are complete/done. Note that when you call
+curl_multi_socket_action(3) on a specific socket and the counter
+decreases by one, it DOES NOT necessarily mean that this exact socket/transfer
+is the one that completed. Use curl_multi_info_read(3) to figure out
+which easy handle that completed.
+
+The curl_multi_socket_action(3) functions inform the application about
+updates in the socket (file descriptor) status by doing none, one, or multiple
+calls to the socket callback function set with the
+CURLMOPT_SOCKETFUNCTION(3) option to curl_multi_setopt(3). They
+update the status with changes since the previous time the callback was
+called.
+
+Get the timeout time by setting the CURLMOPT_TIMERFUNCTION(3) option
+with curl_multi_setopt(3). Your application then gets called with
+information on how long to wait for socket actions at most before doing the
+timeout action: call the curl_multi_socket_action(3) function with the
+**sockfd** argument set to CURL_SOCKET_TIMEOUT. You can also use the
+curl_multi_timeout(3) function to poll the value at any given time, but
+for an event-based system using the callback is far better than relying on
+polling the timeout value.
+
+Usage of curl_multi_socket(3) is deprecated, whereas the function is
+equivalent to curl_multi_socket_action(3) with **ev_bitmask** set to
+0.
+
+Force libcurl to (re-)check all its internal sockets and transfers instead of
+just a single one by calling curl_multi_socket_all(3). Note that there
+should not be any reason to use this function.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ /* the event-library gets told when there activity on the socket 'fd',
+ which we translate to a call to curl_multi_socket_action() */
+ int running;
+ int rc;
+ int fd;
+ CURLM *multi;
+ rc = curl_multi_socket(multi, fd, &running);
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.15.4, and is deemed stable since
+7.16.0.
+
+curl_multi_socket(3) is deprecated, use
+curl_multi_socket_action(3) instead!
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code.
+
+The return code is for the whole multi stack. Problems still might have
+occurred on individual transfers even when one of these functions return OK.
diff --git a/docs/libcurl/curl_multi_strerror.3 b/docs/libcurl/curl_multi_strerror.3
deleted file mode 100644
index 7dd7e8892..000000000
--- a/docs/libcurl/curl_multi_strerror.3
+++ /dev/null
@@ -1,50 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_strerror 3 "26 Apr 2004" "libcurl" "libcurl"
-.SH NAME
-curl_multi_strerror - return string describing error code
-.SH SYNOPSIS
-.nf
-.B #include <curl/curl.h>
-.BI "const char *curl_multi_strerror(CURLMcode " errornum ");"
-.SH DESCRIPTION
-This function returns a string describing the \fICURLMcode\fP error code
-passed in the argument \fIerrornum\fP.
-.SH EXAMPLE
-.nf
-int still_running;
-
-CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
-if(mc)
- printf("error: %s\\n", curl_multi_strerror(mc));
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.12.0
-.SH RETURN VALUE
-A pointer to a null-terminated string.
-.SH "SEE ALSO"
-.BR curl_easy_strerror (3),
-.BR curl_share_strerror (3),
-.BR curl_url_strerror (3),
-.BR libcurl-errors (3)
diff --git a/docs/libcurl/curl_multi_strerror.md b/docs/libcurl/curl_multi_strerror.md
new file mode 100644
index 000000000..5429e0e34
--- /dev/null
+++ b/docs/libcurl/curl_multi_strerror.md
@@ -0,0 +1,51 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_strerror
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_strerror (3)
+ - curl_share_strerror (3)
+ - curl_url_strerror (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+curl_multi_strerror - return string describing error code
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const char *curl_multi_strerror(CURLMcode errornum);
+~~~
+
+# DESCRIPTION
+
+This function returns a string describing the *CURLMcode* error code
+passed in the argument *errornum*.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ int still_running;
+ CURLM *multi = curl_multi_init();
+
+ CURLMcode mc = curl_multi_perform(multi, &still_running);
+ if(mc)
+ printf("error: %s\n", curl_multi_strerror(mc));
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.12.0
+
+# RETURN VALUE
+
+A pointer to a null-terminated string.
diff --git a/docs/libcurl/curl_multi_timeout.3 b/docs/libcurl/curl_multi_timeout.3
deleted file mode 100644
index 23abe9491..000000000
--- a/docs/libcurl/curl_multi_timeout.3
+++ /dev/null
@@ -1,85 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_timeout 3 "2 Jan 2006" "libcurl" "libcurl"
-.SH NAME
-curl_multi_timeout \- how long to wait for action before proceeding
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_timeout(CURLM *multi_handle, long *timeout);
-.fi
-.SH DESCRIPTION
-
-An application using the libcurl multi interface should call
-\fIcurl_multi_timeout(3)\fP to figure out how long it should wait for socket
-actions \- at most \- before proceeding.
-
-Proceeding means either doing the socket-style timeout action: call the
-\fIcurl_multi_socket_action(3)\fP function with the \fBsockfd\fP argument set
-to CURL_SOCKET_TIMEOUT, or call \fIcurl_multi_perform(3)\fP if you are using
-the simpler and older multi interface approach.
-
-The timeout value returned in the long \fBtimeout\fP points to, is in number
-of milliseconds at this moment. If 0, it means you should proceed immediately
-without waiting for anything. If it returns -1, there is no timeout at all set.
-
-An application that uses the multi_socket API SHOULD NOT use this function,
-but SHOULD instead use the \fICURLMOPT_TIMERFUNCTION(3)\fP option for proper
-and desired behavior.
-
-Note: if libcurl returns a -1 timeout here, it just means that libcurl
-currently has no stored timeout value. You must not wait too long (more than a
-few seconds perhaps) before you call \fIcurl_multi_perform(3)\fP again.
-.SH EXAMPLE
-.nf
-struct timeval timeout;
-long timeo;
-
-curl_multi_timeout(multi_handle, &timeo);
-if(timeo < 0)
- /* no set timeout, use a default */
- timeo = 980;
-
-timeout.tv_sec = timeo / 1000;
-timeout.tv_usec = (timeo % 1000) * 1000;
-
-/* wait for activities no longer than the set timeout */
-select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
-.fi
-.SH TYPICAL USAGE
-Call \fIcurl_multi_timeout(3)\fP, then wait for action on the sockets. Figure
-out which sockets to wait for by calling \fIcurl_multi_fdset(3)\fP.
-
-When there is activity or timeout, call \fIcurl_multi_perform(3)\fP and then
-loop - until all transfers are complete.
-.SH AVAILABILITY
-This function was added in libcurl 7.15.4.
-.SH RETURN VALUE
-The standard CURLMcode for multi interface error codes.
-.SH "SEE ALSO"
-.BR curl_multi_fdset (3),
-.BR curl_multi_info_read (3),
-.BR curl_multi_setopt (3),
-.BR curl_multi_socket (3)
diff --git a/docs/libcurl/curl_multi_timeout.md b/docs/libcurl/curl_multi_timeout.md
new file mode 100644
index 000000000..83bad3845
--- /dev/null
+++ b/docs/libcurl/curl_multi_timeout.md
@@ -0,0 +1,89 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_timeout
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_fdset (3)
+ - curl_multi_info_read (3)
+ - curl_multi_setopt (3)
+ - curl_multi_socket (3)
+---
+
+# NAME
+
+curl_multi_timeout - how long to wait for action before proceeding
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_timeout(CURLM *multi_handle, long *timeout);
+~~~
+
+# DESCRIPTION
+
+An application using the libcurl multi interface should call
+curl_multi_timeout(3) to figure out how long it should wait for socket
+actions - at most - before proceeding.
+
+Proceeding means either doing the socket-style timeout action: call the
+curl_multi_socket_action(3) function with the **sockfd** argument set
+to CURL_SOCKET_TIMEOUT, or call curl_multi_perform(3) if you are using
+the simpler and older multi interface approach.
+
+The timeout value returned in the long **timeout** points to, is in number
+of milliseconds at this moment. If 0, it means you should proceed immediately
+without waiting for anything. If it returns -1, there is no timeout at all set.
+
+An application that uses the *multi_socket* API should not use this function.
+It should instead use the CURLMOPT_TIMERFUNCTION(3) option for proper and
+desired behavior.
+
+Note: if libcurl returns a -1 timeout here, it just means that libcurl
+currently has no stored timeout value. You must not wait too long (more than a
+few seconds perhaps) before you call curl_multi_perform(3) again.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct timeval timeout;
+ long timeo;
+ fd_set fdread;
+ fd_set fdwrite;
+ fd_set fdexcep;
+ int maxfd;
+ CURLM *multi = curl_multi_init();
+
+ curl_multi_timeout(multi, &timeo);
+ if(timeo < 0)
+ /* no set timeout, use a default */
+ timeo = 980;
+
+ timeout.tv_sec = timeo / 1000;
+ timeout.tv_usec = (timeo % 1000) * 1000;
+
+ /* wait for activities no longer than the set timeout */
+ select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+}
+~~~
+
+# TYPICAL USAGE
+
+Call curl_multi_timeout(3), then wait for action on the sockets. Figure
+out which sockets to wait for by calling curl_multi_fdset(3).
+
+When there is activity or timeout, call curl_multi_perform(3) and then
+loop - until all transfers are complete.
+
+# AVAILABILITY
+
+This function was added in libcurl 7.15.4.
+
+# RETURN VALUE
+
+The standard CURLMcode for multi interface error codes.
diff --git a/docs/libcurl/curl_multi_wait.3 b/docs/libcurl/curl_multi_wait.3
deleted file mode 100644
index 565fdb8de..000000000
--- a/docs/libcurl/curl_multi_wait.3
+++ /dev/null
@@ -1,128 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_wait 3 "12 Jul 2012" "libcurl" "libcurl"
-.SH NAME
-curl_multi_wait - polls on all easy handles in a multi handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_wait(CURLM *multi_handle,
- struct curl_waitfd extra_fds[],
- unsigned int extra_nfds,
- int timeout_ms,
- int *numfds);
-.ad
-.SH DESCRIPTION
-\fIcurl_multi_wait(3)\fP polls all file descriptors used by the curl easy
-handles contained in the given multi handle set. It blocks until activity is
-detected on at least one of the handles or \fItimeout_ms\fP has passed.
-Alternatively, if the multi handle has a pending internal timeout that has a
-shorter expiry time than \fItimeout_ms\fP, that shorter time is be used
-instead to make sure timeout accuracy is reasonably kept.
-
-The calling application may pass additional \fIcurl_waitfd\fP structures which
-are similar to \fIpoll(2)\fP's \fIpollfd\fP structure to be waited on in the
-same call.
-
-On completion, if \fInumfds\fP is non-NULL, it gets populated with the total
-number of file descriptors on which interesting events occurred. This number
-can include both libcurl internal descriptors as well as descriptors provided
-in \fIextra_fds\fP.
-
-If no extra file descriptors are provided and libcurl has no file descriptor
-to offer to wait for, this function returns immediately. (Consider using
-\fIcurl_multi_poll(3)\fP to avoid this behavior.)
-
-This function is encouraged to be used instead of select(3) when using the
-multi interface to allow applications to easier circumvent the common problem
-with 1024 maximum file descriptors.
-.SH curl_waitfd
-.nf
-struct curl_waitfd {
- curl_socket_t fd;
- short events;
- short revents;
-};
-.fi
-.IP CURL_WAIT_POLLIN
-Bit flag to \fIcurl_waitfd.events\fP indicating the socket should poll on read
-events such as new data received.
-.IP CURL_WAIT_POLLPRI
-Bit flag to \fIcurl_waitfd.events\fP indicating the socket should poll on high
-priority read events such as out of band data.
-.IP CURL_WAIT_POLLOUT
-Bit flag to \fIcurl_waitfd.events\fP indicating the socket should poll on
-write events such as the socket being clear to write without blocking.
-.SH EXAMPLE
-.nf
-CURL *easy_handle;
-CURLM *multi_handle;
-
-/* add the individual easy handle */
-curl_multi_add_handle(multi_handle, easy_handle);
-
-do {
- CURLMcode mc;
- int numfds;
-
- mc = curl_multi_perform(multi_handle, &still_running);
-
- if(mc == CURLM_OK ) {
- /* wait for activity, timeout or "nothing" */
- mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
- }
-
- if(mc != CURLM_OK) {
- fprintf(stderr, "curl_multi failed, code %d.\\n", mc);
- break;
- }
-
- /* 'numfds' being zero means either a timeout or no file descriptors to
- wait for. Try timeout on first occurrence, then assume no file
- descriptors and no file descriptors to wait for means wait for 100
- milliseconds. */
-
- if(!numfds) {
- repeats++; /* count number of repeated zero numfds */
- if(repeats > 1) {
- WAITMS(100); /* sleep 100 milliseconds */
- }
- }
- else
- repeats = 0;
-
-} while(still_running);
-
-curl_multi_remove_handle(multi_handle, easy_handle);
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.28.0.
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code. See
-\fIlibcurl-errors(3)\fP
-.SH "SEE ALSO"
-.BR curl_multi_fdset (3),
-.BR curl_multi_perform (3),
-.BR curl_multi_poll (3)
diff --git a/docs/libcurl/curl_multi_wait.md b/docs/libcurl/curl_multi_wait.md
new file mode 100644
index 000000000..094ace386
--- /dev/null
+++ b/docs/libcurl/curl_multi_wait.md
@@ -0,0 +1,121 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_wait
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_fdset (3)
+ - curl_multi_perform (3)
+ - curl_multi_poll (3)
+---
+
+# NAME
+
+curl_multi_wait - polls on all easy handles in a multi handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_wait(CURLM *multi_handle,
+ struct curl_waitfd extra_fds[],
+ unsigned int extra_nfds,
+ int timeout_ms,
+ int *numfds);
+~~~
+
+# DESCRIPTION
+
+curl_multi_wait(3) polls all file descriptors used by the curl easy
+handles contained in the given multi handle set. It blocks until activity is
+detected on at least one of the handles or *timeout_ms* has passed.
+Alternatively, if the multi handle has a pending internal timeout that has a
+shorter expiry time than *timeout_ms*, that shorter time is be used
+instead to make sure timeout accuracy is reasonably kept.
+
+The calling application may pass additional *curl_waitfd* structures which
+are similar to *poll(2)*'s *pollfd* structure to be waited on in the
+same call.
+
+On completion, if *numfds* is non-NULL, it gets populated with the total
+number of file descriptors on which interesting events occurred. This number
+can include both libcurl internal descriptors as well as descriptors provided
+in *extra_fds*.
+
+If no extra file descriptors are provided and libcurl has no file descriptor
+to offer to wait for, this function returns immediately. (Consider using
+curl_multi_poll(3) to avoid this behavior.)
+
+This function is encouraged to be used instead of select(3) when using the
+multi interface to allow applications to easier circumvent the common problem
+with 1024 maximum file descriptors.
+
+# curl_waitfd
+
+~~~c
+struct curl_waitfd {
+ curl_socket_t fd;
+ short events;
+ short revents;
+};
+~~~
+
+## CURL_WAIT_POLLIN
+
+Bit flag to *curl_waitfd.events* indicating the socket should poll on read
+events such as new data received.
+
+## CURL_WAIT_POLLPRI
+
+Bit flag to *curl_waitfd.events* indicating the socket should poll on high
+priority read events such as out of band data.
+
+## CURL_WAIT_POLLOUT
+
+Bit flag to *curl_waitfd.events* indicating the socket should poll on
+write events such as the socket being clear to write without blocking.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *easy;
+ CURLM *multi = curl_multi_init();
+ int still_running;
+
+ /* add the individual easy handle */
+ curl_multi_add_handle(multi, easy);
+
+ do {
+ CURLMcode mc;
+ int numfds;
+
+ mc = curl_multi_perform(multi, &still_running);
+
+ if(mc == CURLM_OK) {
+ /* wait for activity, timeout or "nothing" */
+ mc = curl_multi_wait(multi, NULL, 0, 1000, &numfds);
+ }
+
+ if(mc != CURLM_OK) {
+ fprintf(stderr, "curl_multi failed, code %d.\n", mc);
+ break;
+ }
+
+ } while(still_running);
+
+ curl_multi_remove_handle(multi, easy);
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.28.0.
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code. See
+libcurl-errors(3)
diff --git a/docs/libcurl/curl_multi_wakeup.3 b/docs/libcurl/curl_multi_wakeup.3
deleted file mode 100644
index c4a71b678..000000000
--- a/docs/libcurl/curl_multi_wakeup.3
+++ /dev/null
@@ -1,89 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_multi_wakeup 3 "17 Nov 2019" "libcurl" "libcurl"
-.SH NAME
-curl_multi_wakeup - wakes up a sleeping curl_multi_poll call
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_wakeup(CURLM *multi_handle);
-.fi
-.SH DESCRIPTION
-This function can be called from any thread and it wakes up a sleeping
-\fIcurl_multi_poll(3)\fP call that is currently (or is about to be) waiting
-for activity or a timeout.
-
-If the function is called when there is no \fIcurl_multi_poll(3)\fP call, it
-causes the next call to return immediately.
-
-Calling this function only guarantees to wake up the current (or the next if
-there is no current) \fIcurl_multi_poll(3)\fP call, which means it is possible
-that multiple calls to this function wake up the same waiting operation.
-
-This function has no effect on \fIcurl_multi_wait(3)\fP calls.
-.SH EXAMPLE
-.nf
-CURL *easy_handle;
-CURLM *multi_handle;
-
-/* add the individual easy handle */
-curl_multi_add_handle(multi_handle, easy_handle);
-
-/* this is thread 1 */
-do {
- CURLMcode mc;
- int numfds;
-
- mc = curl_multi_perform(multi_handle, &still_running);
-
- if(mc == CURLM_OK) {
- /* wait for activity, timeout or wakeup */
- mc = curl_multi_poll(multi_handle, NULL, 0, 10000, &numfds);
- }
-
- if(time_to_die())
- exit(1);
-
-} while(still_running);
-
-curl_multi_remove_handle(multi_handle, easy_handle);
-
-/* this is thread 2 */
-
-if(something makes us decide to stop thread 1) {
-
- set_something_to_signal_thread_1_to_exit();
-
- curl_multi_wakeup(multi_handle);
-}
-
-.fi
-.SH AVAILABILITY
-Added in 7.68.0
-.SH RETURN VALUE
-CURLMcode type, general libcurl multi interface error code.
-.SH "SEE ALSO"
-.BR curl_multi_poll (3),
-.BR curl_multi_wait (3)
diff --git a/docs/libcurl/curl_multi_wakeup.md b/docs/libcurl/curl_multi_wakeup.md
new file mode 100644
index 000000000..f6200c41e
--- /dev/null
+++ b/docs/libcurl/curl_multi_wakeup.md
@@ -0,0 +1,91 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_multi_wakeup
+Section: 3
+Source: libcurl
+See-also:
+ - curl_multi_poll (3)
+ - curl_multi_wait (3)
+---
+
+# NAME
+
+curl_multi_wakeup - wakes up a sleeping curl_multi_poll call
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_wakeup(CURLM *multi_handle);
+~~~
+
+# DESCRIPTION
+
+This function can be called from any thread and it wakes up a sleeping
+curl_multi_poll(3) call that is currently (or is about to be) waiting
+for activity or a timeout.
+
+If the function is called when there is no curl_multi_poll(3) call, it
+causes the next call to return immediately.
+
+Calling this function only guarantees to wake up the current (or the next if
+there is no current) curl_multi_poll(3) call, which means it is possible
+that multiple calls to this function wake up the same waiting operation.
+
+This function has no effect on curl_multi_wait(3) calls.
+
+# EXAMPLE
+
+~~~c
+extern int time_to_die(void);
+extern int set_something_to_signal_thread_1_to_exit(void);
+extern int decide_to_stop_thread1();
+
+int main(void)
+{
+ CURL *easy;
+ CURLM *multi;
+ int still_running;
+
+ /* add the individual easy handle */
+ curl_multi_add_handle(multi, easy);
+
+ /* this is thread 1 */
+ do {
+ CURLMcode mc;
+ int numfds;
+
+ mc = curl_multi_perform(multi, &still_running);
+
+ if(mc == CURLM_OK) {
+ /* wait for activity, timeout or wakeup */
+ mc = curl_multi_poll(multi, NULL, 0, 10000, &numfds);
+ }
+
+ if(time_to_die())
+ return 1;
+
+ } while(still_running);
+
+ curl_multi_remove_handle(multi, easy);
+
+ /* this is thread 2 */
+
+ if(decide_to_stop_thread1()) {
+
+ set_something_to_signal_thread_1_to_exit();
+
+ curl_multi_wakeup(multi);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.68.0
+
+# RETURN VALUE
+
+CURLMcode type, general libcurl multi interface error code.
diff --git a/docs/libcurl/curl_pushheader_byname.3 b/docs/libcurl/curl_pushheader_byname.3
deleted file mode 100644
index 4b0aff7b6..000000000
--- a/docs/libcurl/curl_pushheader_byname.3
+++ /dev/null
@@ -1,81 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_pushheader_byname 3 "9 Jun 2023" "libcurl" "libcurl"
-.SH NAME
-curl_pushheader_byname - get a push header by name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_pushheader_byname(struct curl_pushheaders *h, const char *name);
-.fi
-.SH DESCRIPTION
-This is a function that is only functional within a
-\fICURLMOPT_PUSHFUNCTION(3)\fP callback. It makes no sense to try to use it
-elsewhere and it has no function then.
-
-It returns the value for the given header field name (or NULL) for the
-incoming server push request. This is a shortcut so that the application does
-not have to loop through all headers to find the one it is interested in. The
-data this function points to is freed when this callback returns. If more than
-one header field use the same name, this returns only the first one.
-
-.SH EXAMPLE
-.nf
-int curl_push_callback(CURL *parent,
- CURL *easy,
- size_t num_headers,
- struct curl_pushheaders *headers,
- void *clientp)
-{
- char *headp;
- int *transfers = (int *)clientp;
- FILE *out;
- headp = curl_pushheader_byname(headers, ":path");
- if(headp && !strncmp(headp, "/push-", 6)) {
- fprintf(stderr, "The PATH is %s\\n", headp);
-
- /* save the push here */
- out = fopen("pushed-stream", "wb");
-
- /* write to this file */
- curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
-
- (*transfers)++; /* one more */
-
- return CURL_PUSH_OK;
- }
- return CURL_PUSH_DENY;
-}
-
-curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, curl_push_callback);
-curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &counter);
-.fi
-.SH AVAILABILITY
-Added in 7.44.0
-.SH RETURN VALUE
-Returns a pointer to the header field content or NULL.
-.SH "SEE ALSO"
-.BR CURLMOPT_PUSHFUNCTION (3),
-.BR curl_pushheader_bynum (3)
diff --git a/docs/libcurl/curl_pushheader_byname.md b/docs/libcurl/curl_pushheader_byname.md
new file mode 100644
index 000000000..ecb031f9e
--- /dev/null
+++ b/docs/libcurl/curl_pushheader_byname.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_pushheader_byname
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PUSHFUNCTION (3)
+ - curl_pushheader_bynum (3)
+---
+
+# NAME
+
+curl_pushheader_byname - get a push header by name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_pushheader_byname(struct curl_pushheaders *h, const char *name);
+~~~
+
+# DESCRIPTION
+
+This is a function that is only functional within a
+CURLMOPT_PUSHFUNCTION(3) callback. It makes no sense to try to use it
+elsewhere and it has no function then.
+
+It returns the value for the given header field name (or NULL) for the
+incoming server push request. This is a shortcut so that the application does
+not have to loop through all headers to find the one it is interested in. The
+data this function points to is freed when this callback returns. If more than
+one header field use the same name, this returns only the first one.
+
+# EXAMPLE
+
+~~~c
+#include <string.h> /* for strncmp */
+
+static int push_cb(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *clientp)
+{
+ char *headp;
+ int *transfers = (int *)clientp;
+ FILE *out;
+ headp = curl_pushheader_byname(headers, ":path");
+ if(headp && !strncmp(headp, "/push-", 6)) {
+ fprintf(stderr, "The PATH is %s\n", headp);
+
+ /* save the push here */
+ out = fopen("pushed-stream", "wb");
+
+ /* write to this file */
+ curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
+
+ (*transfers)++; /* one more */
+
+ return CURL_PUSH_OK;
+ }
+ return CURL_PUSH_DENY;
+}
+
+int main(void)
+{
+ int counter;
+ CURLM *multi = curl_multi_init();
+ curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, push_cb);
+ curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &counter);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.44.0
+
+# RETURN VALUE
+
+Returns a pointer to the header field content or NULL.
diff --git a/docs/libcurl/curl_pushheader_bynum.3 b/docs/libcurl/curl_pushheader_bynum.3
deleted file mode 100644
index 491c00432..000000000
--- a/docs/libcurl/curl_pushheader_bynum.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_pushheader_bynum 3 "9 Jun 2023" "libcurl" "libcurl"
-.SH NAME
-curl_pushheader_bynum - get a push header by index
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num);
-.fi
-.SH DESCRIPTION
-This is a function that is only functional within a
-\fICURLMOPT_PUSHFUNCTION(3)\fP callback. It makes no sense to try to use it
-elsewhere and it has no function then.
-
-It returns the value for the header field at the given index \fBnum\fP, for
-the incoming server push request or NULL. The data pointed to is freed by
-libcurl when this callback returns. The returned pointer points to a
-"name:value" string that gets freed when this callback returns.
-
-.SH EXAMPLE
-.nf
-/* output all the incoming push request headers */
-int curl_push_callback(CURL *parent,
- CURL *easy,
- size_t num_headers,
- struct curl_pushheaders *headers,
- void *clientp)
-{
- sizt_t i = 0;
- char *field;
- do {
- field = curl_pushheader_bynum(headers, i);
- if(field)
- fprintf(stderr, "Push header: %s\\n", field);
- i++;
- } while(field);
- return CURL_PUSH_OK; /* permission granted */
-}
-
-curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, curl_push_callback);
-.fi
-.SH AVAILABILITY
-Added in 7.44.0
-.SH RETURN VALUE
-Returns a pointer to the header field content or NULL.
-.SH "SEE ALSO"
-.BR CURLMOPT_PUSHFUNCTION (3),
-.BR curl_pushheader_byname (3)
diff --git a/docs/libcurl/curl_pushheader_bynum.md b/docs/libcurl/curl_pushheader_bynum.md
new file mode 100644
index 000000000..537f06b1c
--- /dev/null
+++ b/docs/libcurl/curl_pushheader_bynum.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_pushheader_bynum
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PUSHFUNCTION (3)
+ - curl_pushheader_byname (3)
+---
+
+# NAME
+
+curl_pushheader_bynum - get a push header by index
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num);
+~~~
+
+# DESCRIPTION
+
+This is a function that is only functional within a
+CURLMOPT_PUSHFUNCTION(3) callback. It makes no sense to try to use it
+elsewhere and it has no function then.
+
+It returns the value for the header field at the given index **num**, for
+the incoming server push request or NULL. The data pointed to is freed by
+libcurl when this callback returns. The returned pointer points to a
+"name:value" string that gets freed when this callback returns.
+
+# EXAMPLE
+
+~~~c
+/* output all the incoming push request headers */
+static int push_cb(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *clientp)
+{
+ int i = 0;
+ char *field;
+ do {
+ field = curl_pushheader_bynum(headers, i);
+ if(field)
+ fprintf(stderr, "Push header: %s\n", field);
+ i++;
+ } while(field);
+ return CURL_PUSH_OK; /* permission granted */
+}
+
+int main(void)
+{
+ CURLM *multi = curl_multi_init();
+ curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, push_cb);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.44.0
+
+# RETURN VALUE
+
+Returns a pointer to the header field content or NULL.
diff --git a/docs/libcurl/curl_share_cleanup.3 b/docs/libcurl/curl_share_cleanup.3
deleted file mode 100644
index 93f098e2a..000000000
--- a/docs/libcurl/curl_share_cleanup.3
+++ /dev/null
@@ -1,56 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_share_cleanup 3 "8 Aug 2003" "libcurl" "libcurl"
-.SH NAME
-curl_share_cleanup - Clean up a shared object
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLSHcode curl_share_cleanup(CURLSH *share_handle);
-.fi
-.SH DESCRIPTION
-This function deletes a shared object. The share handle cannot be used anymore
-when this function has been called.
-
-Passing in a NULL pointer in \fIshare_handle\fP makes this function return
-immediately with no action.
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
- /* use the share, then ... */
- curl_share_cleanup(share);
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-CURLSHE_OK (zero) means that the option was set properly, non-zero means an
-error occurred as \fI<curl/curl.h>\fP defines. See the \fIlibcurl-errors(3)\fP
-man page for the full list with descriptions. If an error occurs, then the
-share object is not deleted.
-.SH "SEE ALSO"
-.BR curl_share_init (3),
-.BR curl_share_setopt (3)
diff --git a/docs/libcurl/curl_share_cleanup.md b/docs/libcurl/curl_share_cleanup.md
new file mode 100644
index 000000000..59126a145
--- /dev/null
+++ b/docs/libcurl/curl_share_cleanup.md
@@ -0,0 +1,54 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_share_cleanup
+Section: 3
+Source: libcurl
+See-also:
+ - curl_share_init (3)
+ - curl_share_setopt (3)
+---
+
+# NAME
+
+curl_share_cleanup - Clean up a shared object
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLSHcode curl_share_cleanup(CURLSH *share_handle);
+~~~
+
+# DESCRIPTION
+
+This function deletes a shared object. The share handle cannot be used anymore
+when this function has been called.
+
+Passing in a NULL pointer in *share_handle* makes this function return
+immediately with no action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
+ /* use the share, then ... */
+ curl_share_cleanup(share);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+CURLSHE_OK (zero) means that the option was set properly, non-zero means an
+error occurred as *<curl/curl.h>* defines. See the libcurl-errors(3)
+man page for the full list with descriptions. If an error occurs, then the
+share object is not deleted.
diff --git a/docs/libcurl/curl_share_init.3 b/docs/libcurl/curl_share_init.3
deleted file mode 100644
index f414a14f3..000000000
--- a/docs/libcurl/curl_share_init.3
+++ /dev/null
@@ -1,58 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_share_init 3 "Aug 3, 2003" "libcurl" "libcurl"
-.SH NAME
-curl_share_init - Create a shared object
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLSH *curl_share_init();
-.fi
-.SH DESCRIPTION
-This function returns a pointer to a \fICURLSH\fP handle to be used as input
-to all the other share-functions, sometimes referred to as a share handle in
-some places in the documentation. This init call MUST have a corresponding
-call to \fIcurl_share_cleanup(3)\fP when all operations using the share are
-complete.
-
-This \fIshare handle\fP is what you pass to curl using the
-\fICURLOPT_SHARE(3)\fP option with \fIcurl_easy_setopt(3)\fP, to make that
-specific curl handle use the data in this share.
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-If this function returns NULL, something went wrong (out of memory, etc.)
-and therefore the share object was not created.
-.SH "SEE ALSO"
-.BR curl_share_cleanup (3),
-.BR curl_share_setopt (3)
diff --git a/docs/libcurl/curl_share_init.md b/docs/libcurl/curl_share_init.md
new file mode 100644
index 000000000..553710727
--- /dev/null
+++ b/docs/libcurl/curl_share_init.md
@@ -0,0 +1,56 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_share_init
+Section: 3
+Source: libcurl
+See-also:
+ - curl_share_cleanup (3)
+ - curl_share_setopt (3)
+---
+
+# NAME
+
+curl_share_init - Create a shared object
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLSH *curl_share_init();
+~~~
+
+# DESCRIPTION
+
+This function returns a pointer to a *CURLSH* handle to be used as input
+to all the other share-functions, sometimes referred to as a share handle in
+some places in the documentation. This init call MUST have a corresponding
+call to curl_share_cleanup(3) when all operations using the share are
+complete.
+
+This *share handle* is what you pass to curl using the
+CURLOPT_SHARE(3) option with curl_easy_setopt(3), to make that
+specific curl handle use the data in this share.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+If this function returns NULL, something went wrong (out of memory, etc.)
+and therefore the share object was not created.
diff --git a/docs/libcurl/curl_share_setopt.3 b/docs/libcurl/curl_share_setopt.3
deleted file mode 100644
index d894291ba..000000000
--- a/docs/libcurl/curl_share_setopt.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_share_setopt 3 "8 Aug 2003" "libcurl" "libcurl"
-.SH NAME
-curl_share_setopt - Set options for a shared object
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option, parameter);
-.fi
-.SH DESCRIPTION
-Set the \fIoption\fP to \fIparameter\fP for the given \fIshare\fP.
-.SH OPTIONS
-.IP CURLSHOPT_LOCKFUNC
-See \fICURLSHOPT_LOCKFUNC(3)\fP.
-.IP CURLSHOPT_UNLOCKFUNC
-See \fICURLSHOPT_UNLOCKFUNC(3)\fP.
-.IP CURLSHOPT_SHARE
-See \fICURLSHOPT_SHARE(3)\fP.
-.IP CURLSHOPT_UNSHARE
-See \fICURLSHOPT_UNSHARE(3)\fP.
-.IP CURLSHOPT_USERDATA
-See \fICURLSHOPT_USERDATA(3)\fP.
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-CURLSHE_OK (zero) means that the option was set properly, non-zero means an
-error occurred as \fI<curl/curl.h>\fP defines. See the \fIlibcurl-errors(3)\fP
-man page for the full list with descriptions.
-.SH "SEE ALSO"
-.BR curl_share_cleanup (3),
-.BR curl_share_init (3)
diff --git a/docs/libcurl/curl_share_setopt.md b/docs/libcurl/curl_share_setopt.md
new file mode 100644
index 000000000..5ab95503b
--- /dev/null
+++ b/docs/libcurl/curl_share_setopt.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_share_setopt
+Section: 3
+Source: libcurl
+See-also:
+ - curl_share_cleanup (3)
+ - curl_share_init (3)
+---
+
+# NAME
+
+curl_share_setopt - Set options for a shared object
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option, parameter);
+~~~
+
+# DESCRIPTION
+
+Set the *option* to *parameter* for the given *share*.
+
+# OPTIONS
+
+## CURLSHOPT_LOCKFUNC
+
+See CURLSHOPT_LOCKFUNC(3).
+
+## CURLSHOPT_UNLOCKFUNC
+
+See CURLSHOPT_UNLOCKFUNC(3).
+
+## CURLSHOPT_SHARE
+
+See CURLSHOPT_SHARE(3).
+
+## CURLSHOPT_UNSHARE
+
+See CURLSHOPT_UNSHARE(3).
+
+## CURLSHOPT_USERDATA
+
+See CURLSHOPT_USERDATA(3).
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+CURLSHE_OK (zero) means that the option was set properly, non-zero means an
+error occurred as *<curl/curl.h>* defines. See the libcurl-errors(3)
+man page for the full list with descriptions.
diff --git a/docs/libcurl/curl_share_strerror.3 b/docs/libcurl/curl_share_strerror.3
deleted file mode 100644
index 6dd857dca..000000000
--- a/docs/libcurl/curl_share_strerror.3
+++ /dev/null
@@ -1,50 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_share_strerror 3 "Apr 26, 2004" "libcurl" "libcurl"
-.SH NAME
-curl_share_strerror - return string describing error code
-.SH SYNOPSIS
-.nf
-.B #include <curl/curl.h>
-.BI "const char *curl_share_strerror(CURLSHcode " errornum ");"
-.SH DESCRIPTION
-The \fIcurl_share_strerror(3)\fP function returns a string describing the
-\fICURLSHcode\fP error code passed in the argument \fIerrornum\fP.
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-This function was added in libcurl 7.12.0
-.SH RETURN VALUE
-A pointer to a null-terminated string.
-.SH "SEE ALSO"
-.BR curl_easy_strerror (3),
-.BR curl_multi_strerror (3),
-.BR curl_url_strerror (3),
-.BR libcurl-errors (3)
diff --git a/docs/libcurl/curl_share_strerror.md b/docs/libcurl/curl_share_strerror.md
new file mode 100644
index 000000000..130d43b3b
--- /dev/null
+++ b/docs/libcurl/curl_share_strerror.md
@@ -0,0 +1,50 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_share_strerror
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_strerror (3)
+ - curl_multi_strerror (3)
+ - curl_url_strerror (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+curl_share_strerror - return string describing error code
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const char *curl_share_strerror(CURLSHcode errornum);
+~~~
+
+# DESCRIPTION
+
+The curl_share_strerror(3) function returns a string describing the
+*CURLSHcode* error code passed in the argument *errornum*.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+This function was added in libcurl 7.12.0
+
+# RETURN VALUE
+
+A pointer to a null-terminated string.
diff --git a/docs/libcurl/curl_slist_append.3 b/docs/libcurl/curl_slist_append.3
deleted file mode 100644
index b869d3aea..000000000
--- a/docs/libcurl/curl_slist_append.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_slist_append 3 "19 Jun 2003" "libcurl" "libcurl"
-.SH NAME
-curl_slist_append - add a string to an slist
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-struct curl_slist *curl_slist_append(struct curl_slist *list,
- const char *string);
-.fi
-.SH DESCRIPTION
-\fIcurl_slist_append(3)\fP appends a string to a linked list of strings. The
-existing \fBlist\fP should be passed as the first argument and the new list is
-returned from this function. Pass in NULL in the \fBlist\fP argument to create
-a new list. The specified \fBstring\fP has been appended when this function
-returns. \fIcurl_slist_append(3)\fP copies the string.
-
-The list should be freed again (after usage) with
-\fIcurl_slist_free_all(3)\fP.
-.SH EXAMPLE
-.nf
-CURL *handle;
-struct curl_slist *slist=NULL;
-struct curl_slist *temp=NULL;
-
-slist = curl_slist_append(slist, "pragma:");
-
-if (slist == NULL)
- return -1;
-
-temp = curl_slist_append(slist, "Accept:")
-
-if (temp == NULL) {
- curl_slist_free_all(slist);
- return -1;
-}
-
-slist = temp;
-
-curl_easy_setopt(handle, CURLOPT_HTTPHEADER, slist);
-
-curl_easy_perform(handle);
-
-curl_slist_free_all(slist); /* free the list again */
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-A null pointer is returned if anything went wrong, otherwise the new list
-pointer is returned. To avoid overwriting an existing non-empty list on
-failure, the new list should be returned to a temporary variable which can
-be tested for NULL before updating the original list pointer.
-.SH "SEE ALSO"
-.BR curl_slist_free_all (3)
diff --git a/docs/libcurl/curl_slist_append.md b/docs/libcurl/curl_slist_append.md
new file mode 100644
index 000000000..9773fd494
--- /dev/null
+++ b/docs/libcurl/curl_slist_append.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_slist_append
+Section: 3
+Source: libcurl
+See-also:
+ - curl_slist_free_all (3)
+---
+
+# NAME
+
+curl_slist_append - add a string to an slist
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+struct curl_slist *curl_slist_append(struct curl_slist *list,
+ const char *string);
+~~~
+
+# DESCRIPTION
+
+curl_slist_append(3) appends a string to a linked list of strings. The
+existing **list** should be passed as the first argument and the new list is
+returned from this function. Pass in NULL in the **list** argument to create
+a new list. The specified **string** has been appended when this function
+returns. curl_slist_append(3) copies the string.
+
+The list should be freed again (after usage) with
+curl_slist_free_all(3).
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *handle;
+ struct curl_slist *slist = NULL;
+ struct curl_slist *temp = NULL;
+
+ slist = curl_slist_append(slist, "pragma:");
+
+ if(!slist)
+ return -1;
+
+ temp = curl_slist_append(slist, "Accept:");
+
+ if(!temp) {
+ curl_slist_free_all(slist);
+ return -1;
+ }
+
+ slist = temp;
+
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, slist);
+
+ curl_easy_perform(handle);
+
+ curl_slist_free_all(slist); /* free the list again */
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+A null pointer is returned if anything went wrong, otherwise the new list
+pointer is returned. To avoid overwriting an existing non-empty list on
+failure, the new list should be returned to a temporary variable which can
+be tested for NULL before updating the original list pointer.
diff --git a/docs/libcurl/curl_slist_free_all.3 b/docs/libcurl/curl_slist_free_all.3
deleted file mode 100644
index 5b562a063..000000000
--- a/docs/libcurl/curl_slist_free_all.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_slist_free_all 3 "5 March 2001" "libcurl" "libcurl"
-.SH NAME
-curl_slist_free_all - free an entire curl_slist list
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_slist_free_all(struct curl_slist *list);
-.fi
-.SH DESCRIPTION
-curl_slist_free_all() removes all traces of a previously built curl_slist
-linked list.
-
-Passing in a NULL pointer in \fIlist\fP makes this function return immediately
-with no action.
-.SH EXAMPLE
-.nf
-CURL *handle;
-struct curl_slist *slist=NULL;
-
-slist = curl_slist_append(slist, "X-libcurl: coolness");
-
-if (slist == NULL)
- return -1;
-
-curl_easy_setopt(handle, CURLOPT_HTTPHEADER, slist);
-
-curl_easy_perform(handle);
-
-curl_slist_free_all(slist); /* free the list again */
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Nothing.
-.SH "SEE ALSO"
-.BR curl_slist_append (3)
diff --git a/docs/libcurl/curl_slist_free_all.md b/docs/libcurl/curl_slist_free_all.md
new file mode 100644
index 000000000..928f30601
--- /dev/null
+++ b/docs/libcurl/curl_slist_free_all.md
@@ -0,0 +1,58 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_slist_free_all
+Section: 3
+Source: libcurl
+See-also:
+ - curl_slist_append (3)
+---
+
+# NAME
+
+curl_slist_free_all - free an entire curl_slist list
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_slist_free_all(struct curl_slist *list);
+~~~
+
+# DESCRIPTION
+
+curl_slist_free_all() removes all traces of a previously built curl_slist
+linked list.
+
+Passing in a NULL pointer in *list* makes this function return immediately
+with no action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *handle;
+ struct curl_slist *slist = NULL;
+
+ slist = curl_slist_append(slist, "X-libcurl: coolness");
+
+ if(!slist)
+ return -1;
+
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, slist);
+
+ curl_easy_perform(handle);
+
+ curl_slist_free_all(slist); /* free the list again */
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Nothing.
diff --git a/docs/libcurl/curl_strequal.3 b/docs/libcurl/curl_strequal.3
deleted file mode 100644
index c66c6529a..000000000
--- a/docs/libcurl/curl_strequal.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_strequal 3 "30 April 2004" "libcurl" "libcurl"
-.SH NAME
-curl_strequal, curl_strnequal - case insensitive string comparisons
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int curl_strequal(char *str1, char *str2);
-int curl_strnequal(char *str1, char *str2, size_t length);
-.fi
-.SH DESCRIPTION
-The
-.B curl_strequal()
-function compares the two strings \fIstr1\fP and \fIstr2\fP, ignoring the case
-of the characters. It returns a non-zero (TRUE) integer if the strings are
-identical.
-.sp
-The \fBcurl_strnequal()\fP function is similar, except it only compares the
-first \fIlength\fP characters of \fIstr1\fP.
-.sp
-These functions are provided by libcurl to enable applications to compare
-strings in a truly portable manner. There are no standard portable case
-insensitive string comparison functions. These two work on all platforms.
-.SH EXAMPLE
-.nf
-if(curl_strequal(name, input))
- printf("Name and input matches\\n");
-if(curl_strnequal(name, input, 5))
- printf("Name and input matches in the 5 first bytes\\n");
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Non-zero if the strings are identical. Zero if they are not.
-.SH "SEE ALSO"
-.BR strcmp "(3), " strcasecmp "(3)"
diff --git a/docs/libcurl/curl_strequal.md b/docs/libcurl/curl_strequal.md
new file mode 100644
index 000000000..518faee6a
--- /dev/null
+++ b/docs/libcurl/curl_strequal.md
@@ -0,0 +1,57 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_strequal
+Section: 3
+Source: libcurl
+See-also:
+ - strcasecmp (3)
+ - strcmp (3)
+---
+
+# NAME
+
+curl_strequal, curl_strnequal - case insensitive string comparisons
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int curl_strequal(const char *str1, const char *str2);
+int curl_strnequal(const char *str1, const char *str2, size_t length);
+~~~
+
+# DESCRIPTION
+
+The curl_strequal(3) function compares the two strings *str1* and
+*str2*, ignoring the case of the characters. It returns a non-zero (TRUE)
+integer if the strings are identical.
+
+The **curl_strnequal()** function is similar, except it only compares the
+first *length* characters of *str1*.
+
+These functions are provided by libcurl to enable applications to compare
+strings in a truly portable manner. There are no standard portable case
+insensitive string comparison functions. These two work on all platforms.
+
+# EXAMPLE
+
+~~~c
+int main(int argc, char **argv)
+{
+ const char *name = "compare";
+ if(curl_strequal(name, argv[1]))
+ printf("Name and input matches\n");
+ if(curl_strnequal(name, argv[1], 5))
+ printf("Name and input matches in the 5 first bytes\n");
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Non-zero if the strings are identical. Zero if they are not.
diff --git a/docs/libcurl/curl_strnequal.3 b/docs/libcurl/curl_strnequal.3
deleted file mode 100644
index ce41d3e41..000000000
--- a/docs/libcurl/curl_strnequal.3
+++ /dev/null
@@ -1 +0,0 @@
-.so man3/curl_strequal.3
diff --git a/docs/libcurl/curl_strnequal.md b/docs/libcurl/curl_strnequal.md
new file mode 100644
index 000000000..518faee6a
--- /dev/null
+++ b/docs/libcurl/curl_strnequal.md
@@ -0,0 +1,57 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_strequal
+Section: 3
+Source: libcurl
+See-also:
+ - strcasecmp (3)
+ - strcmp (3)
+---
+
+# NAME
+
+curl_strequal, curl_strnequal - case insensitive string comparisons
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int curl_strequal(const char *str1, const char *str2);
+int curl_strnequal(const char *str1, const char *str2, size_t length);
+~~~
+
+# DESCRIPTION
+
+The curl_strequal(3) function compares the two strings *str1* and
+*str2*, ignoring the case of the characters. It returns a non-zero (TRUE)
+integer if the strings are identical.
+
+The **curl_strnequal()** function is similar, except it only compares the
+first *length* characters of *str1*.
+
+These functions are provided by libcurl to enable applications to compare
+strings in a truly portable manner. There are no standard portable case
+insensitive string comparison functions. These two work on all platforms.
+
+# EXAMPLE
+
+~~~c
+int main(int argc, char **argv)
+{
+ const char *name = "compare";
+ if(curl_strequal(name, argv[1]))
+ printf("Name and input matches\n");
+ if(curl_strnequal(name, argv[1], 5))
+ printf("Name and input matches in the 5 first bytes\n");
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Non-zero if the strings are identical. Zero if they are not.
diff --git a/docs/libcurl/curl_unescape.3 b/docs/libcurl/curl_unescape.3
deleted file mode 100644
index d91349282..000000000
--- a/docs/libcurl/curl_unescape.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_unescape 3 "22 March 2001" "libcurl" "libcurl"
-.SH NAME
-curl_unescape - URL decodes the given string
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_unescape(const char *input, int length);
-.fi
-.SH DESCRIPTION
-Obsolete function. Use \fIcurl_easy_unescape(3)\fP instead!
-
-This function converts the URL encoded string \fBinput\fP to a "plain string"
-and return that as a new allocated string. All input characters that are URL
-encoded (%XX where XX is a two-digit hexadecimal number) are converted to
-their plain text versions.
-
-If the \fBlength\fP argument is set to 0, \fIcurl_unescape(3)\fP calls
-strlen() on \fBinput\fP to find out the size.
-
-You must \fIcurl_free(3)\fP the returned string when you are done with it.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- int decodelen;
- char *decoded = curl_unescape("%63%75%72%6c", 12, &decodelen);
- if(decoded) {
- /* do not assume printf() works on the decoded data! */
- printf("Decoded: ");
- /* ... */
- curl_free(decoded);
- }
-}
-.fi
-.SH AVAILABILITY
-Since 7.15.4, \fIcurl_easy_unescape(3)\fP should be used. This function might
-be removed in a future release.
-.SH RETURN VALUE
-A pointer to a null-terminated string or NULL if it failed.
-.SH "SEE ALSO"
-.BR curl_easy_escape (3),
-.BR curl_easy_unescape (3),
-.BR curl_free (3),
-.BR RFC 2396
diff --git a/docs/libcurl/curl_unescape.md b/docs/libcurl/curl_unescape.md
new file mode 100644
index 000000000..8ae9f5089
--- /dev/null
+++ b/docs/libcurl/curl_unescape.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_unescape
+Section: 3
+Source: libcurl
+See-also:
+ - RFC 2396
+ - curl_easy_escape (3)
+ - curl_easy_unescape (3)
+ - curl_free (3)
+---
+
+# NAME
+
+curl_unescape - URL decodes the given string
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_unescape(const char *input, int length);
+~~~
+
+# DESCRIPTION
+
+Obsolete function. Use curl_easy_unescape(3) instead.
+
+This function converts the URL encoded string **input** to a "plain string"
+and return that as a new allocated string. All input characters that are URL
+encoded (%XX where XX is a two-digit hexadecimal number) are converted to
+their plain text versions.
+
+If the **length** argument is set to 0, curl_unescape(3) calls
+strlen() on **input** to find out the size.
+
+You must curl_free(3) the returned string when you are done with it.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ char *decoded = curl_unescape("%63%75%72%6c", 12);
+ if(decoded) {
+ /* do not assume printf() works on the decoded data */
+ printf("Decoded: ");
+ /* ... */
+ curl_free(decoded);
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Since 7.15.4, curl_easy_unescape(3) should be used. This function might
+be removed in a future release.
+
+# RETURN VALUE
+
+A pointer to a null-terminated string or NULL if it failed.
diff --git a/docs/libcurl/curl_url.3 b/docs/libcurl/curl_url.3
deleted file mode 100644
index 01eb55e61..000000000
--- a/docs/libcurl/curl_url.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_url 3 "6 Aug 2018" "libcurl" "libcurl"
-.SH NAME
-curl_url - returns a new URL handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLU *curl_url();
-.fi
-.SH DESCRIPTION
-This function allocates a URL object and returns a \fICURLU\fP handle for it,
-to be used as input to all other URL API functions.
-
-This is a handle to a URL object that holds or can hold URL components for a
-single URL. When the object is first created, there is of course no components
-stored. They are then set in the object with the \fIcurl_url_set(3)\fP
-function.
-.SH EXAMPLE
-.nf
- CURLUcode rc;
- CURLU *url = curl_url();
- rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
- if(!rc) {
- char *scheme;
- rc = curl_url_get(url, CURLUPART_SCHEME, &scheme, 0);
- if(!rc) {
- printf("the scheme is %s\\n", scheme);
- curl_free(scheme);
- }
- curl_url_cleanup(url);
- }
-.fi
-.SH AVAILABILITY
-Added in 7.62.0
-.SH RETURN VALUE
-Returns a \fBCURLU *\fP if successful, or NULL if out of memory.
-.SH "SEE ALSO"
-.BR curl_url_cleanup (3),
-.BR curl_url_dup (3),
-.BR curl_url_get (3),
-.BR curl_url_set (3),
-.BR curl_url_strerror (3),
-.BR CURLOPT_CURLU (3)
diff --git a/docs/libcurl/curl_url.md b/docs/libcurl/curl_url.md
new file mode 100644
index 000000000..f71fb3580
--- /dev/null
+++ b/docs/libcurl/curl_url.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_url
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CURLU (3)
+ - curl_url_cleanup (3)
+ - curl_url_dup (3)
+ - curl_url_get (3)
+ - curl_url_set (3)
+ - curl_url_strerror (3)
+---
+
+# NAME
+
+curl_url - returns a new URL handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLU *curl_url();
+~~~
+
+# DESCRIPTION
+
+This function allocates a URL object and returns a *CURLU* handle for it,
+to be used as input to all other URL API functions.
+
+This is a handle to a URL object that holds or can hold URL components for a
+single URL. When the object is first created, there is of course no components
+stored. They are then set in the object with the curl_url_set(3)
+function.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLUcode rc;
+ CURLU *url = curl_url();
+ rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
+ if(!rc) {
+ char *scheme;
+ rc = curl_url_get(url, CURLUPART_SCHEME, &scheme, 0);
+ if(!rc) {
+ printf("the scheme is %s\n", scheme);
+ curl_free(scheme);
+ }
+ curl_url_cleanup(url);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0
+
+# RETURN VALUE
+
+Returns a **CURLU *** if successful, or NULL if out of memory.
diff --git a/docs/libcurl/curl_url_cleanup.3 b/docs/libcurl/curl_url_cleanup.3
deleted file mode 100644
index 7dc5f61a7..000000000
--- a/docs/libcurl/curl_url_cleanup.3
+++ /dev/null
@@ -1,53 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_url_cleanup 3 "6 Aug 2018" "libcurl" "libcurl"
-.SH NAME
-curl_url_cleanup - free the URL handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void curl_url_cleanup(CURLU *handle);
-.fi
-.SH DESCRIPTION
-Frees all the resources associated with the given \fICURLU\fP handle!
-
-Passing in a NULL pointer in \fIhandle\fP makes this function return
-immediately with no action.
-.SH EXAMPLE
-.nf
- CURLU *url = curl_url();
- curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
- curl_url_cleanup(url);
-.fi
-.SH AVAILABILITY
-Added in 7.62.0
-.SH RETURN VALUE
-none
-.SH "SEE ALSO"
-.BR curl_url_dup (3),
-.BR curl_url (3),
-.BR curl_url_set (3),
-.BR curl_url_get (3),
-.BR CURLOPT_CURLU (3)
diff --git a/docs/libcurl/curl_url_cleanup.md b/docs/libcurl/curl_url_cleanup.md
new file mode 100644
index 000000000..d0f85b69c
--- /dev/null
+++ b/docs/libcurl/curl_url_cleanup.md
@@ -0,0 +1,51 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_url_cleanup
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CURLU (3)
+ - curl_url (3)
+ - curl_url_dup (3)
+ - curl_url_get (3)
+ - curl_url_set (3)
+---
+
+# NAME
+
+curl_url_cleanup - free the URL handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void curl_url_cleanup(CURLU *handle);
+~~~
+
+# DESCRIPTION
+
+Frees all the resources associated with the given *CURLU* handle!
+
+Passing in a NULL pointer in *handle* makes this function return
+immediately with no action.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLU *url = curl_url();
+ curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
+ curl_url_cleanup(url);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0
+
+# RETURN VALUE
+
+none
diff --git a/docs/libcurl/curl_url_dup.3 b/docs/libcurl/curl_url_dup.3
deleted file mode 100644
index a2e9850b5..000000000
--- a/docs/libcurl/curl_url_dup.3
+++ /dev/null
@@ -1,58 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_url_dup 3 "6 Aug 2018" "libcurl" "libcurl"
-.SH NAME
-curl_url_dup - duplicate a URL handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLU *curl_url_dup(CURLU *inhandle);
-.fi
-.SH DESCRIPTION
-Duplicates the URL object the input \fICURLU\fP \fIinhandle\fP identifies and
-returns a pointer to the copy as a new \fICURLU\fP handle. The new handle also
-needs to be freed with \fIcurl_url_cleanup(3)\fP.
-.SH EXAMPLE
-.nf
- CURLUcode rc;
- CURLU *url = curl_url();
- CURLU *url2;
- rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
- if(!rc) {
- url2 = curl_url_dup(url); /* clone it! */
- curl_url_cleanup(url2);
- }
- curl_url_cleanup(url);
-.fi
-.SH AVAILABILITY
-Added in 7.62.0
-.SH RETURN VALUE
-Returns a new handle or NULL if out of memory.
-.SH "SEE ALSO"
-.BR curl_url (3),
-.BR curl_url_cleanup (3),
-.BR curl_url_get (3),
-.BR curl_url_set (3),
-.BR CURLOPT_CURLU (3)
diff --git a/docs/libcurl/curl_url_dup.md b/docs/libcurl/curl_url_dup.md
new file mode 100644
index 000000000..ea590ce83
--- /dev/null
+++ b/docs/libcurl/curl_url_dup.md
@@ -0,0 +1,56 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_url_dup
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CURLU (3)
+ - curl_url (3)
+ - curl_url_cleanup (3)
+ - curl_url_get (3)
+ - curl_url_set (3)
+---
+
+# NAME
+
+curl_url_dup - duplicate a URL handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLU *curl_url_dup(const CURLU *inhandle);
+~~~
+
+# DESCRIPTION
+
+Duplicates the URL object the input *CURLU* *inhandle* identifies and
+returns a pointer to the copy as a new *CURLU* handle. The new handle also
+needs to be freed with curl_url_cleanup(3).
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLUcode rc;
+ CURLU *url = curl_url();
+ CURLU *url2;
+ rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
+ if(!rc) {
+ url2 = curl_url_dup(url); /* clone it! */
+ curl_url_cleanup(url2);
+ }
+ curl_url_cleanup(url);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0
+
+# RETURN VALUE
+
+Returns a new handle or NULL if out of memory.
diff --git a/docs/libcurl/curl_url_get.3 b/docs/libcurl/curl_url_get.3
deleted file mode 100644
index 815e5587e..000000000
--- a/docs/libcurl/curl_url_get.3
+++ /dev/null
@@ -1,175 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_url_get 3 "6 Aug 2018" "libcurl" "libcurl"
-.SH NAME
-curl_url_get - extract a part from a URL
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLUcode curl_url_get(CURLU *url,
- CURLUPart part,
- char **content,
- unsigned int flags);
-.fi
-.SH DESCRIPTION
-Given a \fIurl\fP handle of a URL object, this function extracts an individual
-piece or the full URL from it.
-
-The \fIpart\fP argument specifies which part to extract (see list below) and
-\fIcontent\fP points to a 'char *' to get updated to point to a newly
-allocated string with the contents.
-
-The \fIflags\fP argument is a bitmask with individual features.
-
-The returned content pointer must be freed with \fIcurl_free(3)\fP after use.
-.SH FLAGS
-The flags argument is zero, one or more bits set in a bitmask.
-.IP CURLU_DEFAULT_PORT
-If the handle has no port stored, this option makes \fIcurl_url_get(3)\fP
-return the default port for the used scheme.
-.IP CURLU_DEFAULT_SCHEME
-If the handle has no scheme stored, this option makes \fIcurl_url_get(3)\fP
-return the default scheme instead of error.
-.IP CURLU_NO_DEFAULT_PORT
-Instructs \fIcurl_url_get(3)\fP to not return a port number if it matches the
-default port for the scheme.
-.IP CURLU_URLDECODE
-Asks \fIcurl_url_get(3)\fP to URL decode the contents before returning it. It
-does not decode the scheme, the port number or the full URL.
-
-The query component also gets plus-to-space conversion as a bonus when this
-bit is set.
-
-Note that this URL decoding is charset unaware and you get a zero terminated
-string back with data that could be intended for a particular encoding.
-
-If there are byte values lower than 32 in the decoded string, the get
-operation returns an error instead.
-.IP CURLU_URLENCODE
-If set, \fIcurl_url_get(3)\fP URL encodes the host name part when a full URL
-is retrieved. If not set (default), libcurl returns the URL with the host name
-"raw" to support IDN names to appear as-is. IDN host names are typically using
-non-ASCII bytes that otherwise gets percent-encoded.
-
-Note that even when not asking for URL encoding, the '%' (byte 37) is URL
-encoded to make sure the host name remains valid.
-.IP CURLU_PUNYCODE
-If set and \fICURLU_URLENCODE\fP is not set, and asked to retrieve the
-\fBCURLUPART_HOST\fP or \fBCURLUPART_URL\fP parts, libcurl returns the host
-name in its punycode version if it contains any non-ASCII octets (and is an
-IDN name).
-
-If libcurl is built without IDN capabilities, using this bit makes
-\fIcurl_url_get(3)\fP return \fICURLUE_LACKS_IDN\fP if the host name contains
-anything outside the ASCII range.
-
-(Added in curl 7.88.0)
-.IP CURLU_PUNY2IDN
-If set and asked to retrieve the \fBCURLUPART_HOST\fP or \fBCURLUPART_URL\fP
-parts, libcurl returns the host name in its IDN (International Domain Name)
-UTF-8 version if it otherwise is a punycode version. If the punycode name
-cannot be converted to IDN correctly, libcurl returns
-\fICURLUE_BAD_HOSTNAME\fP.
-
-If libcurl is built without IDN capabilities, using this bit makes
-\fIcurl_url_get(3)\fP return \fICURLUE_LACKS_IDN\fP if the host name is using
-punycode.
-
-(Added in curl 8.3.0)
-.SH PARTS
-.IP CURLUPART_URL
-When asked to return the full URL, \fIcurl_url_get(3)\fP returns a normalized
-and possibly cleaned up version using all available URL parts.
-
-We advise using the \fICURLU_PUNYCODE\fP option to get the URL as "normalized"
-as possible since IDN allows host names to be written in many different ways
-that still end up the same punycode version.
-.IP CURLUPART_SCHEME
-Scheme cannot be URL decoded on get.
-.IP CURLUPART_USER
-.IP CURLUPART_PASSWORD
-.IP CURLUPART_OPTIONS
-The options field is an optional field that might follow the password in the
-userinfo part. It is only recognized/used when parsing URLs for the following
-schemes: pop3, smtp and imap. The URL API still allows users to set and get
-this field independently of scheme when not parsing full URLs.
-.IP CURLUPART_HOST
-The host name. If it is an IPv6 numeric address, the zone id is not part of it
-but is provided separately in \fICURLUPART_ZONEID\fP. IPv6 numerical addresses
-are returned within brackets ([]).
-
-IPv6 names are normalized when set, which should make them as short as
-possible while maintaining correct syntax.
-.IP CURLUPART_ZONEID
-If the host name is a numeric IPv6 address, this field might also be set.
-.IP CURLUPART_PORT
-A port cannot be URL decoded on get. This number is returned in a string just
-like all other parts. That string is guaranteed to hold a valid port number in
-ASCII using base 10.
-.IP CURLUPART_PATH
-The \fIpart\fP is always at least a slash ('/') even if no path was supplied
-in the URL. A URL path always starts with a slash.
-.IP CURLUPART_QUERY
-The initial question mark that denotes the beginning of the query part is a
-delimiter only. It is not part of the query contents.
-
-A not-present query returns \fIpart\fP set to NULL.
-A zero-length query returns \fIpart\fP as a zero-length string.
-
-The query part gets pluses converted to space when asked to URL decode on get
-with the CURLU_URLDECODE bit.
-.IP CURLUPART_FRAGMENT
-The initial hash sign that denotes the beginning of the fragment is a
-delimiter only. It is not part of the fragment contents.
-.SH EXAMPLE
-.nf
- CURLUcode rc;
- CURLU *url = curl_url();
- rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
- if(!rc) {
- char *scheme;
- rc = curl_url_get(url, CURLUPART_SCHEME, &scheme, 0);
- if(!rc) {
- printf("the scheme is %s\\n", scheme);
- curl_free(scheme);
- }
- curl_url_cleanup(url);
- }
-.fi
-.SH AVAILABILITY
-Added in 7.62.0. CURLUPART_ZONEID was added in 7.65.0.
-.SH RETURN VALUE
-Returns a CURLUcode error value, which is CURLUE_OK (0) if everything went
-fine. See the \fIlibcurl-errors(3)\fP man page for the full list with
-descriptions.
-
-If this function returns an error, no URL part is returned.
-.SH "SEE ALSO"
-.BR curl_url (3),
-.BR curl_url_cleanup (3),
-.BR curl_url_dup (3),
-.BR curl_url_set (3),
-.BR curl_url_strerror (3),
-.BR CURLOPT_CURLU (3)
diff --git a/docs/libcurl/curl_url_get.md b/docs/libcurl/curl_url_get.md
new file mode 100644
index 000000000..2ea421818
--- /dev/null
+++ b/docs/libcurl/curl_url_get.md
@@ -0,0 +1,210 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_url_get
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CURLU (3)
+ - curl_url (3)
+ - curl_url_cleanup (3)
+ - curl_url_dup (3)
+ - curl_url_set (3)
+ - curl_url_strerror (3)
+---
+
+# NAME
+
+curl_url_get - extract a part from a URL
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLUcode curl_url_get(const CURLU *url,
+ CURLUPart part,
+ char **content,
+ unsigned int flags);
+~~~
+
+# DESCRIPTION
+
+Given a *url* handle of a URL object, this function extracts an individual
+piece or the full URL from it.
+
+The *part* argument specifies which part to extract (see list below) and
+*content* points to a 'char *' to get updated to point to a newly
+allocated string with the contents.
+
+The *flags* argument is a bitmask with individual features.
+
+The returned content pointer must be freed with curl_free(3) after use.
+
+# FLAGS
+
+The flags argument is zero, one or more bits set in a bitmask.
+
+## CURLU_DEFAULT_PORT
+
+If the handle has no port stored, this option makes curl_url_get(3)
+return the default port for the used scheme.
+
+## CURLU_DEFAULT_SCHEME
+
+If the handle has no scheme stored, this option makes curl_url_get(3)
+return the default scheme instead of error.
+
+## CURLU_NO_DEFAULT_PORT
+
+Instructs curl_url_get(3) to not return a port number if it matches the
+default port for the scheme.
+
+## CURLU_URLDECODE
+
+Asks curl_url_get(3) to URL decode the contents before returning it. It
+does not decode the scheme, the port number or the full URL.
+
+The query component also gets plus-to-space conversion as a bonus when this
+bit is set.
+
+Note that this URL decoding is charset unaware and you get a zero terminated
+string back with data that could be intended for a particular encoding.
+
+If there are byte values lower than 32 in the decoded string, the get
+operation returns an error instead.
+
+## CURLU_URLENCODE
+
+If set, curl_url_get(3) URL encodes the hostname part when a full URL
+is retrieved. If not set (default), libcurl returns the URL with the host name
+"raw" to support IDN names to appear as-is. IDN host names are typically using
+non-ASCII bytes that otherwise gets percent-encoded.
+
+Note that even when not asking for URL encoding, the '%' (byte 37) is URL
+encoded to make sure the hostname remains valid.
+
+## CURLU_PUNYCODE
+
+If set and *CURLU_URLENCODE* is not set, and asked to retrieve the
+**CURLUPART_HOST** or **CURLUPART_URL** parts, libcurl returns the host
+name in its punycode version if it contains any non-ASCII octets (and is an
+IDN name).
+
+If libcurl is built without IDN capabilities, using this bit makes
+curl_url_get(3) return *CURLUE_LACKS_IDN* if the hostname contains
+anything outside the ASCII range.
+
+(Added in curl 7.88.0)
+
+## CURLU_PUNY2IDN
+
+If set and asked to retrieve the **CURLUPART_HOST** or **CURLUPART_URL**
+parts, libcurl returns the hostname in its IDN (International Domain Name)
+UTF-8 version if it otherwise is a punycode version. If the punycode name
+cannot be converted to IDN correctly, libcurl returns
+*CURLUE_BAD_HOSTNAME*.
+
+If libcurl is built without IDN capabilities, using this bit makes
+curl_url_get(3) return *CURLUE_LACKS_IDN* if the hostname is using
+punycode.
+
+(Added in curl 8.3.0)
+
+# PARTS
+
+## CURLUPART_URL
+
+When asked to return the full URL, curl_url_get(3) returns a normalized
+and possibly cleaned up version using all available URL parts.
+
+We advise using the *CURLU_PUNYCODE* option to get the URL as "normalized"
+as possible since IDN allows host names to be written in many different ways
+that still end up the same punycode version.
+
+## CURLUPART_SCHEME
+
+Scheme cannot be URL decoded on get.
+
+## CURLUPART_USER
+
+## CURLUPART_PASSWORD
+
+## CURLUPART_OPTIONS
+
+The options field is an optional field that might follow the password in the
+userinfo part. It is only recognized/used when parsing URLs for the following
+schemes: pop3, smtp and imap. The URL API still allows users to set and get
+this field independently of scheme when not parsing full URLs.
+
+## CURLUPART_HOST
+
+The hostname. If it is an IPv6 numeric address, the zone id is not part of it
+but is provided separately in *CURLUPART_ZONEID*. IPv6 numerical addresses
+are returned within brackets ([]).
+
+IPv6 names are normalized when set, which should make them as short as
+possible while maintaining correct syntax.
+
+## CURLUPART_ZONEID
+
+If the hostname is a numeric IPv6 address, this field might also be set.
+
+## CURLUPART_PORT
+
+A port cannot be URL decoded on get. This number is returned in a string just
+like all other parts. That string is guaranteed to hold a valid port number in
+ASCII using base 10.
+
+## CURLUPART_PATH
+
+The *part* is always at least a slash ('/') even if no path was supplied
+in the URL. A URL path always starts with a slash.
+
+## CURLUPART_QUERY
+
+The initial question mark that denotes the beginning of the query part is a
+delimiter only. It is not part of the query contents.
+
+A not-present query returns *part* set to NULL.
+A zero-length query returns *part* as a zero-length string.
+
+The query part gets pluses converted to space when asked to URL decode on get
+with the CURLU_URLDECODE bit.
+
+## CURLUPART_FRAGMENT
+
+The initial hash sign that denotes the beginning of the fragment is a
+delimiter only. It is not part of the fragment contents.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLUcode rc;
+ CURLU *url = curl_url();
+ rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
+ if(!rc) {
+ char *scheme;
+ rc = curl_url_get(url, CURLUPART_SCHEME, &scheme, 0);
+ if(!rc) {
+ printf("the scheme is %s\n", scheme);
+ curl_free(scheme);
+ }
+ curl_url_cleanup(url);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0. CURLUPART_ZONEID was added in 7.65.0.
+
+# RETURN VALUE
+
+Returns a CURLUcode error value, which is CURLUE_OK (0) if everything went
+fine. See the libcurl-errors(3) man page for the full list with
+descriptions.
+
+If this function returns an error, no URL part is returned.
diff --git a/docs/libcurl/curl_url_set.3 b/docs/libcurl/curl_url_set.3
deleted file mode 100644
index 912694f7b..000000000
--- a/docs/libcurl/curl_url_set.3
+++ /dev/null
@@ -1,209 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_url_set 3 "6 Aug 2018" "libcurl" "libcurl"
-.SH NAME
-curl_url_set - set a URL part
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLUcode curl_url_set(CURLU *url,
- CURLUPart part,
- const char *content,
- unsigned int flags);
-.fi
-.SH DESCRIPTION
-The \fIurl\fP handle to work on, passed in as the first argument, must be a
-handle previously created by \fIcurl_url(3)\fP or \fIcurl_url_dup(3)\fP.
-
-This function sets or updates individual URL components, or parts, held by the
-URL object the handle identifies.
-
-The \fIpart\fP argument should identify the particular URL part (see list
-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 would use in a URL: URL encoded.
-
-When setting part in the URL object that was previously already set, it
-replaces the data that was previously stored for that part with the new
-\fIcontent\fP.
-
-The caller does not have to keep \fIcontent\fP around after a successful call
-as this function copies the content.
-
-Setting a part to a NULL pointer removes that part's contents from the
-\fICURLU\fP handle.
-
-By default, this API only accepts URLs using schemes for protocols that are
-supported built-in. To make libcurl parse URLs generically even for schemes it
-does not know about, the \fBCURLU_NON_SUPPORT_SCHEME\fP flags bit must be
-set. Otherwise, this function returns \fICURLUE_UNSUPPORTED_SCHEME\fP for URL
-schemes it does not recognize.
-
-This function has an 8 MB maximum length limit for all provided input strings.
-In the real world, excessively long fields in URLs cause problems even if this
-API accepts them.
-
-When setting or updating contents of individual URL parts, this API might
-accept data that would not be otherwise possible to set in the string when it
-gets populated as a result of a full URL parse. Beware. If done so, extracting
-a full URL later on from such components might render an invalid URL.
-
-The \fIflags\fP argument is a bitmask with independent features.
-.SH PARTS
-.IP CURLUPART_URL
-Allows the full URL of the handle to be replaced. If the handle already is
-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
-is replaced with the components of the newly set URL.
-
-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.
-
-Unless \fICURLU_NO_AUTHORITY\fP is set, a blank host name is not allowed in
-the URL.
-.IP CURLUPART_SCHEME
-Scheme cannot be URL decoded on set. libcurl only accepts setting schemes up
-to 40 bytes long.
-.IP CURLUPART_USER
-.IP CURLUPART_PASSWORD
-.IP CURLUPART_OPTIONS
-The options field is an optional field that might follow the password in the
-userinfo part. It is only recognized/used when parsing URLs for the following
-schemes: pop3, smtp and imap. This function however allows users to
-independently set this field.
-.IP CURLUPART_HOST
-The host name. If it is International Domain Name (IDN) the string must then
-be encoded as your locale says or UTF-8 (when WinIDN is used). If it is a
-bracketed IPv6 numeric address it may contain a zone id (or you can use
-\fICURLUPART_ZONEID\fP).
-
-Unless \fICURLU_NO_AUTHORITY\fP is set, a blank host name is not allowed to set.
-.IP CURLUPART_ZONEID
-If the host name is a numeric IPv6 address, this field can also be set.
-.IP CURLUPART_PORT
-The port number cannot be URL encoded on set. The given port number is
-provided as a string and the decimal number in it must be between 0 and
-65535. Anything else returns an error.
-.IP CURLUPART_PATH
-If a path is set in the URL without a leading slash, a slash is prepended
-automatically.
-.IP CURLUPART_QUERY
-The query part gets spaces converted to pluses when asked to URL encode on set
-with the \fICURLU_URLENCODE\fP bit.
-
-If used together with the \fICURLU_APPENDQUERY\fP bit, the provided part is
-appended on the end of the existing query.
-
-The question mark in the URL is not part of the actual query contents.
-.IP CURLUPART_FRAGMENT
-The hash sign in the URL is not part of the actual fragment contents.
-.SH FLAGS
-The flags argument is zero, one or more bits set in a bitmask.
-.IP CURLU_APPENDQUERY
-Can be used when setting the \fICURLUPART_QUERY\fP component. The provided new
-part is then appended at the end of the existing query - and if the previous
-part did not end with an ampersand (&), an ampersand gets inserted before the
-new appended part.
-
-When \fICURLU_APPENDQUERY\fP is used together with \fICURLU_URLENCODE\fP, the
-first '=' symbol is not URL encoded.
-.IP CURLU_NON_SUPPORT_SCHEME
-If set, allows \fIcurl_url_set(3)\fP to set a non-supported scheme.
-.IP CURLU_URLENCODE
-When set, \fIcurl_url_set(3)\fP URL encodes the part on entry, except for
-scheme, port and URL.
-
-When setting the path component with URL encoding enabled, the slash character
-is be skipped.
-
-The query part gets space-to-plus conversion before the URL conversion.
-
-This URL encoding is charset unaware and converts the input in a byte-by-byte
-manner.
-.IP CURLU_DEFAULT_SCHEME
-If set, allows the URL to be set without a scheme and then sets that to the
-default scheme: HTTPS. Overrides the \fICURLU_GUESS_SCHEME\fP option if both
-are set.
-.IP CURLU_GUESS_SCHEME
-If set, allows the URL to be set without a scheme and it instead "guesses"
-which scheme that was intended based on the host name. If the outermost
-subdomain name matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that scheme
-is used, otherwise it picks HTTP. Conflicts with the
-\fICURLU_DEFAULT_SCHEME\fP option which takes precedence if both are set.
-.IP CURLU_NO_AUTHORITY
-If set, skips authority checks. The RFC allows individual schemes to omit the
-host part (normally the only mandatory part of the authority), but libcurl
-cannot know whether this is permitted for custom schemes. Specifying the flag
-permits empty authority sections, similar to how file scheme is handled.
-.IP CURLU_PATH_AS_IS
-When set for \fBCURLUPART_URL\fP, this skips the normalization of the
-path. That is the procedure where libcurl otherwise removes sequences of
-dot-slash and dot-dot etc. The same option used for transfers is called
-\fICURLOPT_PATH_AS_IS(3)\fP.
-.IP CURLU_ALLOW_SPACE
-If set, the URL parser allows space (ASCII 32) where possible. The URL syntax
-does normally not allow spaces anywhere, but they should be encoded as %20
-or '+'. When spaces are allowed, they are still not allowed in the scheme.
-When space is used and allowed in a URL, it is stored as-is unless
-\fICURLU_URLENCODE\fP is also set, which then makes libcurl URL encode the
-space before stored. This affects how the URL is constructed when
-\fIcurl_url_get(3)\fP is subsequently used to extract the full URL or
-individual parts. (Added in 7.78.0)
-.IP CURLU_DISALLOW_USER
-If set, the URL parser does not accept embedded credentials for the
-\fBCURLUPART_URL\fP, and instead returns \fBCURLUE_USER_NOT_ALLOWED\fP for
-such URLs.
-.SH EXAMPLE
-.nf
- CURLUcode rc;
- CURLU *url = curl_url();
- rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
- if(!rc) {
- char *scheme;
- /* change it to an FTP URL */
- rc = curl_url_set(url, CURLUPART_SCHEME, "ftp", 0);
- }
- curl_url_cleanup(url);
-.fi
-.SH AVAILABILITY
-Added in 7.62.0. CURLUPART_ZONEID was added in 7.65.0.
-.SH RETURN VALUE
-Returns a \fICURLUcode\fP error value, which is CURLUE_OK (0) if everything
-went fine. See the \fIlibcurl-errors(3)\fP man page for the full list with
-descriptions.
-
-The input string passed to \fIcurl_url_set(3)\fP must be shorter than eight
-million bytes. Otherwise this function returns \fBCURLUE_MALFORMED_INPUT\fP.
-
-If this function returns an error, no URL part is set.
-.SH "SEE ALSO"
-.BR curl_url (3),
-.BR curl_url_cleanup (3),
-.BR curl_url_dup (3),
-.BR curl_url_get (3),
-.BR curl_url_strerror (3),
-.BR CURLOPT_CURLU (3)
diff --git a/docs/libcurl/curl_url_set.md b/docs/libcurl/curl_url_set.md
new file mode 100644
index 000000000..fe2f7ff98
--- /dev/null
+++ b/docs/libcurl/curl_url_set.md
@@ -0,0 +1,247 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_url_set
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CURLU (3)
+ - curl_url (3)
+ - curl_url_cleanup (3)
+ - curl_url_dup (3)
+ - curl_url_get (3)
+ - curl_url_strerror (3)
+---
+
+# NAME
+
+curl_url_set - set a URL part
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLUcode curl_url_set(CURLU *url,
+ CURLUPart part,
+ const char *content,
+ unsigned int flags);
+~~~
+
+# DESCRIPTION
+
+The *url* handle to work on, passed in as the first argument, must be a
+handle previously created by curl_url(3) or curl_url_dup(3).
+
+This function sets or updates individual URL components, or parts, held by the
+URL object the handle identifies.
+
+The *part* argument should identify the particular URL part (see list
+below) to set or change, with *content* pointing to a null-terminated
+string with the new contents for that URL part. The contents should be in the
+form and encoding they would use in a URL: URL encoded.
+
+When setting part in the URL object that was previously already set, it
+replaces the data that was previously stored for that part with the new
+*content*.
+
+The caller does not have to keep *content* around after a successful call
+as this function copies the content.
+
+Setting a part to a NULL pointer removes that part's contents from the
+*CURLU* handle.
+
+By default, this API only accepts URLs using schemes for protocols that are
+supported built-in. To make libcurl parse URLs generically even for schemes it
+does not know about, the **CURLU_NON_SUPPORT_SCHEME** flags bit must be
+set. Otherwise, this function returns *CURLUE_UNSUPPORTED_SCHEME* for URL
+schemes it does not recognize.
+
+This function has an 8 MB maximum length limit for all provided input strings.
+In the real world, excessively long fields in URLs cause problems even if this
+API accepts them.
+
+When setting or updating contents of individual URL parts, this API might
+accept data that would not be otherwise possible to set in the string when it
+gets populated as a result of a full URL parse. Beware. If done so, extracting
+a full URL later on from such components might render an invalid URL.
+
+The *flags* argument is a bitmask with independent features.
+
+# PARTS
+
+## CURLUPART_URL
+
+Allows the full URL of the handle to be replaced. If the handle already is
+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
+is replaced with the components of the newly set URL.
+
+Pass a pointer to a null-terminated string to the *url* parameter. The
+string must point to a correctly formatted "RFC 3986+" URL or be a NULL
+pointer.
+
+Unless *CURLU_NO_AUTHORITY* is set, a blank hostname is not allowed in
+the URL.
+
+## CURLUPART_SCHEME
+
+Scheme cannot be URL decoded on set. libcurl only accepts setting schemes up
+to 40 bytes long.
+
+## CURLUPART_USER
+
+## CURLUPART_PASSWORD
+
+## CURLUPART_OPTIONS
+
+The options field is an optional field that might follow the password in the
+userinfo part. It is only recognized/used when parsing URLs for the following
+schemes: pop3, smtp and imap. This function however allows users to
+independently set this field.
+
+## CURLUPART_HOST
+
+The hostname. If it is International Domain Name (IDN) the string must then be
+encoded as your locale says or UTF-8 (when WinIDN is used). If it is a
+bracketed IPv6 numeric address it may contain a zone id (or you can use
+*CURLUPART_ZONEID*).
+
+Unless *CURLU_NO_AUTHORITY* is set, a blank hostname is not allowed to set.
+
+## CURLUPART_ZONEID
+
+If the hostname is a numeric IPv6 address, this field can also be set.
+
+## CURLUPART_PORT
+
+The port number cannot be URL encoded on set. The given port number is
+provided as a string and the decimal number in it must be between 0 and
+65535. Anything else returns an error.
+
+## CURLUPART_PATH
+
+If a path is set in the URL without a leading slash, a slash is prepended
+automatically.
+
+## CURLUPART_QUERY
+
+The query part gets spaces converted to pluses when asked to URL encode on set
+with the *CURLU_URLENCODE* bit.
+
+If used together with the *CURLU_APPENDQUERY* bit, the provided part is
+appended on the end of the existing query.
+
+The question mark in the URL is not part of the actual query contents.
+
+## CURLUPART_FRAGMENT
+
+The hash sign in the URL is not part of the actual fragment contents.
+
+# FLAGS
+
+The flags argument is zero, one or more bits set in a bitmask.
+
+## CURLU_APPENDQUERY
+
+Can be used when setting the *CURLUPART_QUERY* component. The provided new
+part is then appended at the end of the existing query - and if the previous
+part did not end with an ampersand (&), an ampersand gets inserted before the
+new appended part.
+
+When *CURLU_APPENDQUERY* is used together with *CURLU_URLENCODE*, the
+first '=' symbol is not URL encoded.
+
+## CURLU_NON_SUPPORT_SCHEME
+
+If set, allows curl_url_set(3) to set a non-supported scheme.
+
+## CURLU_URLENCODE
+
+When set, curl_url_set(3) URL encodes the part on entry, except for
+scheme, port and URL.
+
+When setting the path component with URL encoding enabled, the slash character
+is be skipped.
+
+The query part gets space-to-plus conversion before the URL conversion.
+
+This URL encoding is charset unaware and converts the input in a byte-by-byte
+manner.
+
+## CURLU_DEFAULT_SCHEME
+
+If set, allows the URL to be set without a scheme and then sets that to the
+default scheme: HTTPS. Overrides the *CURLU_GUESS_SCHEME* option if both
+are set.
+
+## CURLU_GUESS_SCHEME
+
+If set, allows the URL to be set without a scheme and it instead "guesses"
+which scheme that was intended based on the hostname. If the outermost
+subdomain name matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that scheme is
+used, otherwise it picks HTTP. Conflicts with the *CURLU_DEFAULT_SCHEME*
+option which takes precedence if both are set.
+
+## CURLU_NO_AUTHORITY
+
+If set, skips authority checks. The RFC allows individual schemes to omit the
+host part (normally the only mandatory part of the authority), but libcurl
+cannot know whether this is permitted for custom schemes. Specifying the flag
+permits empty authority sections, similar to how file scheme is handled.
+
+## CURLU_PATH_AS_IS
+
+When set for **CURLUPART_URL**, this skips the normalization of the
+path. That is the procedure where libcurl otherwise removes sequences of
+dot-slash and dot-dot etc. The same option used for transfers is called
+CURLOPT_PATH_AS_IS(3).
+
+## CURLU_ALLOW_SPACE
+
+If set, the URL parser allows space (ASCII 32) where possible. The URL syntax
+does normally not allow spaces anywhere, but they should be encoded as %20
+or '+'. When spaces are allowed, they are still not allowed in the scheme.
+When space is used and allowed in a URL, it is stored as-is unless
+*CURLU_URLENCODE* is also set, which then makes libcurl URL encode the
+space before stored. This affects how the URL is constructed when
+curl_url_get(3) is subsequently used to extract the full URL or
+individual parts. (Added in 7.78.0)
+
+## CURLU_DISALLOW_USER
+
+If set, the URL parser does not accept embedded credentials for the
+**CURLUPART_URL**, and instead returns **CURLUE_USER_NOT_ALLOWED** for
+such URLs.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLUcode rc;
+ CURLU *url = curl_url();
+ rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
+ if(!rc) {
+ /* change it to an FTP URL */
+ rc = curl_url_set(url, CURLUPART_SCHEME, "ftp", 0);
+ }
+ curl_url_cleanup(url);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0. CURLUPART_ZONEID was added in 7.65.0.
+
+# RETURN VALUE
+
+Returns a *CURLUcode* error value, which is CURLUE_OK (0) if everything
+went fine. See the libcurl-errors(3) man page for the full list with
+descriptions.
+
+The input string passed to curl_url_set(3) must be shorter than eight
+million bytes. Otherwise this function returns **CURLUE_MALFORMED_INPUT**.
+
+If this function returns an error, no URL part is set.
diff --git a/docs/libcurl/curl_url_strerror.3 b/docs/libcurl/curl_url_strerror.3
deleted file mode 100644
index b3fd40379..000000000
--- a/docs/libcurl/curl_url_strerror.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_url_strerror 3 "21 Aug 2021" "libcurl" "libcurl"
-.SH NAME
-curl_url_strerror - return string describing error code
-.SH SYNOPSIS
-.nf
-.B #include <curl/curl.h>
-.BI "const char *curl_url_strerror(CURLUcode " errornum ");"
-.SH DESCRIPTION
-This function returns a string describing the CURLUcode error code passed in
-the argument \fIerrornum\fP.
-.SH EXAMPLE
-.nf
- CURLUcode rc;
- CURLU *url = curl_url();
- rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
- if(rc)
- printf("URL error: %s\\n", curl_url_strerror(rc));
- curl_url_cleanup(url);
-.fi
-
-.SH AVAILABILITY
-Added in 7.80.0
-.SH RETURN VALUE
-A pointer to a null-terminated string.
-.SH "SEE ALSO"
-.BR curl_easy_strerror (3),
-.BR curl_multi_strerror (3),
-.BR curl_share_strerror (3),
-.BR curl_url_get (3),
-.BR curl_url_set (3),
-.BR libcurl-errors (3)
diff --git a/docs/libcurl/curl_url_strerror.md b/docs/libcurl/curl_url_strerror.md
new file mode 100644
index 000000000..26562aa21
--- /dev/null
+++ b/docs/libcurl/curl_url_strerror.md
@@ -0,0 +1,53 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_url_strerror
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_strerror (3)
+ - curl_multi_strerror (3)
+ - curl_share_strerror (3)
+ - curl_url_get (3)
+ - curl_url_set (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+curl_url_strerror - return string describing error code
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const char *curl_url_strerror(CURLUcode errornum);
+~~~
+
+# DESCRIPTION
+
+This function returns a string describing the CURLUcode error code passed in
+the argument *errornum*.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLUcode rc;
+ CURLU *url = curl_url();
+ rc = curl_url_set(url, CURLUPART_URL, "https://example.com", 0);
+ if(rc)
+ printf("URL error: %s\n", curl_url_strerror(rc));
+ curl_url_cleanup(url);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.80.0
+
+# RETURN VALUE
+
+A pointer to a null-terminated string.
diff --git a/docs/libcurl/curl_version.3 b/docs/libcurl/curl_version.3
deleted file mode 100644
index 0036778e7..000000000
--- a/docs/libcurl/curl_version.3
+++ /dev/null
@@ -1,49 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH curl_version 3 "5 March 2001" "libcurl" "libcurl"
-.SH NAME
-curl_version - returns the libcurl version string
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-char *curl_version();
-.fi
-.SH DESCRIPTION
-Returns a human readable string with the version number of libcurl and some of
-its important components (like OpenSSL version).
-
-We recommend using \fIcurl_version_info(3)\fP instead!
-.SH EXAMPLE
-.nf
-printf("libcurl version %s\\n", curl_version());
-.fi
-
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-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/curl_version.md b/docs/libcurl/curl_version.md
new file mode 100644
index 000000000..3a3cb359b
--- /dev/null
+++ b/docs/libcurl/curl_version.md
@@ -0,0 +1,46 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_version
+Section: 3
+Source: libcurl
+See-also:
+ - curl_version_info (3)
+---
+
+# NAME
+
+curl_version - returns the libcurl version string
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+char *curl_version();
+~~~
+
+# DESCRIPTION
+
+Returns a human readable string with the version number of libcurl and some of
+its important components (like OpenSSL version).
+
+We recommend using curl_version_info(3) instead!
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ printf("libcurl version %s\n", curl_version());
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+A pointer to a null-terminated string. The string resides in a statically
+allocated buffer and must not be freed by the caller.
diff --git a/docs/libcurl/curl_version_info.3 b/docs/libcurl/curl_version_info.3
deleted file mode 100644
index ac07abee3..000000000
--- a/docs/libcurl/curl_version_info.3
+++ /dev/null
@@ -1,320 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_version_info 3 "2 Nov 2014" "libcurl" "libcurl"
-.SH NAME
-curl_version_info - returns runtime libcurl version info
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-curl_version_info_data *curl_version_info(CURLversion age);
-.fi
-.SH DESCRIPTION
-Returns a pointer to a filled in static struct with information about various
-features in the running version of libcurl. \fIage\fP should be set to the
-version of this functionality by the time you write your program. This way,
-libcurl always returns a proper struct that your program understands, while
-programs in the future might get a different struct. \fBCURLVERSION_NOW\fP is
-the most recent one for the library you have installed:
-.nf
- data = curl_version_info(CURLVERSION_NOW);
-.fi
-Applications should use this information to judge if things are possible to do
-or not, instead of using compile-time checks, as dynamic/DLL libraries can be
-changed independent of applications.
-
-This function can alter the returned static data as long as
-\fIcurl_global_init(3)\fP has not been called. It is therefore not thread-safe
-before libcurl initialization occurs.
-
-The curl_version_info_data struct looks like this
-
-.nf
-typedef struct {
- CURLversion age; /* see description below */
-
- const char *version; /* human readable string */
- unsigned int version_num; /* numeric representation */
- const char *host; /* human readable string */
- int features; /* bitmask, see below */
- char *ssl_version; /* human readable string */
- long ssl_version_num; /* not used, always zero */
- const char *libz_version; /* human readable string */
- const char *const *protocols; /* protocols */
-
- /* when 'age' is CURLVERSION_SECOND or higher, the members below exist */
- const char *ares; /* human readable string */
- int ares_num; /* number */
-
- /* when 'age' is CURLVERSION_THIRD or higher, the members below exist */
- const char *libidn; /* human readable string */
-
- /* when 'age' is CURLVERSION_FOURTH or higher (>= 7.16.1), the members
- below exist */
- int iconv_ver_num; /* '_libiconv_version' if iconv support enabled */
-
- const char *libssh_version; /* human readable string */
-
- /* when 'age' is CURLVERSION_FIFTH or higher (>= 7.57.0), the members
- below exist */
- unsigned int brotli_ver_num; /* Numeric Brotli version
- (MAJOR << 24) | (MINOR << 12) | PATCH */
- const char *brotli_version; /* human readable string. */
-
- /* when 'age' is CURLVERSION_SIXTH or higher (>= 7.66.0), the members
- below exist */
- unsigned int nghttp2_ver_num; /* Numeric nghttp2 version
- (MAJOR << 16) | (MINOR << 8) | PATCH */
- const char *nghttp2_version; /* human readable string. */
-
- const char *quic_version; /* human readable quic (+ HTTP/3) library +
- version or NULL */
-
- /* when 'age' is CURLVERSION_SEVENTH or higher (>= 7.70.0), the members
- below exist */
- const char *cainfo; /* the built-in default CURLOPT_CAINFO, might
- be NULL */
- const char *capath; /* the built-in default CURLOPT_CAPATH, might
- be NULL */
- /* when 'age' is CURLVERSION_EIGHTH or higher (>= 7.71.0), the members
- below exist */
- unsigned int zstd_ver_num; /* Numeric Zstd version
- (MAJOR << 24) | (MINOR << 12) | PATCH */
- const char *zstd_version; /* human readable string. */
- /* when 'age' is CURLVERSION_NINTH or higher (>= 7.75.0), the members
- below exist */
- const char *hyper_version; /* human readable string. */
- /* when 'age' is CURLVERSION_TENTH or higher (>= 7.77.0), the members
- below exist */
- const char *gsasl_version; /* human readable string. */
- /* when 'age' is CURLVERSION_ELEVENTH or higher (>= 7.87.0), the members
- below exist */
- const char *const *feature_names; /* Feature names. */
-} curl_version_info_data;
-.fi
-
-\fIage\fP describes what the age of this struct is. The number depends on how
-new the libcurl you are using is. You are however guaranteed to get a struct
-that you have a matching struct for in the header, as you tell libcurl your
-"age" with the input argument.
-
-\fIversion\fP is just an ascii string for the libcurl version.
-
-\fIversion_num\fP is a 24 bit number created like this: <8 bits major number>
-| <8 bits minor number> | <8 bits patch number>. Version 7.9.8 is therefore
-returned as 0x070908.
-
-\fIhost\fP is an ascii string showing what host information that this libcurl
-was built for. As discovered by a configure script or set by the build
-environment.
-
-\fIfeatures\fP is a bit mask representing available features. It can
-have none, one or more bits set.
-The use of this field is deprecated: use \fIfeature_names\fP instead.
-The feature names description below lists the associated bits.
-
-\fIfeature_names\fP is a pointer to an array of string pointers, containing the
-names of the features that libcurl supports. The array is terminated by a NULL
-entry. Currently defined names are:
-.RS
-.IP """alt-svc"""
-\fIfeatures\fP mask bit: CURL_VERSION_ALTSVC
-.br
-HTTP Alt-Svc parsing and the associated options (Added in 7.64.1)
-.IP """AsynchDNS"""
-\fIfeatures\fP mask bit: CURL_VERSION_ASYNCHDNS
-.br
-libcurl was built with support for asynchronous name lookups, which allows
-more exact timeouts (even on Windows) and less blocking when using the multi
-interface. (added in 7.10.7)
-.IP """brotli"""
-\fIfeatures\fP mask bit: CURL_VERSION_BROTLI
-.br
-supports HTTP Brotli content encoding using libbrotlidec (Added in 7.57.0)
-.IP """Debug"""
-\fIfeatures\fP mask bit: CURL_VERSION_DEBUG
-.br
-libcurl was built with debug capabilities (added in 7.10.6)
-.IP """gsasl"""
-\fIfeatures\fP mask bit: CURL_VERSION_GSASL
-.br
-libcurl was built with libgsasl and thus with some extra SCRAM-SHA
-authentication methods. (added in 7.76.0)
-.IP """GSS-API"""
-\fIfeatures\fP mask bit: CURL_VERSION_GSSAPI
-.br
-libcurl was built with support for GSS-API. This makes libcurl use provided
-functions for Kerberos and SPNEGO authentication. It also allows libcurl
-to use the current user credentials without the app having to pass them on.
-(Added in 7.38.0)
-.IP """HSTS"""
-\fIfeatures\fP mask bit: CURL_VERSION_HSTS
-.br
-libcurl was built with support for HSTS (HTTP Strict Transport Security)
-(Added in 7.74.0)
-.IP """HTTP2"""
-\fIfeatures\fP mask bit: CURL_VERSION_HTTP2
-.br
-libcurl was built with support for HTTP2.
-(Added in 7.33.0)
-.IP """HTTP3"""
-\fIfeatures\fP mask bit: CURL_VERSION_HTTP3
-.br
-HTTP/3 and QUIC support are built-in (Added in 7.66.0)
-.IP """HTTPS-proxy"""
-\fIfeatures\fP mask bit: CURL_VERSION_HTTPS_PROXY
-.br
-libcurl was built with support for HTTPS-proxy.
-(Added in 7.52.0)
-.IP """IDN"""
-\fIfeatures\fP mask bit: CURL_VERSION_IDN
-.br
-libcurl was built with support for IDNA, domain names with international
-letters. (Added in 7.12.0)
-.IP """IPv6"""
-\fIfeatures\fP mask bit: CURL_VERSION_IPV6
-.br
-supports IPv6
-.IP """Kerberos"""
-\fIfeatures\fP mask bit: CURL_VERSION_KERBEROS5
-.br
-supports Kerberos V5 authentication for FTP, IMAP, LDAP, POP3, SMTP and
-SOCKSv5 proxy. (Added in 7.40.0)
-.IP """Largefile"""
-\fIfeatures\fP mask bit: CURL_VERSION_LARGEFILE
-.br
-libcurl was built with support for large files. (Added in 7.11.1)
-.IP """libz"""
-\fIfeatures\fP mask bit: CURL_VERSION_LIBZ
-.br
-supports HTTP deflate using libz (Added in 7.10)
-.IP """MultiSSL"""
-\fIfeatures\fP mask bit: CURL_VERSION_MULTI_SSL
-.br
-libcurl was built with multiple SSL backends. For details, see
-\fIcurl_global_sslset(3)\fP.
-(Added in 7.56.0)
-.IP """NTLM"""
-\fIfeatures\fP mask bit: CURL_VERSION_NTLM
-.br
-supports HTTP NTLM (added in 7.10.6)
-.IP """NTLM_WB"""
-\fIfeatures\fP mask bit: CURL_VERSION_NTLM_WB
-.br
-libcurl was built with support for NTLM delegation to a winbind helper.
-(Added in 7.22.0)
-.IP """PSL"""
-\fIfeatures\fP mask bit: CURL_VERSION_PSL
-.br
-libcurl was built with support for Mozilla's Public Suffix List. This makes
-libcurl ignore cookies with a domain that is on the list.
-(Added in 7.47.0)
-.IP """SPNEGO"""
-\fIfeatures\fP mask bit: CURL_VERSION_SPNEGO
-.br
-libcurl was built with support for SPNEGO authentication (Simple and Protected
-GSS-API Negotiation Mechanism, defined in RFC 2478.) (added in 7.10.8)
-.IP """SSL"""
-\fIfeatures\fP mask bit: CURL_VERSION_SSL
-.br
-supports SSL (HTTPS/FTPS) (Added in 7.10)
-.IP """SSPI"""
-\fIfeatures\fP mask bit: CURL_VERSION_SSPI
-.br
-libcurl was built with support for SSPI. This is only available on Windows and
-makes libcurl use Windows-provided functions for Kerberos, NTLM, SPNEGO and
-Digest authentication. It also allows libcurl to use the current user
-credentials without the app having to pass them on. (Added in 7.13.2)
-.IP """threadsafe"""
-\fIfeatures\fP mask bit: CURL_VERSION_THREADSAFE
-.br
-libcurl was built with thread-safety support (Atomic or SRWLOCK) to protect
-curl initialization. (Added in 7.84.0) See \fIlibcurl-thread(3)\fP
-.IP """TLS-SRP"""
-\fIfeatures\fP mask bit: CURL_VERSION_TLSAUTH_SRP
-.br
-libcurl was built with support for TLS-SRP (in one or more of the built-in TLS
-backends). (Added in 7.21.4)
-.IP """TrackMemory"""
-\fIfeatures\fP mask bit: CURL_VERSION_CURLDEBUG
-.br
-libcurl was built with memory tracking debug capabilities. This is mainly of
-interest for libcurl hackers. (added in 7.19.6)
-.IP """Unicode"""
-\fIfeatures\fP mask bit: CURL_VERSION_UNICODE
-.br
-libcurl was built with Unicode support on Windows. This makes non-ASCII
-characters work in filenames and options passed to libcurl. (Added in 7.72.0)
-.IP """UnixSockets"""
-\fIfeatures\fP mask bit: CURL_VERSION_UNIX_SOCKETS
-.br
-libcurl was built with support for Unix domain sockets.
-(Added in 7.40.0)
-.IP """zstd"""
-\fIfeatures\fP mask bit: CURL_VERSION_ZSTD
-.br
-supports HTTP zstd content encoding using zstd library (Added in 7.72.0)
-.IP none
-\fIfeatures\fP mask bit: CURL_VERSION_CONV
-.br
-libcurl was built with support for character conversions, as provided by the
-CURLOPT_CONV_* callbacks. Always 0 since 7.82.0. (Added in 7.15.4)
-.IP none
-\fIfeatures\fP mask bit: CURL_VERSION_GSSNEGOTIATE
-.br
-supports HTTP GSS-Negotiate (added in 7.10.6, deprecated in 7.38.0)
-.IP none
-\fIfeatures\fP mask bit: CURL_VERSION_KERBEROS4
-.br
-supports Kerberos V4 (when using FTP). Legacy bit. Deprecated since 7.33.0.
-.RE
-
-\fIssl_version\fP is an ASCII string for the TLS library name + version
-used. If libcurl has no SSL support, this is NULL. For example "Schannel",
-\&"Secure Transport" or "OpenSSL/1.1.0g".
-
-\fIssl_version_num\fP is always 0.
-
-\fIlibz_version\fP is an ASCII string (there is no numerical version). If
-libcurl has no libz support, this is NULL.
-
-\fIprotocols\fP is a pointer to an array of char * pointers, containing the
-names protocols that libcurl supports (using lowercase letters). The protocol
-names are the same as would be used in URLs. The array is terminated by a NULL
-entry.
-.SH EXAMPLE
-.nf
-curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
-printf("libcurl version %u.%u.%u\\n",
- (ver->version_num >> 16) & 0xff,
- (ver->version_num >> 8) & 0xff,
- ver->version_num & 0xff);
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-A pointer to a curl_version_info_data struct.
-.SH "SEE ALSO"
-\fIcurl_version(3)\fP
diff --git a/docs/libcurl/curl_version_info.md b/docs/libcurl/curl_version_info.md
new file mode 100644
index 000000000..9fc764e18
--- /dev/null
+++ b/docs/libcurl/curl_version_info.md
@@ -0,0 +1,381 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_version_info
+Section: 3
+Source: libcurl
+See-also:
+ - curl_version (3)
+---
+
+# NAME
+
+curl_version_info - returns runtime libcurl version info
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+curl_version_info_data *curl_version_info(CURLversion age);
+~~~
+
+# DESCRIPTION
+
+Returns a pointer to a filled in static struct with information about various
+features in the running version of libcurl. *age* should be set to the
+version of this functionality by the time you write your program. This way,
+libcurl always returns a proper struct that your program understands, while
+programs in the future might get a different struct. **CURLVERSION_NOW** is
+the most recent one for the library you have installed:
+~~~c
+ data = curl_version_info(CURLVERSION_NOW);
+~~~
+Applications should use this information to judge if things are possible to do
+or not, instead of using compile-time checks, as dynamic/DLL libraries can be
+changed independent of applications.
+
+This function can alter the returned static data as long as
+curl_global_init(3) has not been called. It is therefore not thread-safe
+before libcurl initialization occurs.
+
+The curl_version_info_data struct looks like this
+
+~~~c
+typedef struct {
+ CURLversion age; /* see description below */
+
+ const char *version; /* human readable string */
+ unsigned int version_num; /* numeric representation */
+ const char *host; /* human readable string */
+ int features; /* bitmask, see below */
+ char *ssl_version; /* human readable string */
+ long ssl_version_num; /* not used, always zero */
+ const char *libz_version; /* human readable string */
+ const char *const *protocols; /* protocols */
+
+ /* when 'age' is CURLVERSION_SECOND or higher, the members below exist */
+ const char *ares; /* human readable string */
+ int ares_num; /* number */
+
+ /* when 'age' is CURLVERSION_THIRD or higher, the members below exist */
+ const char *libidn; /* human readable string */
+
+ /* when 'age' is CURLVERSION_FOURTH or higher (>= 7.16.1), the members
+ below exist */
+ int iconv_ver_num; /* '_libiconv_version' if iconv support enabled */
+
+ const char *libssh_version; /* human readable string */
+
+ /* when 'age' is CURLVERSION_FIFTH or higher (>= 7.57.0), the members
+ below exist */
+ unsigned int brotli_ver_num; /* Numeric Brotli version
+ (MAJOR << 24) | (MINOR << 12) | PATCH */
+ const char *brotli_version; /* human readable string. */
+
+ /* when 'age' is CURLVERSION_SIXTH or higher (>= 7.66.0), the members
+ below exist */
+ unsigned int nghttp2_ver_num; /* Numeric nghttp2 version
+ (MAJOR << 16) | (MINOR << 8) | PATCH */
+ const char *nghttp2_version; /* human readable string. */
+
+ const char *quic_version; /* human readable quic (+ HTTP/3) library +
+ version or NULL */
+
+ /* when 'age' is CURLVERSION_SEVENTH or higher (>= 7.70.0), the members
+ below exist */
+ const char *cainfo; /* the built-in default CURLOPT_CAINFO, might
+ be NULL */
+ const char *capath; /* the built-in default CURLOPT_CAPATH, might
+ be NULL */
+ /* when 'age' is CURLVERSION_EIGHTH or higher (>= 7.71.0), the members
+ below exist */
+ unsigned int zstd_ver_num; /* Numeric Zstd version
+ (MAJOR << 24) | (MINOR << 12) | PATCH */
+ const char *zstd_version; /* human readable string. */
+ /* when 'age' is CURLVERSION_NINTH or higher (>= 7.75.0), the members
+ below exist */
+ const char *hyper_version; /* human readable string. */
+ /* when 'age' is CURLVERSION_TENTH or higher (>= 7.77.0), the members
+ below exist */
+ const char *gsasl_version; /* human readable string. */
+ /* when 'age' is CURLVERSION_ELEVENTH or higher (>= 7.87.0), the members
+ below exist */
+ const char *const *feature_names; /* Feature names. */
+} curl_version_info_data;
+~~~
+
+*age* describes what the age of this struct is. The number depends on how
+new the libcurl you are using is. You are however guaranteed to get a struct
+that you have a matching struct for in the header, as you tell libcurl your
+"age" with the input argument.
+
+*version* is just an ascii string for the libcurl version.
+
+*version_num* is a 24 bit number created like this: <8 bits major number>
+| <8 bits minor number> | <8 bits patch number>. Version 7.9.8 is therefore
+returned as 0x070908.
+
+*host* is an ascii string showing what host information that this libcurl
+was built for. As discovered by a configure script or set by the build
+environment.
+
+*features* is a bit mask representing available features. It can have none,
+one or more bits set. The use of this field is deprecated: use
+*feature_names* instead. The feature names description below lists the
+associated bits.
+
+*feature_names* is a pointer to an array of string pointers, containing the
+names of the features that libcurl supports. The array is terminated by a NULL
+entry. See the list of features names below.
+
+*ssl_version* is an ASCII string for the TLS library name + version used. If
+libcurl has no SSL support, this is NULL. For example "Schannel", "Secure
+Transport" or "OpenSSL/1.1.0g".
+
+*ssl_version_num* is always 0.
+
+*libz_version* is an ASCII string (there is no numerical version). If
+libcurl has no libz support, this is NULL.
+
+*protocols* is a pointer to an array of char * pointers, containing the
+names protocols that libcurl supports (using lowercase letters). The protocol
+names are the same as would be used in URLs. The array is terminated by a NULL
+entry.
+
+# FEATURES
+
+## alt-svc
+
+*features* mask bit: CURL_VERSION_ALTSVC
+
+HTTP Alt-Svc parsing and the associated options (Added in 7.64.1)
+
+## AsynchDNS
+
+*features* mask bit: CURL_VERSION_ASYNCHDNS
+
+libcurl was built with support for asynchronous name lookups, which allows
+more exact timeouts (even on Windows) and less blocking when using the multi
+interface. (added in 7.10.7)
+
+## brotli
+
+*features* mask bit: CURL_VERSION_BROTLI
+
+supports HTTP Brotli content encoding using libbrotlidec (Added in 7.57.0)
+
+## Debug
+
+*features* mask bit: CURL_VERSION_DEBUG
+
+libcurl was built with debug capabilities (added in 7.10.6)
+
+## gsasl
+
+*features* mask bit: CURL_VERSION_GSASL
+
+libcurl was built with libgsasl and thus with some extra SCRAM-SHA
+authentication methods. (added in 7.76.0)
+
+## GSS-API
+
+*features* mask bit: CURL_VERSION_GSSAPI
+
+libcurl was built with support for GSS-API. This makes libcurl use provided
+functions for Kerberos and SPNEGO authentication. It also allows libcurl
+to use the current user credentials without the app having to pass them on.
+(Added in 7.38.0)
+
+## HSTS
+
+*features* mask bit: CURL_VERSION_HSTS
+
+libcurl was built with support for HSTS (HTTP Strict Transport Security)
+(Added in 7.74.0)
+
+## HTTP2
+
+*features* mask bit: CURL_VERSION_HTTP2
+
+libcurl was built with support for HTTP2.
+(Added in 7.33.0)
+
+## HTTP3
+
+*features* mask bit: CURL_VERSION_HTTP3
+
+HTTP/3 and QUIC support are built-in (Added in 7.66.0)
+
+## HTTPS-proxy
+
+*features* mask bit: CURL_VERSION_HTTPS_PROXY
+
+libcurl was built with support for HTTPS-proxy.
+(Added in 7.52.0)
+
+## IDN
+
+*features* mask bit: CURL_VERSION_IDN
+
+libcurl was built with support for IDNA, domain names with international
+letters. (Added in 7.12.0)
+
+## IPv6
+
+*features* mask bit: CURL_VERSION_IPV6
+
+supports IPv6
+
+## Kerberos
+
+*features* mask bit: CURL_VERSION_KERBEROS5
+
+supports Kerberos V5 authentication for FTP, IMAP, LDAP, POP3, SMTP and
+SOCKSv5 proxy. (Added in 7.40.0)
+
+## Largefile
+
+*features* mask bit: CURL_VERSION_LARGEFILE
+
+libcurl was built with support for large files. (Added in 7.11.1)
+
+## libz
+
+*features* mask bit: CURL_VERSION_LIBZ
+
+supports HTTP deflate using libz (Added in 7.10)
+
+## MultiSSL
+
+*features* mask bit: CURL_VERSION_MULTI_SSL
+
+libcurl was built with multiple SSL backends. For details, see
+curl_global_sslset(3).
+(Added in 7.56.0)
+
+## NTLM
+
+*features* mask bit: CURL_VERSION_NTLM
+
+supports HTTP NTLM (added in 7.10.6)
+
+## NTLM_WB
+
+*features* mask bit: CURL_VERSION_NTLM_WB
+
+libcurl was built with support for NTLM delegation to a winbind helper.
+(Added in 7.22.0)
+
+## PSL
+
+*features* mask bit: CURL_VERSION_PSL
+
+libcurl was built with support for Mozilla's Public Suffix List. This makes
+libcurl ignore cookies with a domain that is on the list.
+(Added in 7.47.0)
+
+## SPNEGO
+
+*features* mask bit: CURL_VERSION_SPNEGO
+
+libcurl was built with support for SPNEGO authentication (Simple and Protected
+GSS-API Negotiation Mechanism, defined in RFC 2478.) (added in 7.10.8)
+
+## SSL
+
+*features* mask bit: CURL_VERSION_SSL
+
+supports SSL (HTTPS/FTPS) (Added in 7.10)
+
+## SSPI
+
+*features* mask bit: CURL_VERSION_SSPI
+
+libcurl was built with support for SSPI. This is only available on Windows and
+makes libcurl use Windows-provided functions for Kerberos, NTLM, SPNEGO and
+Digest authentication. It also allows libcurl to use the current user
+credentials without the app having to pass them on. (Added in 7.13.2)
+
+## threadsafe
+
+*features* mask bit: CURL_VERSION_THREADSAFE
+
+libcurl was built with thread-safety support (Atomic or SRWLOCK) to protect
+curl initialization. (Added in 7.84.0) See libcurl-thread(3)
+
+## TLS-SRP
+
+*features* mask bit: CURL_VERSION_TLSAUTH_SRP
+
+libcurl was built with support for TLS-SRP (in one or more of the built-in TLS
+backends). (Added in 7.21.4)
+
+## TrackMemory
+
+*features* mask bit: CURL_VERSION_CURLDEBUG
+
+libcurl was built with memory tracking debug capabilities. This is mainly of
+interest for libcurl hackers. (added in 7.19.6)
+
+## Unicode
+
+*features* mask bit: CURL_VERSION_UNICODE
+
+libcurl was built with Unicode support on Windows. This makes non-ASCII
+characters work in filenames and options passed to libcurl. (Added in 7.72.0)
+
+## UnixSockets
+
+*features* mask bit: CURL_VERSION_UNIX_SOCKETS
+
+libcurl was built with support for Unix domain sockets.
+(Added in 7.40.0)
+
+## zstd
+
+*features* mask bit: CURL_VERSION_ZSTD
+
+supports HTTP zstd content encoding using zstd library (Added in 7.72.0)
+
+## no name
+
+*features* mask bit: CURL_VERSION_CONV
+
+libcurl was built with support for character conversions, as provided by the
+CURLOPT_CONV_* callbacks. Always 0 since 7.82.0. (Added in 7.15.4,
+deprecated.)
+
+## no name
+
+*features* mask bit: CURL_VERSION_GSSNEGOTIATE
+
+supports HTTP GSS-Negotiate (added in 7.10.6, deprecated in 7.38.0)
+
+## no name
+
+*features* mask bit: CURL_VERSION_KERBEROS4
+
+supports Kerberos V4 (when using FTP). Legacy bit. Deprecated since 7.33.0.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ curl_version_info_data *ver = curl_version_info(CURLVERSION_NOW);
+ printf("libcurl version %u.%u.%u\n",
+ (ver->version_num >> 16) & 0xff,
+ (ver->version_num >> 8) & 0xff,
+ ver->version_num & 0xff);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+A pointer to a curl_version_info_data struct.
+curl_version(3)
diff --git a/docs/libcurl/curl_ws_meta.3 b/docs/libcurl/curl_ws_meta.3
deleted file mode 100644
index d9ab43a11..000000000
--- a/docs/libcurl/curl_ws_meta.3
+++ /dev/null
@@ -1,121 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_ws_meta 3 "12 Jun 2022" "libcurl" "libcurl"
-.SH NAME
-curl_ws_meta - meta data WebSocket information
-.SH SYNOPSIS
-.nf
-#include <curl/easy.h>
-
-struct curl_ws_frame {
- int age; /* zero */
- int flags; /* See the CURLWS_* defines */
- curl_off_t offset; /* the offset of this data into the frame */
- curl_off_t bytesleft; /* number of pending bytes left of the payload */
-};
-
-const struct curl_ws_frame *curl_ws_meta(CURL *curl);
-.fi
-.SH DESCRIPTION
-This function call is EXPERIMENTAL.
-
-When the write callback (\fICURLOPT_WRITEFUNCTION(3)\fP) is invoked on
-received WebSocket traffic, \fIcurl_ws_meta(3)\fP can be called from within
-the callback to provide additional information about the current frame.
-
-This function only works from within the callback, and only when receiving
-WebSocket data.
-
-This function requires an easy handle as input argument for libcurl to know
-what transfer the question is about, but as there is no such pointer provided
-to the callback by libcurl itself, applications that want to use
-\fIcurl_ws_meta(3)\fP need to pass it on to the callback on its own.
-
-.SH "struct fields"
-.IP age
-This field specify the age of this struct. It is always zero for now.
-.IP flags
-This is a bitmask with individual bits set that describes the WebSocket
-data. See the list below.
-.IP offset
-When this frame is a continuation of fragment data already delivered, this is
-the offset into the final fragment where this piece belongs.
-.IP bytesleft
-If this is not a complete fragment, the \fIbytesleft\fP field informs about
-how many additional bytes are expected to arrive before this fragment is
-complete.
-.SH FLAGS
-.IP CURLWS_TEXT
-The buffer contains text data. Note that this makes a difference to WebSocket
-but libcurl itself does not make any verification of the content or
-precautions that you actually receive valid UTF-8 content.
-.IP CURLWS_BINARY
-This is binary data.
-.IP CURLWS_CONT
-This is not the final fragment of the message, it implies that there is
-another fragment coming as part of the same message.
-.IP CURLWS_CLOSE
-This transfer is now closed.
-.IP CURLWS_PING
-This as an incoming ping message, that expects a pong response.
-.SH EXAMPLE
-.nf
-
-/* we pass a pointer to this struct to the callback */
-struct customdata {
- CURL *easy;
- void *ptr;
-};
-
-static size_t writecb(unsigned char *buffer,
- size_t size, size_t nitems, void *p)
-{
- struct customdata *c = (struct customdata *)p;
- const struct curl_ws_frame *m = curl_ws_meta(c->easy);
-
- /* m->flags tells us about the traffic */
-}
-
-{
- struct customdata custom;
- custom.easy = easy;
- custom.ptr = NULL;
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, &custom);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.86.0.
-.SH RETURN VALUE
-This function returns a pointer to a \fIcurl_ws_frame\fP struct with read-only
-information that is valid for this specific callback invocation. If it cannot
-return this information, or if the function is called in the wrong context, it
-returns NULL.
-.SH "SEE ALSO"
-.BR curl_easy_setopt (3),
-.BR curl_easy_getinfo (3),
-.BR curl_ws_send (3),
-.BR curl_ws_recv (3),
-.BR libcurl-ws (3)
diff --git a/docs/libcurl/curl_ws_meta.md b/docs/libcurl/curl_ws_meta.md
new file mode 100644
index 000000000..531791a51
--- /dev/null
+++ b/docs/libcurl/curl_ws_meta.md
@@ -0,0 +1,143 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_ws_meta
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+ - curl_ws_recv (3)
+ - curl_ws_send (3)
+ - libcurl-ws (3)
+---
+
+# NAME
+
+curl_ws_meta - meta data WebSocket information
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+const struct curl_ws_frame *curl_ws_meta(CURL *curl);
+~~~
+
+# DESCRIPTION
+
+This function call is EXPERIMENTAL.
+
+When the write callback (CURLOPT_WRITEFUNCTION(3)) is invoked on
+received WebSocket traffic, curl_ws_meta(3) can be called from within
+the callback to provide additional information about the current frame.
+
+This function only works from within the callback, and only when receiving
+WebSocket data.
+
+This function requires an easy handle as input argument for libcurl to know
+what transfer the question is about, but as there is no such pointer provided
+to the callback by libcurl itself, applications that want to use
+curl_ws_meta(3) need to pass it on to the callback on its own.
+
+# struct curl_ws_frame
+
+~~~c
+struct curl_ws_frame {
+ int age;
+ int flags;
+ curl_off_t offset;
+ curl_off_t bytesleft;
+};
+~~~
+
+## age
+
+This field specify the age of this struct. It is always zero for now.
+
+## flags
+
+This is a bitmask with individual bits set that describes the WebSocket
+data. See the list below.
+
+## offset
+
+When this frame is a continuation of fragment data already delivered, this is
+the offset into the final fragment where this piece belongs.
+
+## bytesleft
+
+If this is not a complete fragment, the *bytesleft* field informs about
+how many additional bytes are expected to arrive before this fragment is
+complete.
+
+# FLAGS
+
+## CURLWS_TEXT
+
+The buffer contains text data. Note that this makes a difference to WebSocket
+but libcurl itself does not make any verification of the content or
+precautions that you actually receive valid UTF-8 content.
+
+## CURLWS_BINARY
+
+This is binary data.
+
+## CURLWS_CONT
+
+This is not the final fragment of the message, it implies that there is
+another fragment coming as part of the same message.
+
+## CURLWS_CLOSE
+
+This transfer is now closed.
+
+## CURLWS_PING
+
+This as an incoming ping message, that expects a pong response.
+
+# EXAMPLE
+
+~~~c
+
+/* we pass a pointer to this struct to the callback */
+struct customdata {
+ CURL *easy;
+ void *ptr;
+};
+
+static size_t writecb(unsigned char *buffer,
+ size_t size, size_t nitems, void *p)
+{
+ struct customdata *c = (struct customdata *)p;
+ const struct curl_ws_frame *m = curl_ws_meta(c->easy);
+
+ printf("flags: %x\n", m->flags);
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct customdata custom;
+ custom.easy = curl;
+ custom.ptr = NULL;
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &custom);
+
+ curl_easy_perform(curl);
+
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.86.0.
+
+# RETURN VALUE
+
+This function returns a pointer to a *curl_ws_frame* struct with read-only
+information that is valid for this specific callback invocation. If it cannot
+return this information, or if the function is called in the wrong context, it
+returns NULL.
diff --git a/docs/libcurl/curl_ws_recv.3 b/docs/libcurl/curl_ws_recv.3
deleted file mode 100644
index a9df029e8..000000000
--- a/docs/libcurl/curl_ws_recv.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_ws_recv 3 "12 Jun 2022" "libcurl" "libcurl"
-.SH NAME
-curl_ws_recv - receive WebSocket data
-.SH SYNOPSIS
-.nf
-#include <curl/easy.h>
-
-CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
- size_t *recv, const struct curl_ws_frame **meta);
-.fi
-.SH DESCRIPTION
-This function call is EXPERIMENTAL.
-
-Retrieves as much as possible of a received WebSocket data fragment into the
-\fBbuffer\fP, but not more than \fBbuflen\fP bytes. \fIrecv\fP is set to the
-number of bytes actually stored.
-
-If there is more fragment data to deliver than what fits in the provided
-\fIbuffer\fP, libcurl returns a full buffer and the application needs to call
-this function again to continue draining the buffer.
-
-The \fImeta\fP pointer gets set to point to a \fIconst struct curl_ws_frame\fP
-that contains information about the received data. See the
-\fIcurl_ws_meta(3)\fP for details on that struct.
-.SH EXAMPLE
-.nf
- size_t rlen;
- const struct curl_ws_frame *meta;
- char buffer[256];
- CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
-.fi
-.SH AVAILABILITY
-Added in 7.86.0.
-.SH RETURN VALUE
-Returns \fBCURLE_OK\fP if everything is okay, and a non-zero number for
-errors. Returns \fBCURLE_GOT_NOTHING\fP if the associated connection is
-closed.
-
-Instead of blocking, the function returns \fBCURLE_AGAIN\fP. The correct
-behavior is then to wait for the socket to signal readability before calling
-this function again.
-.SH "SEE ALSO"
-.BR curl_easy_setopt (3),
-.BR curl_easy_perform (3),
-.BR curl_easy_getinfo (3),
-.BR curl_ws_send (3),
-.BR libcurl-ws (3)
diff --git a/docs/libcurl/curl_ws_recv.md b/docs/libcurl/curl_ws_recv.md
new file mode 100644
index 000000000..d801eddee
--- /dev/null
+++ b/docs/libcurl/curl_ws_recv.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_ws_recv
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_perform (3)
+ - curl_easy_setopt (3)
+ - curl_ws_send (3)
+ - libcurl-ws (3)
+---
+
+# NAME
+
+curl_ws_recv - receive WebSocket data
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
+ size_t *recv, const struct curl_ws_frame **meta);
+~~~
+
+# DESCRIPTION
+
+This function call is EXPERIMENTAL.
+
+Retrieves as much as possible of a received WebSocket data fragment into the
+**buffer**, but not more than **buflen** bytes. *recv* is set to the
+number of bytes actually stored.
+
+If there is more fragment data to deliver than what fits in the provided
+*buffer*, libcurl returns a full buffer and the application needs to call
+this function again to continue draining the buffer.
+
+The *meta* pointer gets set to point to a *const struct curl_ws_frame*
+that contains information about the received data. See the
+curl_ws_meta(3) for details on that struct.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+ char buffer[256];
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
+ if(res)
+ printf("error: %s\n", curl_easy_strerror(res));
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.86.0.
+
+# RETURN VALUE
+
+Returns **CURLE_OK** if everything is okay, and a non-zero number for
+errors. Returns **CURLE_GOT_NOTHING** if the associated connection is
+closed.
+
+Instead of blocking, the function returns **CURLE_AGAIN**. The correct
+behavior is then to wait for the socket to signal readability before calling
+this function again.
diff --git a/docs/libcurl/curl_ws_send.3 b/docs/libcurl/curl_ws_send.3
deleted file mode 100644
index 9df2cc164..000000000
--- a/docs/libcurl/curl_ws_send.3
+++ /dev/null
@@ -1,102 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH curl_ws_send 3 "12 Jun 2022" "libcurl" "libcurl"
-.SH NAME
-curl_ws_send - send WebSocket data
-.SH SYNOPSIS
-.nf
-#include <curl/easy.h>
-
-CURLcode curl_ws_send(CURL *curl, const void *buffer, size_t buflen,
- size_t *sent, curl_off_t fragsize,
- unsigned int flags);
-.fi
-.SH DESCRIPTION
-This function call is EXPERIMENTAL.
-
-Send the specific message fragment over an established WebSocket
-connection. The \fIbuffer\fP holds the data to send and it is \fIbuflen\fP
-number of payload bytes in that memory area.
-
-\fIsent\fP is returned as the number of payload bytes actually sent.
-
-To send a (huge) fragment using multiple calls with partial content per
-invoke, set the \fICURLWS_OFFSET\fP bit and the \fIfragsize\fP argument as the
-total expected size for the first part, then set the \fICURLWS_OFFSET\fP with
-a zero \fIfragsize\fP for the following parts.
-
-If not sending a partial fragment or if this is raw mode, \fIfragsize\fP
-should be set to zero.
-
-If \fBCURLWS_RAW_MODE\fP is enabled in \fICURLOPT_WS_OPTIONS(3)\fP, the
-\fBflags\fP argument should be set to 0.
-
-To send a message consisting of multiple frames, set the \fICURLWS_CONT\fP bit
-in all frames except the final one.
-.SH FLAGS
-.IP CURLWS_TEXT
-The buffer contains text data. Note that this makes a difference to WebSocket
-but libcurl itself does not make any verification of the content or
-precautions that you actually send valid UTF-8 content.
-.IP CURLWS_BINARY
-This is binary data.
-.IP CURLWS_CONT
-This is not the final fragment of the message, which implies that there is
-another fragment coming as part of the same message where this bit is not set.
-.IP CURLWS_CLOSE
-Close this transfer.
-.IP CURLWS_PING
-This is a ping.
-.IP CURLWS_PONG
-This is a pong.
-.IP CURLWS_OFFSET
-The provided data is only a partial fragment and there is more coming in a
-following call to \fIcurl_ws_send()\fP. When sending only a piece of the
-fragment like this, the \fIfragsize\fP must be provided with the total
-expected fragment size in the first call and it needs to be zero in subsequent
-calls.
-.SH EXAMPLE
-.nf
-int ping(CURL *curl, const char *send_payload)
-{
- size_t sent;
- CURLcode result =
- curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
- CURLWS_PING);
- return (int)result;
-}
-.fi
-.SH AVAILABILITY
-Added in 7.86.0.
-.SH RETURN VALUE
-\fICURLE_OK\fP (zero) means that the data was sent properly, non-zero means an
-error occurred as \fI<curl/curl.h>\fP defines. See the \fIlibcurl-errors(3)\fP
-man page for the full list with descriptions.
-.SH "SEE ALSO"
-.BR curl_easy_setopt (3),
-.BR curl_easy_perform (3),
-.BR curl_easy_getinfo (3),
-.BR curl_ws_recv (3),
-.BR libcurl-ws (3)
diff --git a/docs/libcurl/curl_ws_send.md b/docs/libcurl/curl_ws_send.md
new file mode 100644
index 000000000..a5a056c9d
--- /dev/null
+++ b/docs/libcurl/curl_ws_send.md
@@ -0,0 +1,120 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: curl_ws_send
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_perform (3)
+ - curl_easy_setopt (3)
+ - curl_ws_recv (3)
+ - libcurl-ws (3)
+---
+
+# NAME
+
+curl_ws_send - send WebSocket data
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_ws_send(CURL *curl, const void *buffer, size_t buflen,
+ size_t *sent, curl_off_t fragsize,
+ unsigned int flags);
+~~~
+
+# DESCRIPTION
+
+This function call is EXPERIMENTAL.
+
+Send the specific message fragment over an established WebSocket
+connection. The *buffer* holds the data to send and it is *buflen*
+number of payload bytes in that memory area.
+
+*sent* is returned as the number of payload bytes actually sent.
+
+To send a (huge) fragment using multiple calls with partial content per
+invoke, set the *CURLWS_OFFSET* bit and the *fragsize* argument as the
+total expected size for the first part, then set the *CURLWS_OFFSET* with
+a zero *fragsize* for the following parts.
+
+If not sending a partial fragment or if this is raw mode, *fragsize*
+should be set to zero.
+
+If **CURLWS_RAW_MODE** is enabled in CURLOPT_WS_OPTIONS(3), the
+**flags** argument should be set to 0.
+
+To send a message consisting of multiple frames, set the *CURLWS_CONT* bit
+in all frames except the final one.
+
+# FLAGS
+
+## CURLWS_TEXT
+
+The buffer contains text data. Note that this makes a difference to WebSocket
+but libcurl itself does not make any verification of the content or
+precautions that you actually send valid UTF-8 content.
+
+## CURLWS_BINARY
+
+This is binary data.
+
+## CURLWS_CONT
+
+This is not the final fragment of the message, which implies that there is
+another fragment coming as part of the same message where this bit is not set.
+
+## CURLWS_CLOSE
+
+Close this transfer.
+
+## CURLWS_PING
+
+This is a ping.
+
+## CURLWS_PONG
+
+This is a pong.
+
+## CURLWS_OFFSET
+
+The provided data is only a partial fragment and there is more coming in a
+following call to *curl_ws_send()*. When sending only a piece of the
+fragment like this, the *fragsize* must be provided with the total
+expected fragment size in the first call and it needs to be zero in subsequent
+calls.
+
+# EXAMPLE
+
+~~~c
+#include <string.h> /* for strlen */
+
+const char *send_payload = "magic";
+
+int main(void)
+{
+ size_t sent;
+ CURLcode res;
+ CURL *curl = curl_easy_init();
+ curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com/");
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L);
+ curl_easy_perform(curl);
+ res = curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
+ CURLWS_PING);
+ curl_easy_cleanup(curl);
+ return (int)res;
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.86.0.
+
+# RETURN VALUE
+
+*CURLE_OK* (zero) means that the data was sent properly, non-zero means an
+error occurred as *<curl/curl.h>* defines. See the libcurl-errors(3)
+man page for the full list with descriptions.
diff --git a/docs/libcurl/libcurl-easy.3 b/docs/libcurl/libcurl-easy.3
deleted file mode 100644
index 1842c2116..000000000
--- a/docs/libcurl/libcurl-easy.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH libcurl 3 "19 Sep 2014" "libcurl" "libcurl"
-.SH NAME
-libcurl-easy \- easy interface overview
-.SH DESCRIPTION
-When using libcurl's "easy" interface you init your session and get a handle
-(often referred to as an "easy handle"), which you use as input to the easy
-interface functions you use. Use \fIcurl_easy_init(3)\fP to get the handle.
-
-You continue by setting all the options you want in the upcoming transfer, the
-most important among them is the URL itself (you cannot transfer anything
-without a specified URL as you may have figured out yourself). You might want
-to set some callbacks as well that are called from the library when data is
-available etc. \fIcurl_easy_setopt(3)\fP is used for all this.
-
-\fICURLOPT_URL(3)\fP is the only option you really must set, as otherwise
-there can be no transfer. Another commonly used option is
-\fICURLOPT_VERBOSE(3)\fP that helps you see what libcurl is doing under the
-hood, which is useful when debugging for example. The
-\fIcurl_easy_setopt(3)\fP man page has a full index of the almost 300
-available options.
-
-If you at any point would like to blank all previously set options for a
-single easy handle, you can call \fIcurl_easy_reset(3)\fP and you can also
-make a clone of an easy handle (with all its set options) using
-\fIcurl_easy_duphandle(3)\fP.
-
-When all is setup, you tell libcurl to perform the transfer using
-\fIcurl_easy_perform(3)\fP. It performs the entire transfer operation and does
-not return until it is done (successfully or not).
-
-After the transfer has been made, you can set new options and make another
-transfer, or if you are done, cleanup the session by calling
-\fIcurl_easy_cleanup(3)\fP. If you want persistent connections, you do not
-cleanup immediately, but instead run ahead and perform other transfers using
-the same easy handle.
-.SH "SEE ALSO"
-.BR curl_easy_init (3),
-.BR curl_easy_cleanup (3),
-.BR curl_easy_setopt (3),
-.BR libcurl-errors (3),
-.BR libcurl-multi (3),
-.BR libcurl (3)
diff --git a/docs/libcurl/libcurl-easy.md b/docs/libcurl/libcurl-easy.md
new file mode 100644
index 000000000..f456c97be
--- /dev/null
+++ b/docs/libcurl/libcurl-easy.md
@@ -0,0 +1,52 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_cleanup (3)
+ - curl_easy_init (3)
+ - curl_easy_setopt (3)
+ - libcurl (3)
+ - libcurl-errors (3)
+ - libcurl-multi (3)
+---
+
+# NAME
+
+libcurl-easy - easy interface overview
+
+# DESCRIPTION
+
+When using libcurl's "easy" interface you init your session and get a handle
+(often referred to as an "easy handle"), which you use as input to the easy
+interface functions you use. Use curl_easy_init(3) to get the handle.
+
+You continue by setting all the options you want in the upcoming transfer, the
+most important among them is the URL itself (you cannot transfer anything
+without a specified URL as you may have figured out yourself). You might want
+to set some callbacks as well that are called from the library when data is
+available etc. curl_easy_setopt(3) is used for all this.
+
+CURLOPT_URL(3) is the only option you really must set, as otherwise
+there can be no transfer. Another commonly used option is
+CURLOPT_VERBOSE(3) that helps you see what libcurl is doing under the
+hood, which is useful when debugging for example. The
+curl_easy_setopt(3) man page has a full index of the almost 300
+available options.
+
+If you at any point would like to blank all previously set options for a
+single easy handle, you can call curl_easy_reset(3) and you can also
+make a clone of an easy handle (with all its set options) using
+curl_easy_duphandle(3).
+
+When all is setup, you tell libcurl to perform the transfer using
+curl_easy_perform(3). It performs the entire transfer operation and does
+not return until it is done (successfully or not).
+
+After the transfer has been made, you can set new options and make another
+transfer, or if you are done, cleanup the session by calling
+curl_easy_cleanup(3). If you want persistent connections, you do not
+cleanup immediately, but instead run ahead and perform other transfers using
+the same easy handle.
diff --git a/docs/libcurl/libcurl-env-dbg.3 b/docs/libcurl/libcurl-env-dbg.3
deleted file mode 100644
index 6995a8ede..000000000
--- a/docs/libcurl/libcurl-env-dbg.3
+++ /dev/null
@@ -1,97 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH libcurl-env-dbg 3 "18 September 2023" "libcurl" "libcurl"
-.SH NAME
-libcurl-env-dbg \- environment variables libcurl DEBUGBUILD understands
-.SH DESCRIPTION
-This is a set of variables only recognized and used if libcurl was built
-"debug enabled", which should never be true for a library used in production.
-These variables are intended for internal use only, subject to change and have
-many effects on the behavior of libcurl. Refer to the source code to determine
-how exactly they are being used.
-.RS
-.IP "CURL_ALTSVC_HTTP"
-Bypass the AltSvc HTTPS protocol restriction if this variable exists.
-.IP "CURL_DBG_SOCK_RBLOCK"
-The percentage of recv() calls that should be answered with a EAGAIN at random.
-For TCP/UNIX sockets.
-.IP "CURL_DBG_SOCK_RMAX"
-The maximum data that shall be received from the network in one recv() call.
-For TCP/UNIX sockets. This is applied to every recv.
-
-Example: \fBCURL_DBG_SOCK_RMAX=400\fP means recv buffer size is limited to a
-maximum of 400 bytes.
-.IP "CURL_DBG_SOCK_WBLOCK"
-The percentage of send() calls that should be answered with a EAGAIN at random.
-For TCP/UNIX sockets.
-.IP "CURL_DBG_SOCK_WPARTIAL"
-The percentage of data that shall be written to the network. For TCP/UNIX
-sockets. This is applied to every send.
-
-Example: \fBCURL_DBG_SOCK_WPARTIAL=80\fP means a send with 1000 bytes would
-only send 800.
-.IP "CURL_DBG_QUIC_WBLOCK"
-The percentage of send() calls that should be answered with EAGAIN at random.
-QUIC only.
-.IP "CURL_DEBUG"
-Trace logging behavior as an alternative to calling \fIcurl_global_trace(3)\fP.
-
-Example: \fBCURL_DEBUG=http/2\fP means trace details about HTTP/2 handling.
-.IP "CURL_DEBUG_SIZE"
-Fake the size returned by CURLINFO_HEADER_SIZE and CURLINFO_REQUEST_SIZE.
-.IP "CURL_GETHOSTNAME"
-Fake the local machine's unqualified hostname for NTLM and SMTP.
-.IP "CURL_HSTS_HTTP"
-Bypass the HSTS HTTPS protocol restriction if this variable exists.
-.IP "CURL_FORCETIME"
-A time of 0 is used for AWS signatures and NTLM if this variable exists.
-.IP "CURL_ENTROPY"
-A fixed faked value to use instead of a proper random number so that functions
-in libcurl that are otherwise getting random outputs can be tested for what
-they generate.
-.IP "CURL_SMALLREQSEND"
-An alternative size of HTTP data to be sent at a time only if smaller than the
-current.
-.IP "CURL_SMALLSENDS"
-An alternative size of socket data to be sent at a time only if smaller than
-the current.
-.IP "CURL_TIME"
-Fake unix timestamp to use for AltSvc, HSTS and CURLINFO variables that are
-time related.
-
-This variable can also be used to fake the data returned by some CURLINFO
-variables that are not time-related (such as CURLINFO_LOCAL_PORT), and in that
-case the value is not a timestamp.
-.IP "CURL_TRACE"
-LDAP tracing is enabled if this variable exists and its value is 1 or greater.
-
-OpenLDAP tracing is separate. Refer to CURL_OPENLDAP_TRACE.
-.IP "CURL_NTLM_WB_FILE"
-Debug-version of the \fIntlm-wb\fP executable.
-.IP "CURL_OPENLDAP_TRACE"
-OpenLDAP tracing is enabled if this variable exists and its value is 1 or
-greater. There's a number of debug levels, refer to \fIopenldap.c\fP comments.
-.RE
-.SH "SEE ALSO"
-.BR libcurl-env (3)
diff --git a/docs/libcurl/libcurl-env-dbg.md b/docs/libcurl/libcurl-env-dbg.md
new file mode 100644
index 000000000..21b763bb4
--- /dev/null
+++ b/docs/libcurl/libcurl-env-dbg.md
@@ -0,0 +1,118 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-env-dbg
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl-env (3)
+---
+
+# NAME
+
+libcurl-env-dbg - environment variables libcurl DEBUGBUILD understands
+
+# DESCRIPTION
+
+This is a set of variables only recognized and used if libcurl was built
+"debug enabled", which should never be true for a library used in production.
+These variables are intended for internal use only, subject to change and have
+many effects on the behavior of libcurl. Refer to the source code to determine
+how exactly they are being used.
+
+## CURL_ALTSVC_HTTP
+
+Bypass the AltSvc HTTPS protocol restriction if this variable exists.
+
+## CURL_DBG_SOCK_RBLOCK
+
+The percentage of recv() calls that should be answered with a EAGAIN at random.
+For TCP/UNIX sockets.
+
+## CURL_DBG_SOCK_RMAX
+
+The maximum data that shall be received from the network in one recv() call.
+For TCP/UNIX sockets. This is applied to every recv.
+
+Example: **CURL_DBG_SOCK_RMAX=400** means recv buffer size is limited to a
+maximum of 400 bytes.
+
+## CURL_DBG_SOCK_WBLOCK
+
+The percentage of send() calls that should be answered with a EAGAIN at random.
+For TCP/UNIX sockets.
+
+## CURL_DBG_SOCK_WPARTIAL
+
+The percentage of data that shall be written to the network. For TCP/UNIX
+sockets. This is applied to every send.
+
+Example: **CURL_DBG_SOCK_WPARTIAL=80** means a send with 1000 bytes would
+only send 800.
+
+## CURL_DBG_QUIC_WBLOCK
+
+The percentage of send() calls that should be answered with EAGAIN at random.
+QUIC only.
+
+## CURL_DEBUG
+
+Trace logging behavior as an alternative to calling curl_global_trace(3).
+
+Example: **CURL_DEBUG=http/2** means trace details about HTTP/2 handling.
+
+## CURL_DEBUG_SIZE
+
+Fake the size returned by CURLINFO_HEADER_SIZE and CURLINFO_REQUEST_SIZE.
+
+## CURL_GETHOSTNAME
+
+Fake the local machine's unqualified hostname for NTLM and SMTP.
+
+## CURL_HSTS_HTTP
+
+Bypass the HSTS HTTPS protocol restriction if this variable exists.
+
+## CURL_FORCETIME
+
+A time of 0 is used for AWS signatures and NTLM if this variable exists.
+
+## CURL_ENTROPY
+
+A fixed faked value to use instead of a proper random number so that functions
+in libcurl that are otherwise getting random outputs can be tested for what
+they generate.
+
+## CURL_SMALLREQSEND
+
+An alternative size of HTTP data to be sent at a time only if smaller than the
+current.
+
+## CURL_SMALLSENDS
+
+An alternative size of socket data to be sent at a time only if smaller than
+the current.
+
+## CURL_TIME
+
+Fake unix timestamp to use for AltSvc, HSTS and CURLINFO variables that are
+time related.
+
+This variable can also be used to fake the data returned by some CURLINFO
+variables that are not time-related (such as CURLINFO_LOCAL_PORT), and in that
+case the value is not a timestamp.
+
+## CURL_TRACE
+
+LDAP tracing is enabled if this variable exists and its value is 1 or greater.
+
+OpenLDAP tracing is separate. Refer to CURL_OPENLDAP_TRACE.
+
+## CURL_NTLM_WB_FILE
+
+Debug-version of the *ntlm-wb* executable.
+
+## CURL_OPENLDAP_TRACE
+
+OpenLDAP tracing is enabled if this variable exists and its value is 1 or
+greater. There is a number of debug levels, refer to *openldap.c* comments.
diff --git a/docs/libcurl/libcurl-env.3 b/docs/libcurl/libcurl-env.3
deleted file mode 100644
index c2ba43215..000000000
--- a/docs/libcurl/libcurl-env.3
+++ /dev/null
@@ -1,92 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH libcurl-env 3 "20 January 2018" "libcurl" "libcurl"
-.SH NAME
-libcurl-env \- environment variables libcurl understands
-.SH DESCRIPTION
-libcurl reads and understands a set of environment variables that if set
-controls and changes behaviors. This is the full list of variables to set and
-description of what they do. Also note that curl, the command line tool,
-supports a set of additional environment variables independently of this.
-.RS
-.IP "[scheme]_proxy"
-When libcurl is given a URL to use in a transfer, it first extracts the scheme
-part from the URL and checks if there is a given proxy set for that in its
-corresponding environment variable. A URL like https://example.com makes
-libcurl use the \fBhttp_proxy\fP variable, while a URL like ftp://example.com
-uses the \fBftp_proxy\fP variable.
-
-These proxy variables are also checked for in their uppercase versions, except
-the \fBhttp_proxy\fP one which is only used lowercase. Note also that some
-systems actually have a case insensitive handling of environment variables and
-then of course \fBHTTP_PROXY\fP still works.
-
-An exception exists for the WebSocket \fBws\fP and \fBwss\fP URL schemes,
-where libcurl first checks \fBws_proxy\fP or \fBwss_proxy\fP but if they are
-not set, it will fall back and try the http and https versions instead if set.
-.IP ALL_PROXY
-This is a setting to set proxy for all URLs, independently of what scheme is
-being used. Note that the scheme specific variables overrides this one if set.
-.IP CURL_SSL_BACKEND
-When libcurl is built to support multiple SSL backends, it selects a specific
-backend at first use. If no selection is done by the program using libcurl,
-this variable's selection is used. Setting a name that is not a built-in
-alternative makes libcurl stay with the default.
-
-SSL backend names (case-insensitive): BearSSL, GnuTLS, mbedTLS,
-nss, OpenSSL, rustls, Schannel, Secure-Transport, wolfSSL
-.IP HOME
-When the netrc feature is used (\fICURLOPT_NETRC(3)\fP), this variable is
-checked as the primary way to find the "current" home directory in which
-the .netrc file is likely to exist.
-.IP USERPROFILE
-When the netrc feature is used (\fICURLOPT_NETRC(3)\fP), this variable is
-checked as the secondary way to find the "current" home directory (on Windows
-only) in which the .netrc file is likely to exist.
-.IP LOGNAME
-User name to use when invoking the \fIntlm-wb\fP tool, if \fINTLMUSER\fP was
-not set.
-.IP NO_PROXY
-This has the same functionality as the \fICURLOPT_NOPROXY(3)\fP option: it
-gives libcurl a comma-separated list of host name patterns for which libcurl
-should not use a proxy.
-.IP NTLMUSER
-User name to use when invoking the \fIntlm-wb\fP tool.
-.IP SSLKEYLOGFILE
-When set and libcurl runs with a SSL backend that supports this feature,
-libcurl saves SSL secrets into the given file name. Using those SSL secrets,
-other tools (such as Wireshark) can decrypt the SSL communication and
-analyze/view the traffic.
-
-These secrets and this file might be sensitive. Users are advised to take
-precautions so that they are not stolen or otherwise inadvertently revealed.
-.IP USER
-User name to use when invoking the \fIntlm-wb\fP tool, if \fINTLMUSER\fP and
-\fILOGNAME\fP were not set.
-.RE
-.SH "Debug Variables"
-Debug variables are intended for internal use and are documented in
-\fIlibcurl-env-dbg(3)\fP.
-.SH "SEE ALSO"
-.BR libcurl-env-dbg (3)
diff --git a/docs/libcurl/libcurl-env.md b/docs/libcurl/libcurl-env.md
new file mode 100644
index 000000000..bd3e29c73
--- /dev/null
+++ b/docs/libcurl/libcurl-env.md
@@ -0,0 +1,99 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-env
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl-env-dbg (3)
+---
+
+# NAME
+
+libcurl-env - environment variables libcurl understands
+
+# DESCRIPTION
+
+libcurl reads and understands a set of environment variables that if set
+controls and changes behaviors. This is the full list of variables to set and
+description of what they do. Also note that curl, the command line tool,
+supports a set of additional environment variables independently of this.
+
+## [scheme]_proxy
+
+When libcurl is given a URL to use in a transfer, it first extracts the scheme
+part from the URL and checks if there is a given proxy set for that in its
+corresponding environment variable. A URL like https://example.com makes
+libcurl use the **http_proxy** variable, while a URL like ftp://example.com
+uses the **ftp_proxy** variable.
+
+These proxy variables are also checked for in their uppercase versions, except
+the **http_proxy** one which is only used lowercase. Note also that some
+systems actually have a case insensitive handling of environment variables and
+then of course **HTTP_PROXY** still works.
+
+An exception exists for the WebSocket **ws** and **wss** URL schemes,
+where libcurl first checks **ws_proxy** or **wss_proxy** but if they are
+not set, it will fall back and try the http and https versions instead if set.
+
+## ALL_PROXY
+
+This is a setting to set proxy for all URLs, independently of what scheme is
+being used. Note that the scheme specific variables overrides this one if set.
+
+## CURL_SSL_BACKEND
+
+When libcurl is built to support multiple SSL backends, it selects a specific
+backend at first use. If no selection is done by the program using libcurl,
+this variable's selection is used. Setting a name that is not a built-in
+alternative makes libcurl stay with the default.
+
+SSL backend names (case-insensitive): BearSSL, GnuTLS, mbedTLS,
+nss, OpenSSL, rustls, Schannel, Secure-Transport, wolfSSL
+
+## HOME
+
+When the netrc feature is used (CURLOPT_NETRC(3)), this variable is
+checked as the primary way to find the "current" home directory in which
+the .netrc file is likely to exist.
+
+## USERPROFILE
+
+When the netrc feature is used (CURLOPT_NETRC(3)), this variable is
+checked as the secondary way to find the "current" home directory (on Windows
+only) in which the .netrc file is likely to exist.
+
+## LOGNAME
+
+User name to use when invoking the *ntlm-wb* tool, if *NTLMUSER* was
+not set.
+
+## NO_PROXY
+
+This has the same functionality as the CURLOPT_NOPROXY(3) option: it
+gives libcurl a comma-separated list of hostname patterns for which libcurl
+should not use a proxy.
+
+## NTLMUSER
+
+User name to use when invoking the *ntlm-wb* tool.
+
+## SSLKEYLOGFILE
+
+When set and libcurl runs with a SSL backend that supports this feature,
+libcurl saves SSL secrets into the given filename. Using those SSL secrets,
+other tools (such as Wireshark) can decrypt the SSL communication and
+analyze/view the traffic.
+
+These secrets and this file might be sensitive. Users are advised to take
+precautions so that they are not stolen or otherwise inadvertently revealed.
+
+## USER
+
+User name to use when invoking the *ntlm-wb* tool, if *NTLMUSER* and
+*LOGNAME* were not set.
+
+# Debug Variables
+
+Debug variables are intended for internal use and are documented in
+libcurl-env-dbg(3).
diff --git a/docs/libcurl/libcurl-errors.3 b/docs/libcurl/libcurl-errors.3
deleted file mode 100644
index f83bf6a2f..000000000
--- a/docs/libcurl/libcurl-errors.3
+++ /dev/null
@@ -1,441 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH libcurl-errors 3 "23 Nov 2021" "libcurl" "libcurl"
-.SH NAME
-libcurl-errors \- error codes in libcurl
-.SH DESCRIPTION
-This man page includes most, if not all, available error codes in libcurl.
-Why they occur and possibly what you can do to fix the problem are also included.
-.SH "CURLcode"
-Almost all "easy" interface functions return a CURLcode error code. No matter
-what, using the \fIcurl_easy_setopt(3)\fP option \fICURLOPT_ERRORBUFFER(3)\fP
-is a good idea as it gives you a human readable error string that may offer
-more details about the cause of the error than just the error code.
-\fIcurl_easy_strerror(3)\fP can be called to get an error string from a given
-CURLcode number.
-
-CURLcode is one of the following:
-.IP "CURLE_OK (0)"
-All fine. Proceed as usual.
-.IP "CURLE_UNSUPPORTED_PROTOCOL (1)"
-The URL you passed to libcurl used a protocol that this libcurl does not
-support. The support might be a compile-time option that you did not use, it
-can be a misspelled protocol string or just a protocol libcurl has no code
-for.
-.IP "CURLE_FAILED_INIT (2)"
-Early initialization code failed. This is likely to be an internal error or
-problem, or a resource problem where something fundamental could not get done
-at init time.
-.IP "CURLE_URL_MALFORMAT (3)"
-The URL was not properly formatted.
-.IP "CURLE_NOT_BUILT_IN (4)"
-A requested feature, protocol or option was not found built-in in this libcurl
-due to a build-time decision. This means that a feature or option was not
-enabled or explicitly disabled when libcurl was built and in order to get it
-to function you have to get a rebuilt libcurl.
-.IP "CURLE_COULDNT_RESOLVE_PROXY (5)"
-Could not resolve proxy. The given proxy host could not be resolved.
-.IP "CURLE_COULDNT_RESOLVE_HOST (6)"
-Could not resolve host. The given remote host was not resolved.
-.IP "CURLE_COULDNT_CONNECT (7)"
-Failed to connect() to host or proxy.
-.IP "CURLE_WEIRD_SERVER_REPLY (8)"
-The server sent data libcurl could not parse. This error code was known as
-\fICURLE_FTP_WEIRD_SERVER_REPLY\fP before 7.51.0.
-.IP "CURLE_REMOTE_ACCESS_DENIED (9)"
-We were denied access to the resource given in the URL. For FTP, this occurs
-while trying to change to the remote directory.
-.IP "CURLE_FTP_ACCEPT_FAILED (10)"
-While waiting for the server to connect back when an active FTP session is
-used, an error code was sent over the control connection or similar.
-.IP "CURLE_FTP_WEIRD_PASS_REPLY (11)"
-After having sent the FTP password to the server, libcurl expects a proper
-reply. This error code indicates that an unexpected code was returned.
-.IP "CURLE_FTP_ACCEPT_TIMEOUT (12)"
-During an active FTP session while waiting for the server to connect, the
-\fICURLOPT_ACCEPTTIMEOUT_MS(3)\fP (or the internal default) timeout expired.
-.IP "CURLE_FTP_WEIRD_PASV_REPLY (13)"
-libcurl failed to get a sensible result back from the server as a response to
-either a PASV or a EPSV command. The server is flawed.
-.IP "CURLE_FTP_WEIRD_227_FORMAT (14)"
-FTP servers return a 227-line as a response to a PASV command. If libcurl
-fails to parse that line, this return code is passed back.
-.IP "CURLE_FTP_CANT_GET_HOST (15)"
-An internal failure to lookup the host used for the new connection.
-.IP "CURLE_HTTP2 (16)"
-A problem was detected in the HTTP2 framing layer. This is somewhat generic
-and can be one out of several problems, see the error buffer for details.
-.IP "CURLE_FTP_COULDNT_SET_TYPE (17)"
-Received an error when trying to set the transfer mode to binary or ASCII.
-.IP "CURLE_PARTIAL_FILE (18)"
-A file transfer was shorter or larger than expected. This happens when the
-server first reports an expected transfer size, and then delivers data that
-does not match the previously given size.
-.IP "CURLE_FTP_COULDNT_RETR_FILE (19)"
-This was either a weird reply to a 'RETR' command or a zero byte transfer
-complete.
-.IP "Obsolete error (20)"
-Not used in modern versions.
-.IP "CURLE_QUOTE_ERROR (21)"
-When sending custom "QUOTE" commands to the remote server, one of the commands
-returned an error code that was 400 or higher (for FTP) or otherwise
-indicated unsuccessful completion of the command.
-.IP "CURLE_HTTP_RETURNED_ERROR (22)"
-This is returned if \fICURLOPT_FAILONERROR(3)\fP is set TRUE and the HTTP
-server returns an error code that is >= 400.
-.IP "CURLE_WRITE_ERROR (23)"
-An error occurred when writing received data to a local file, or an error was
-returned to libcurl from a write callback.
-.IP "Obsolete error (24)"
-Not used in modern versions.
-.IP "CURLE_UPLOAD_FAILED (25)"
-Failed starting the upload. For FTP, the server typically denied the STOR
-command. The error buffer usually contains the server's explanation for this.
-.IP "CURLE_READ_ERROR (26)"
-There was a problem reading a local file or an error returned by the read
-callback.
-.IP "CURLE_OUT_OF_MEMORY (27)"
-A memory allocation request failed. This is serious badness and
-things are severely screwed up if this ever occurs.
-.IP "CURLE_OPERATION_TIMEDOUT (28)"
-Operation timeout. The specified time-out period was reached according to the
-conditions.
-.IP "Obsolete error (29)"
-Not used in modern versions.
-.IP "CURLE_FTP_PORT_FAILED (30)"
-The FTP PORT command returned error. This mostly happens when you have not
-specified a good enough address for libcurl to use. See
-\fICURLOPT_FTPPORT(3)\fP.
-.IP "CURLE_FTP_COULDNT_USE_REST (31)"
-The FTP REST command returned error. This should never happen if the server is
-sane.
-.IP "Obsolete error (32)"
-Not used in modern versions.
-.IP "CURLE_RANGE_ERROR (33)"
-The server does not support or accept range requests.
-.IP "CURLE_HTTP_POST_ERROR (34)"
-This is an odd error that mainly occurs due to internal confusion.
-.IP "CURLE_SSL_CONNECT_ERROR (35)"
-A problem occurred somewhere in the SSL/TLS handshake. You really want the
-error buffer and read the message there as it pinpoints the problem slightly
-more. Could be certificates (file formats, paths, permissions), passwords, and
-others.
-.IP "CURLE_BAD_DOWNLOAD_RESUME (36)"
-The download could not be resumed because the specified offset was out of the
-file boundary.
-.IP "CURLE_FILE_COULDNT_READ_FILE (37)"
-A file given with FILE:// could not be opened. Most likely because the file
-path does not identify an existing file. Did you check file permissions?
-.IP "CURLE_LDAP_CANNOT_BIND (38)"
-LDAP cannot bind. LDAP bind operation failed.
-.IP "CURLE_LDAP_SEARCH_FAILED (39)"
-LDAP search failed.
-.IP "Obsolete error (40)"
-Not used in modern versions.
-.IP "CURLE_FUNCTION_NOT_FOUND (41)"
-Function not found. A required zlib function was not found.
-.IP "CURLE_ABORTED_BY_CALLBACK (42)"
-Aborted by callback. A callback returned "abort" to libcurl.
-.IP "CURLE_BAD_FUNCTION_ARGUMENT (43)"
-A function was called with a bad parameter.
-.IP "Obsolete error (44)"
-Not used in modern versions.
-.IP "CURLE_INTERFACE_FAILED (45)"
-Interface error. A specified outgoing interface could not be used. Set which
-interface to use for outgoing connections' source IP address with
-\fICURLOPT_INTERFACE(3)\fP.
-.IP "Obsolete error (46)"
-Not used in modern versions.
-.IP "CURLE_TOO_MANY_REDIRECTS (47)"
-Too many redirects. When following redirects, libcurl hit the maximum amount.
-Set your limit with \fICURLOPT_MAXREDIRS(3)\fP.
-.IP "CURLE_UNKNOWN_OPTION (48)"
-An option passed to libcurl is not recognized/known. Refer to the appropriate
-documentation. This is most likely a problem in the program that uses
-libcurl. The error buffer might contain more specific information about which
-exact option it concerns.
-.IP "CURLE_SETOPT_OPTION_SYNTAX (49)"
-An option passed in to a setopt was wrongly formatted. See error message for
-details about what option.
-.IP "Obsolete errors (50-51)"
-Not used in modern versions.
-.IP "CURLE_GOT_NOTHING (52)"
-Nothing was returned from the server, and under the circumstances, getting
-nothing is considered an error.
-.IP "CURLE_SSL_ENGINE_NOTFOUND (53)"
-The specified crypto engine was not found.
-.IP "CURLE_SSL_ENGINE_SETFAILED (54)"
-Failed setting the selected SSL crypto engine as default.
-.IP "CURLE_SEND_ERROR (55)"
-Failed sending network data.
-.IP "CURLE_RECV_ERROR (56)"
-Failure with receiving network data.
-.IP "Obsolete error (57)"
-Not used in modern versions.
-.IP "CURLE_SSL_CERTPROBLEM (58)"
-problem with the local client certificate.
-.IP "CURLE_SSL_CIPHER (59)"
-Could not use specified cipher.
-.IP "CURLE_PEER_FAILED_VERIFICATION (60)"
-The remote server's SSL certificate or SSH fingerprint was deemed not OK.
-This error code has been unified with CURLE_SSL_CACERT since 7.62.0. Its
-previous value was 51.
-.IP "CURLE_BAD_CONTENT_ENCODING (61)"
-Unrecognized transfer encoding.
-.IP "Obsolete error (62)"
-Not used in modern versions.
-.IP "CURLE_FILESIZE_EXCEEDED (63)"
-Maximum file size exceeded.
-.IP "CURLE_USE_SSL_FAILED (64)"
-Requested FTP SSL level failed.
-.IP "CURLE_SEND_FAIL_REWIND (65)"
-When doing a send operation curl had to rewind the data to retransmit, but the
-rewinding operation failed.
-.IP "CURLE_SSL_ENGINE_INITFAILED (66)"
-Initiating the SSL Engine failed.
-.IP "CURLE_LOGIN_DENIED (67)"
-The remote server denied curl to login (Added in 7.13.1)
-.IP "CURLE_TFTP_NOTFOUND (68)"
-File not found on TFTP server.
-.IP "CURLE_TFTP_PERM (69)"
-Permission problem on TFTP server.
-.IP "CURLE_REMOTE_DISK_FULL (70)"
-Out of disk space on the server.
-.IP "CURLE_TFTP_ILLEGAL (71)"
-Illegal TFTP operation.
-.IP "CURLE_TFTP_UNKNOWNID (72)"
-Unknown TFTP transfer ID.
-.IP "CURLE_REMOTE_FILE_EXISTS (73)"
-File already exists and is not overwritten.
-.IP "CURLE_TFTP_NOSUCHUSER (74)"
-This error should never be returned by a properly functioning TFTP server.
-.IP "Obsolete error (75-76)"
-Not used in modern versions.
-.IP "CURLE_SSL_CACERT_BADFILE (77)"
-Problem with reading the SSL CA cert (path? access rights?)
-.IP "CURLE_REMOTE_FILE_NOT_FOUND (78)"
-The resource referenced in the URL does not exist.
-.IP "CURLE_SSH (79)"
-An unspecified error occurred during the SSH session.
-.IP "CURLE_SSL_SHUTDOWN_FAILED (80)"
-Failed to shut down the SSL connection.
-.IP "CURLE_AGAIN (81)"
-Socket is not ready for send/recv wait till it's ready and try again. This
-return code is only returned from \fIcurl_easy_recv(3)\fP and
-\fIcurl_easy_send(3)\fP (Added in 7.18.2)
-.IP "CURLE_SSL_CRL_BADFILE (82)"
-Failed to load CRL file (Added in 7.19.0)
-.IP "CURLE_SSL_ISSUER_ERROR (83)"
-Issuer check failed (Added in 7.19.0)
-.IP "CURLE_FTP_PRET_FAILED (84)"
-The FTP server does not understand the PRET command at all or does not support
-the given argument. Be careful when using \fICURLOPT_CUSTOMREQUEST(3)\fP, a
-custom LIST command is sent with the PRET command before PASV as well. (Added
-in 7.20.0)
-.IP "CURLE_RTSP_CSEQ_ERROR (85)"
-Mismatch of RTSP CSeq numbers.
-.IP "CURLE_RTSP_SESSION_ERROR (86)"
-Mismatch of RTSP Session Identifiers.
-.IP "CURLE_FTP_BAD_FILE_LIST (87)"
-Unable to parse FTP file list (during FTP wildcard downloading).
-.IP "CURLE_CHUNK_FAILED (88)"
-Chunk callback reported error.
-.IP "CURLE_NO_CONNECTION_AVAILABLE (89)"
-(For internal use only, is never returned by libcurl) No connection available,
-the session is queued. (added in 7.30.0)
-.IP "CURLE_SSL_PINNEDPUBKEYNOTMATCH (90)"
-Failed to match the pinned key specified with \fICURLOPT_PINNEDPUBLICKEY(3)\fP.
-.IP "CURLE_SSL_INVALIDCERTSTATUS (91)"
-Status returned failure when asked with \fICURLOPT_SSL_VERIFYSTATUS(3)\fP.
-.IP "CURLE_HTTP2_STREAM (92)"
-Stream error in the HTTP/2 framing layer.
-.IP "CURLE_RECURSIVE_API_CALL (93)"
-An API function was called from inside a callback.
-.IP "CURLE_AUTH_ERROR (94)"
-An authentication function returned an error.
-.IP "CURLE_HTTP3 (95)"
-A problem was detected in the HTTP/3 layer. This is somewhat generic and can
-be one out of several problems, see the error buffer for details.
-.IP "CURLE_QUIC_CONNECT_ERROR (96)"
-QUIC connection error. This error may be caused by an SSL library error. QUIC
-is the protocol used for HTTP/3 transfers.
-.IP "CURLE_PROXY (97)"
-Proxy handshake error. \fICURLINFO_PROXY_ERROR(3)\fP provides extra details on
-the specific problem.
-.IP "CURLE_SSL_CLIENTCERT (98)"
-SSL Client Certificate required.
-.IP "CURLE_UNRECOVERABLE_POLL (99)"
-An internal call to poll() or select() returned error that is not recoverable.
-.IP "CURLE_OBSOLETE*"
-These error codes are never returned. They were used in an old libcurl version
-and are currently unused.
-.SH "CURLMcode"
-This is the generic return code used by functions in the libcurl multi
-interface. Also consider \fIcurl_multi_strerror(3)\fP.
-.IP "CURLM_CALL_MULTI_PERFORM (-1)"
-This is not really an error. It means you should call
-\fIcurl_multi_perform(3)\fP again without doing select() or similar in
-between. Before version 7.20.0 (released on February 9 2010) this could be returned by
-\fIcurl_multi_perform(3)\fP, but in later versions this return code is never
-used.
-.IP "CURLM_CALL_MULTI_SOCKET (-1)"
-An alias for \fICURLM_CALL_MULTI_PERFORM\fP. Never returned by modern libcurl
-versions.
-.IP "CURLM_OK (0)"
-Things are fine.
-.IP "CURLM_BAD_HANDLE (1)"
-The passed-in handle is not a valid \fICURLM\fP handle.
-.IP "CURLM_BAD_EASY_HANDLE (2)"
-An easy handle was not good/valid. It could mean that it is not an easy handle
-at all, or possibly that the handle already is in use by this or another multi
-handle.
-.IP "CURLM_OUT_OF_MEMORY (3)"
-You are doomed.
-.IP "CURLM_INTERNAL_ERROR (4)"
-This can only be returned if libcurl bugs. Please report it to us!
-.IP "CURLM_BAD_SOCKET (5)"
-The passed-in socket is not a valid one that libcurl already knows about.
-(Added in 7.15.4)
-.IP "CURLM_UNKNOWN_OPTION (6)"
-curl_multi_setopt() with unsupported option
-(Added in 7.15.4)
-.IP "CURLM_ADDED_ALREADY (7)"
-An easy handle already added to a multi handle was attempted to get added a
-second time. (Added in 7.32.1)
-.IP "CURLM_RECURSIVE_API_CALL (8)"
-An API function was called from inside a callback.
-.IP "CURLM_WAKEUP_FAILURE (9)"
-Wake up is unavailable or failed.
-.IP "CURLM_BAD_FUNCTION_ARGUMENT (10)"
-A function was called with a bad parameter.
-.IP "CURLM_ABORTED_BY_CALLBACK (11)"
-A multi handle callback returned error.
-.IP "CURLM_UNRECOVERABLE_POLL (12)"
-An internal call to poll() or select() returned error that is not recoverable.
-.SH "CURLSHcode"
-The "share" interface returns a \fBCURLSHcode\fP to indicate when an error has
-occurred. Also consider \fIcurl_share_strerror(3)\fP.
-.IP "CURLSHE_OK (0)"
-All fine. Proceed as usual.
-.IP "CURLSHE_BAD_OPTION (1)"
-An invalid option was passed to the function.
-.IP "CURLSHE_IN_USE (2)"
-The share object is currently in use.
-.IP "CURLSHE_INVALID (3)"
-An invalid share object was passed to the function.
-.IP "CURLSHE_NOMEM (4)"
-Not enough memory was available.
-(Added in 7.12.0)
-.IP "CURLSHE_NOT_BUILT_IN (5)"
-The requested sharing could not be done because the library you use do not have
-that particular feature enabled. (Added in 7.23.0)
-.SH "CURLUcode"
-The URL interface returns a \fICURLUcode\fP to indicate when an error has
-occurred. Also consider \fIcurl_url_strerror(3)\fP.
-.IP "CURLUE_OK (0)"
-All fine. Proceed as usual.
-.IP "CURLUE_BAD_HANDLE (1)"
-An invalid URL handle was passed as argument.
-.IP "CURLUE_BAD_PARTPOINTER (2)"
-An invalid 'part' argument was passed as argument.
-.IP "CURLUE_MALFORMED_INPUT (3)"
-A malformed input was passed to a URL API function.
-.IP "CURLUE_BAD_PORT_NUMBER (4)"
-The port number was not a decimal number between 0 and 65535.
-.IP "CURLUE_UNSUPPORTED_SCHEME (5)"
-This libcurl build does not support the given URL scheme.
-.IP "CURLUE_URLDECODE (6)"
-URL decode error, most likely because of rubbish in the input.
-.IP "CURLUE_OUT_OF_MEMORY (7)"
-A memory function failed.
-.IP "CURLUE_USER_NOT_ALLOWED (8)"
-Credentials was passed in the URL when prohibited.
-.IP "CURLUE_UNKNOWN_PART (9)"
-An unknown part ID was passed to a URL API function.
-.IP "CURLUE_NO_SCHEME (10)"
-There is no scheme part in the URL.
-.IP "CURLUE_NO_USER (11)"
-There is no user part in the URL.
-.IP "CURLUE_NO_PASSWORD (12)"
-There is no password part in the URL.
-.IP "CURLUE_NO_OPTIONS (13)"
-There is no options part in the URL.
-.IP "CURLUE_NO_HOST (14)"
-There is no host part in the URL.
-.IP "CURLUE_NO_PORT (15)"
-There is no port part in the URL.
-.IP "CURLUE_NO_QUERY (16)"
-There is no query part in the URL.
-.IP "CURLUE_NO_FRAGMENT (17)"
-There is no fragment part in the URL.
-.IP "CURLUE_NO_ZONEID (18)"
-There is no zone id set in the URL.
-.IP "CURLUE_BAD_FILE_URL (19)"
-The file:// URL is invalid.
-.IP "CURLUE_BAD_FRAGMENT (20)"
-The fragment part of the URL contained bad or invalid characters.
-.IP "CURLUE_BAD_HOSTNAME (21)"
-The hostname contained bad or invalid characters.
-.IP "CURLUE_BAD_IPV6 (22)"
-The IPv6 address hostname contained bad or invalid characters.
-.IP "CURLUE_BAD_LOGIN (23)"
-The login part of the URL contained bad or invalid characters.
-.IP "CURLUE_BAD_PASSWORD (24)"
-The password part of the URL contained bad or invalid characters.
-.IP "CURLUE_BAD_PATH (25)"
-The path part of the URL contained bad or invalid characters.
-.IP "CURLUE_BAD_QUERY (26)"
-The query part of the URL contained bad or invalid characters.
-.IP "CURLUE_BAD_SCHEME (27)"
-The scheme part of the URL contained bad or invalid characters.
-.IP "CURLUE_BAD_SLASHES (28)"
-The URL contained an invalid number of slashes.
-.IP "CURLUE_BAD_USER (29)"
-The user part of the URL contained bad or invalid characters.
-.SH "CURLHcode"
-The header interface returns a \fICURLHcode\fP to indicate when an error has
-occurred.
-.IP "CURLHE_BADINDEX (1)"
-There is no header with the requested index.
-.IP "CURLHE_MISSING (2)"
-No such header exists.
-.IP "CURLHE_NOHEADERS (3)"
-No headers at all have been recorded.
-.IP "CURLHE_NOREQUEST (4)"
-There was no such request number.
-.IP "CURLHE_OUT_OF_MEMORY (5)"
-Out of resources
-.IP "CURLHE_BAD_ARGUMENT (6)"
-One or more of the given arguments are bad.
-.IP "CURLHE_NOT_BUILT_IN (7)"
-HTTP support or the header API has been disabled in the build.
-.SH "SEE ALSO"
-.BR curl_easy_strerror (3),
-.BR curl_multi_strerror (3),
-.BR curl_share_strerror (3),
-.BR curl_url_strerror (3),
-.BR CURLOPT_ERRORBUFFER (3),
-.BR CURLOPT_VERBOSE (3),
-.BR CURLOPT_DEBUGFUNCTION (3)
diff --git a/docs/libcurl/libcurl-errors.md b/docs/libcurl/libcurl-errors.md
new file mode 100644
index 000000000..2a7c8bf71
--- /dev/null
+++ b/docs/libcurl/libcurl-errors.md
@@ -0,0 +1,757 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-errors
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_ERRORBUFFER (3)
+ - CURLOPT_VERBOSE (3)
+ - curl_easy_strerror (3)
+ - curl_multi_strerror (3)
+ - curl_share_strerror (3)
+ - curl_url_strerror (3)
+---
+
+# NAME
+
+libcurl-errors - error codes in libcurl
+
+# DESCRIPTION
+
+This man page includes most, if not all, available error codes in libcurl.
+Why they occur and possibly what you can do to fix the problem are also included.
+
+# CURLcode
+
+Almost all "easy" interface functions return a CURLcode error code. No matter
+what, using the curl_easy_setopt(3) option CURLOPT_ERRORBUFFER(3)
+is a good idea as it gives you a human readable error string that may offer
+more details about the cause of the error than just the error code.
+curl_easy_strerror(3) can be called to get an error string from a given
+CURLcode number.
+
+CURLcode is one of the following:
+
+## CURLE_OK (0)
+
+All fine. Proceed as usual.
+
+## CURLE_UNSUPPORTED_PROTOCOL (1)
+
+The URL you passed to libcurl used a protocol that this libcurl does not
+support. The support might be a compile-time option that you did not use, it
+can be a misspelled protocol string or just a protocol libcurl has no code
+for.
+
+## CURLE_FAILED_INIT (2)
+
+Early initialization code failed. This is likely to be an internal error or
+problem, or a resource problem where something fundamental could not get done
+at init time.
+
+## CURLE_URL_MALFORMAT (3)
+
+The URL was not properly formatted.
+
+## CURLE_NOT_BUILT_IN (4)
+
+A requested feature, protocol or option was not found built-in in this libcurl
+due to a build-time decision. This means that a feature or option was not
+enabled or explicitly disabled when libcurl was built and in order to get it
+to function you have to get a rebuilt libcurl.
+
+## CURLE_COULDNT_RESOLVE_PROXY (5)
+
+Could not resolve proxy. The given proxy host could not be resolved.
+
+## CURLE_COULDNT_RESOLVE_HOST (6)
+
+Could not resolve host. The given remote host was not resolved.
+
+## CURLE_COULDNT_CONNECT (7)
+
+Failed to connect() to host or proxy.
+
+## CURLE_WEIRD_SERVER_REPLY (8)
+
+The server sent data libcurl could not parse. This error code was known as
+*CURLE_FTP_WEIRD_SERVER_REPLY* before 7.51.0.
+
+## CURLE_REMOTE_ACCESS_DENIED (9)
+
+We were denied access to the resource given in the URL. For FTP, this occurs
+while trying to change to the remote directory.
+
+## CURLE_FTP_ACCEPT_FAILED (10)
+
+While waiting for the server to connect back when an active FTP session is
+used, an error code was sent over the control connection or similar.
+
+## CURLE_FTP_WEIRD_PASS_REPLY (11)
+
+After having sent the FTP password to the server, libcurl expects a proper
+reply. This error code indicates that an unexpected code was returned.
+
+## CURLE_FTP_ACCEPT_TIMEOUT (12)
+
+During an active FTP session while waiting for the server to connect, the
+CURLOPT_ACCEPTTIMEOUT_MS(3) (or the internal default) timeout expired.
+
+## CURLE_FTP_WEIRD_PASV_REPLY (13)
+
+libcurl failed to get a sensible result back from the server as a response to
+either a PASV or a EPSV command. The server is flawed.
+
+## CURLE_FTP_WEIRD_227_FORMAT (14)
+
+FTP servers return a 227-line as a response to a PASV command. If libcurl
+fails to parse that line, this return code is passed back.
+
+## CURLE_FTP_CANT_GET_HOST (15)
+
+An internal failure to lookup the host used for the new connection.
+
+## CURLE_HTTP2 (16)
+
+A problem was detected in the HTTP2 framing layer. This is somewhat generic
+and can be one out of several problems, see the error buffer for details.
+
+## CURLE_FTP_COULDNT_SET_TYPE (17)
+
+Received an error when trying to set the transfer mode to binary or ASCII.
+
+## CURLE_PARTIAL_FILE (18)
+
+A file transfer was shorter or larger than expected. This happens when the
+server first reports an expected transfer size, and then delivers data that
+does not match the previously given size.
+
+## CURLE_FTP_COULDNT_RETR_FILE (19)
+
+This was either a weird reply to a 'RETR' command or a zero byte transfer
+complete.
+
+## Obsolete error (20)
+
+Not used in modern versions.
+
+## CURLE_QUOTE_ERROR (21)
+
+When sending custom "QUOTE" commands to the remote server, one of the commands
+returned an error code that was 400 or higher (for FTP) or otherwise
+indicated unsuccessful completion of the command.
+
+## CURLE_HTTP_RETURNED_ERROR (22)
+
+This is returned if CURLOPT_FAILONERROR(3) is set TRUE and the HTTP
+server returns an error code that is >= 400.
+
+## CURLE_WRITE_ERROR (23)
+
+An error occurred when writing received data to a local file, or an error was
+returned to libcurl from a write callback.
+
+## Obsolete error (24)
+
+Not used in modern versions.
+
+## CURLE_UPLOAD_FAILED (25)
+
+Failed starting the upload. For FTP, the server typically denied the STOR
+command. The error buffer usually contains the server's explanation for this.
+
+## CURLE_READ_ERROR (26)
+
+There was a problem reading a local file or an error returned by the read
+callback.
+
+## CURLE_OUT_OF_MEMORY (27)
+
+A memory allocation request failed. This is serious badness and
+things are severely screwed up if this ever occurs.
+
+## CURLE_OPERATION_TIMEDOUT (28)
+
+Operation timeout. The specified time-out period was reached according to the
+conditions.
+
+## Obsolete error (29)
+
+Not used in modern versions.
+
+## CURLE_FTP_PORT_FAILED (30)
+
+The FTP PORT command returned error. This mostly happens when you have not
+specified a good enough address for libcurl to use. See
+CURLOPT_FTPPORT(3).
+
+## CURLE_FTP_COULDNT_USE_REST (31)
+
+The FTP REST command returned error. This should never happen if the server is
+sane.
+
+## Obsolete error (32)
+
+Not used in modern versions.
+
+## CURLE_RANGE_ERROR (33)
+
+The server does not support or accept range requests.
+
+## CURLE_HTTP_POST_ERROR (34)
+
+This is an odd error that mainly occurs due to internal confusion.
+
+## CURLE_SSL_CONNECT_ERROR (35)
+
+A problem occurred somewhere in the SSL/TLS handshake. You really want the
+error buffer and read the message there as it pinpoints the problem slightly
+more. Could be certificates (file formats, paths, permissions), passwords, and
+others.
+
+## CURLE_BAD_DOWNLOAD_RESUME (36)
+
+The download could not be resumed because the specified offset was out of the
+file boundary.
+
+## CURLE_FILE_COULDNT_READ_FILE (37)
+
+A file given with FILE:// could not be opened. Most likely because the file
+path does not identify an existing file. Did you check file permissions?
+
+## CURLE_LDAP_CANNOT_BIND (38)
+
+LDAP cannot bind. LDAP bind operation failed.
+
+## CURLE_LDAP_SEARCH_FAILED (39)
+
+LDAP search failed.
+
+## Obsolete error (40)
+
+Not used in modern versions.
+
+## CURLE_FUNCTION_NOT_FOUND (41)
+
+Function not found. A required zlib function was not found.
+
+## CURLE_ABORTED_BY_CALLBACK (42)
+
+Aborted by callback. A callback returned "abort" to libcurl.
+
+## CURLE_BAD_FUNCTION_ARGUMENT (43)
+
+A function was called with a bad parameter.
+
+## Obsolete error (44)
+
+Not used in modern versions.
+
+## CURLE_INTERFACE_FAILED (45)
+
+Interface error. A specified outgoing interface could not be used. Set which
+interface to use for outgoing connections' source IP address with
+CURLOPT_INTERFACE(3).
+
+## Obsolete error (46)
+
+Not used in modern versions.
+
+## CURLE_TOO_MANY_REDIRECTS (47)
+
+Too many redirects. When following redirects, libcurl hit the maximum amount.
+Set your limit with CURLOPT_MAXREDIRS(3).
+
+## CURLE_UNKNOWN_OPTION (48)
+
+An option passed to libcurl is not recognized/known. Refer to the appropriate
+documentation. This is most likely a problem in the program that uses
+libcurl. The error buffer might contain more specific information about which
+exact option it concerns.
+
+## CURLE_SETOPT_OPTION_SYNTAX (49)
+
+An option passed in to a setopt was wrongly formatted. See error message for
+details about what option.
+
+## Obsolete errors (50-51)
+
+Not used in modern versions.
+
+## CURLE_GOT_NOTHING (52)
+
+Nothing was returned from the server, and under the circumstances, getting
+nothing is considered an error.
+
+## CURLE_SSL_ENGINE_NOTFOUND (53)
+
+The specified crypto engine was not found.
+
+## CURLE_SSL_ENGINE_SETFAILED (54)
+
+Failed setting the selected SSL crypto engine as default.
+
+## CURLE_SEND_ERROR (55)
+
+Failed sending network data.
+
+## CURLE_RECV_ERROR (56)
+
+Failure with receiving network data.
+
+## Obsolete error (57)
+
+Not used in modern versions.
+
+## CURLE_SSL_CERTPROBLEM (58)
+
+problem with the local client certificate.
+
+## CURLE_SSL_CIPHER (59)
+
+Could not use specified cipher.
+
+## CURLE_PEER_FAILED_VERIFICATION (60)
+
+The remote server's SSL certificate or SSH fingerprint was deemed not OK.
+This error code has been unified with CURLE_SSL_CACERT since 7.62.0. Its
+previous value was 51.
+
+## CURLE_BAD_CONTENT_ENCODING (61)
+
+Unrecognized transfer encoding.
+
+## Obsolete error (62)
+
+Not used in modern versions.
+
+## CURLE_FILESIZE_EXCEEDED (63)
+
+Maximum file size exceeded.
+
+## CURLE_USE_SSL_FAILED (64)
+
+Requested FTP SSL level failed.
+
+## CURLE_SEND_FAIL_REWIND (65)
+
+When doing a send operation curl had to rewind the data to retransmit, but the
+rewinding operation failed.
+
+## CURLE_SSL_ENGINE_INITFAILED (66)
+
+Initiating the SSL Engine failed.
+
+## CURLE_LOGIN_DENIED (67)
+
+The remote server denied curl to login (Added in 7.13.1)
+
+## CURLE_TFTP_NOTFOUND (68)
+
+File not found on TFTP server.
+
+## CURLE_TFTP_PERM (69)
+
+Permission problem on TFTP server.
+
+## CURLE_REMOTE_DISK_FULL (70)
+
+Out of disk space on the server.
+
+## CURLE_TFTP_ILLEGAL (71)
+
+Illegal TFTP operation.
+
+## CURLE_TFTP_UNKNOWNID (72)
+
+Unknown TFTP transfer ID.
+
+## CURLE_REMOTE_FILE_EXISTS (73)
+
+File already exists and is not overwritten.
+
+## CURLE_TFTP_NOSUCHUSER (74)
+
+This error should never be returned by a properly functioning TFTP server.
+
+## Obsolete error (75-76)
+
+Not used in modern versions.
+
+## CURLE_SSL_CACERT_BADFILE (77)
+
+Problem with reading the SSL CA cert (path? access rights?)
+
+## CURLE_REMOTE_FILE_NOT_FOUND (78)
+
+The resource referenced in the URL does not exist.
+
+## CURLE_SSH (79)
+
+An unspecified error occurred during the SSH session.
+
+## CURLE_SSL_SHUTDOWN_FAILED (80)
+
+Failed to shut down the SSL connection.
+
+## CURLE_AGAIN (81)
+
+Socket is not ready for send/recv. Wait until it is ready and try again. This
+return code is only returned from curl_easy_recv(3) and curl_easy_send(3)
+(Added in 7.18.2)
+
+## CURLE_SSL_CRL_BADFILE (82)
+
+Failed to load CRL file (Added in 7.19.0)
+
+## CURLE_SSL_ISSUER_ERROR (83)
+
+Issuer check failed (Added in 7.19.0)
+
+## CURLE_FTP_PRET_FAILED (84)
+
+The FTP server does not understand the PRET command at all or does not support
+the given argument. Be careful when using CURLOPT_CUSTOMREQUEST(3), a
+custom LIST command is sent with the PRET command before PASV as well. (Added
+in 7.20.0)
+
+## CURLE_RTSP_CSEQ_ERROR (85)
+
+Mismatch of RTSP CSeq numbers.
+
+## CURLE_RTSP_SESSION_ERROR (86)
+
+Mismatch of RTSP Session Identifiers.
+
+## CURLE_FTP_BAD_FILE_LIST (87)
+
+Unable to parse FTP file list (during FTP wildcard downloading).
+
+## CURLE_CHUNK_FAILED (88)
+
+Chunk callback reported error.
+
+## CURLE_NO_CONNECTION_AVAILABLE (89)
+
+(For internal use only, is never returned by libcurl) No connection available,
+the session is queued. (added in 7.30.0)
+
+## CURLE_SSL_PINNEDPUBKEYNOTMATCH (90)
+
+Failed to match the pinned key specified with CURLOPT_PINNEDPUBLICKEY(3).
+
+## CURLE_SSL_INVALIDCERTSTATUS (91)
+
+Status returned failure when asked with CURLOPT_SSL_VERIFYSTATUS(3).
+
+## CURLE_HTTP2_STREAM (92)
+
+Stream error in the HTTP/2 framing layer.
+
+## CURLE_RECURSIVE_API_CALL (93)
+
+An API function was called from inside a callback.
+
+## CURLE_AUTH_ERROR (94)
+
+An authentication function returned an error.
+
+## CURLE_HTTP3 (95)
+
+A problem was detected in the HTTP/3 layer. This is somewhat generic and can
+be one out of several problems, see the error buffer for details.
+
+## CURLE_QUIC_CONNECT_ERROR (96)
+
+QUIC connection error. This error may be caused by an SSL library error. QUIC
+is the protocol used for HTTP/3 transfers.
+
+## CURLE_PROXY (97)
+
+Proxy handshake error. CURLINFO_PROXY_ERROR(3) provides extra details on
+the specific problem.
+
+## CURLE_SSL_CLIENTCERT (98)
+
+SSL Client Certificate required.
+
+## CURLE_UNRECOVERABLE_POLL (99)
+
+An internal call to poll() or select() returned error that is not recoverable.
+
+## CURLE_TOO_LARGE (100)
+
+A value or data field grew larger than allowed.
+
+# CURLMcode
+
+This is the generic return code used by functions in the libcurl multi
+interface. Also consider curl_multi_strerror(3).
+
+## CURLM_CALL_MULTI_PERFORM (-1)
+
+This is not really an error. It means you should call
+curl_multi_perform(3) again without doing select() or similar in
+between. Before version 7.20.0 (released on February 9 2010) this could be returned by
+curl_multi_perform(3), but in later versions this return code is never
+used.
+
+## CURLM_OK (0)
+
+Things are fine.
+
+## CURLM_BAD_HANDLE (1)
+
+The passed-in handle is not a valid *CURLM* handle.
+
+## CURLM_BAD_EASY_HANDLE (2)
+
+An easy handle was not good/valid. It could mean that it is not an easy handle
+at all, or possibly that the handle already is in use by this or another multi
+handle.
+
+## CURLM_OUT_OF_MEMORY (3)
+
+You are doomed.
+
+## CURLM_INTERNAL_ERROR (4)
+
+This can only be returned if libcurl bugs. Please report it to us!
+
+## CURLM_BAD_SOCKET (5)
+
+The passed-in socket is not a valid one that libcurl already knows about.
+(Added in 7.15.4)
+
+## CURLM_UNKNOWN_OPTION (6)
+
+curl_multi_setopt() with unsupported option
+(Added in 7.15.4)
+
+## CURLM_ADDED_ALREADY (7)
+
+An easy handle already added to a multi handle was attempted to get added a
+second time. (Added in 7.32.1)
+
+## CURLM_RECURSIVE_API_CALL (8)
+
+An API function was called from inside a callback.
+
+## CURLM_WAKEUP_FAILURE (9)
+
+Wake up is unavailable or failed.
+
+## CURLM_BAD_FUNCTION_ARGUMENT (10)
+
+A function was called with a bad parameter.
+
+## CURLM_ABORTED_BY_CALLBACK (11)
+
+A multi handle callback returned error.
+
+## CURLM_UNRECOVERABLE_POLL (12)
+
+An internal call to poll() or select() returned error that is not recoverable.
+
+# CURLSHcode
+
+The "share" interface returns a **CURLSHcode** to indicate when an error has
+occurred. Also consider curl_share_strerror(3).
+
+## CURLSHE_OK (0)
+
+All fine. Proceed as usual.
+
+## CURLSHE_BAD_OPTION (1)
+
+An invalid option was passed to the function.
+
+## CURLSHE_IN_USE (2)
+
+The share object is currently in use.
+
+## CURLSHE_INVALID (3)
+
+An invalid share object was passed to the function.
+
+## CURLSHE_NOMEM (4)
+
+Not enough memory was available.
+(Added in 7.12.0)
+
+## CURLSHE_NOT_BUILT_IN (5)
+
+The requested sharing could not be done because the library you use do not have
+that particular feature enabled. (Added in 7.23.0)
+
+# CURLUcode
+
+The URL interface returns a *CURLUcode* to indicate when an error has
+occurred. Also consider curl_url_strerror(3).
+
+## CURLUE_OK (0)
+
+All fine. Proceed as usual.
+
+## CURLUE_BAD_HANDLE (1)
+
+An invalid URL handle was passed as argument.
+
+## CURLUE_BAD_PARTPOINTER (2)
+
+An invalid 'part' argument was passed as argument.
+
+## CURLUE_MALFORMED_INPUT (3)
+
+A malformed input was passed to a URL API function.
+
+## CURLUE_BAD_PORT_NUMBER (4)
+
+The port number was not a decimal number between 0 and 65535.
+
+## CURLUE_UNSUPPORTED_SCHEME (5)
+
+This libcurl build does not support the given URL scheme.
+
+## CURLUE_URLDECODE (6)
+
+URL decode error, most likely because of rubbish in the input.
+
+## CURLUE_OUT_OF_MEMORY (7)
+
+A memory function failed.
+
+## CURLUE_USER_NOT_ALLOWED (8)
+
+Credentials was passed in the URL when prohibited.
+
+## CURLUE_UNKNOWN_PART (9)
+
+An unknown part ID was passed to a URL API function.
+
+## CURLUE_NO_SCHEME (10)
+
+There is no scheme part in the URL.
+
+## CURLUE_NO_USER (11)
+
+There is no user part in the URL.
+
+## CURLUE_NO_PASSWORD (12)
+
+There is no password part in the URL.
+
+## CURLUE_NO_OPTIONS (13)
+
+There is no options part in the URL.
+
+## CURLUE_NO_HOST (14)
+
+There is no host part in the URL.
+
+## CURLUE_NO_PORT (15)
+
+There is no port part in the URL.
+
+## CURLUE_NO_QUERY (16)
+
+There is no query part in the URL.
+
+## CURLUE_NO_FRAGMENT (17)
+
+There is no fragment part in the URL.
+
+## CURLUE_NO_ZONEID (18)
+
+There is no zone id set in the URL.
+
+## CURLUE_BAD_FILE_URL (19)
+
+The file:// URL is invalid.
+
+## CURLUE_BAD_FRAGMENT (20)
+
+The fragment part of the URL contained bad or invalid characters.
+
+## CURLUE_BAD_HOSTNAME (21)
+
+The hostname contained bad or invalid characters.
+
+## CURLUE_BAD_IPV6 (22)
+
+The IPv6 address hostname contained bad or invalid characters.
+
+## CURLUE_BAD_LOGIN (23)
+
+The login part of the URL contained bad or invalid characters.
+
+## CURLUE_BAD_PASSWORD (24)
+
+The password part of the URL contained bad or invalid characters.
+
+## CURLUE_BAD_PATH (25)
+
+The path part of the URL contained bad or invalid characters.
+
+## CURLUE_BAD_QUERY (26)
+
+The query part of the URL contained bad or invalid characters.
+
+## CURLUE_BAD_SCHEME (27)
+
+The scheme part of the URL contained bad or invalid characters.
+
+## CURLUE_BAD_SLASHES (28)
+
+The URL contained an invalid number of slashes.
+
+## CURLUE_BAD_USER (29)
+
+The user part of the URL contained bad or invalid characters.
+
+## CURLUE_LACKS_IDN (30)
+
+libcurl lacks IDN support.
+
+## CURLUE_TOO_LARGE (31)
+
+A value or data field is larger than allowed.
+
+# CURLHcode
+
+The header interface returns a *CURLHcode* to indicate when an error has
+occurred.
+
+## CURLHE_OK (0)
+
+All fine. Proceed as usual.
+
+## CURLHE_BADINDEX (1)
+
+There is no header with the requested index.
+
+## CURLHE_MISSING (2)
+
+No such header exists.
+
+## CURLHE_NOHEADERS (3)
+
+No headers at all have been recorded.
+
+## CURLHE_NOREQUEST (4)
+
+There was no such request number.
+
+## CURLHE_OUT_OF_MEMORY (5)
+
+Out of resources
+
+## CURLHE_BAD_ARGUMENT (6)
+
+One or more of the given arguments are bad.
+
+## CURLHE_NOT_BUILT_IN (7)
+
+HTTP support or the header API has been disabled in the build.
diff --git a/docs/libcurl/libcurl-multi.3 b/docs/libcurl/libcurl-multi.3
deleted file mode 100644
index 8bd893185..000000000
--- a/docs/libcurl/libcurl-multi.3
+++ /dev/null
@@ -1,184 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH libcurl-multi 3 "19 Sep 2014" "libcurl" "libcurl"
-.SH NAME
-libcurl-multi \- how to use the multi interface
-.SH DESCRIPTION
-This is an overview on how to use the libcurl multi interface in your C
-programs. There are specific man pages for each function mentioned in
-here. There is also the \fIlibcurl-tutorial(3)\fP man page for a complete
-tutorial to programming with libcurl and the \fIlibcurl-easy(3)\fP man page
-for an overview of the libcurl easy interface.
-
-All functions in the multi interface are prefixed with curl_multi.
-.SH "OBJECTIVES"
-The multi interface offers several abilities that the easy interface does not.
-They are mainly:
-
-1. Enable a "pull" interface. The application that uses libcurl decides where
-and when to ask libcurl to get/send data.
-
-2. Enable multiple simultaneous transfers in the same thread without making it
-complicated for the application.
-
-3. Enable the application to wait for action on its own file descriptors and
-curl's file descriptors simultaneously.
-
-4. Enable event-based handling and scaling transfers up to and beyond
-thousands of parallel connections.
-.SH "ONE MULTI HANDLE MANY EASY HANDLES"
-To use the multi interface, you must first create a 'multi handle' with
-\fIcurl_multi_init(3)\fP. This handle is then used as input to all further
-curl_multi_* functions.
-
-With a multi handle and the multi interface you can do several simultaneous
-transfers in parallel. Each single transfer is built up around an easy
-handle. You create all the easy handles you need, and setup the appropriate
-options for each easy handle using \fIcurl_easy_setopt(3)\fP.
-
-There are two flavors of the multi interface, the select() oriented one and
-the event based one we call multi_socket. You benefit from reading through the
-description of both versions to fully understand how they work and
-differentiate. We start out with the select() oriented version.
-
-When an easy handle is setup and ready for transfer, then instead of using
-\fIcurl_easy_perform(3)\fP like when using the easy interface for transfers,
-you should add the easy handle to the multi handle with
-\fIcurl_multi_add_handle(3)\fP. You can add more easy handles to a multi
-handle at any point, even if other transfers are already running.
-
-Should you change your mind, the easy handle is again removed from the multi
-stack using \fIcurl_multi_remove_handle(3)\fP. Once removed from the multi
-handle, you can again use other easy interface functions like
-\fIcurl_easy_perform(3)\fP on the handle or whatever you think is
-necessary. You can remove handles at any point during transfers.
-
-Adding the easy handle to the multi handle does not start the transfer.
-Remember that one of the main ideas with this interface is to let your
-application drive. You drive the transfers by invoking
-\fIcurl_multi_perform(3)\fP. libcurl then transfers data if there is anything
-available to transfer. It uses the callbacks and everything else you have
-setup in the individual easy handles. It transfers data on all current
-transfers in the multi stack that are ready to transfer anything. It may be
-all, it may be none. When there is nothing more to do for now, it returns back
-to the calling application.
-
-Your application extracts info from libcurl about when it would like to get
-invoked to transfer data or do other work. The most convenient way is to use
-\fIcurl_multi_poll(3)\fP that helps you wait until the application should call
-libcurl again. The older API to accomplish the same thing is
-\fIcurl_multi_fdset(3)\fP that extracts \fIfd_sets\fP from libcurl to use in
-select() or poll() calls in order to get to know when the transfers in the
-multi stack might need attention. Both these APIs allow for your program to
-wait for input on your own private file descriptors at the same time.
-\fIcurl_multi_timeout(3)\fP also helps you with providing a suitable timeout
-period for your select() calls.
-
-\fIcurl_multi_perform(3)\fP stores the number of still running transfers in
-one of its input arguments, and by reading that you can figure out when all
-the transfers in the multi handles are done. 'done' does not mean
-successful. One or more of the transfers may have failed.
-
-To get information about completed transfers, to figure out success or not and
-similar, \fIcurl_multi_info_read(3)\fP should be called. It can return a
-message about a current or previous transfer. Repeated invokes of the function
-get more messages until the message queue is empty. The information you
-receive there includes an easy handle pointer which you may use to identify
-which easy handle the information regards.
-
-When a single transfer is completed, the easy handle is still left added to
-the multi stack. You need to first remove the easy handle with
-\fIcurl_multi_remove_handle(3)\fP and then close it with
-\fIcurl_easy_cleanup(3)\fP, or possibly set new options to it and add it again
-with \fIcurl_multi_add_handle(3)\fP to start another transfer.
-
-When all transfers in the multi stack are done, close the multi handle with
-\fIcurl_multi_cleanup(3)\fP. Be careful and please note that you \fBMUST\fP
-invoke separate \fIcurl_easy_cleanup(3)\fP calls for every single easy handle
-to clean them up properly.
-
-If you want to reuse an easy handle that was added to the multi handle for
-transfer, you must first remove it from the multi stack and then re-add it
-again (possibly after having altered some options at your own choice).
-.SH "MULTI_SOCKET"
-\fIcurl_multi_socket_action(3)\fP function offers a way for applications to
-not only avoid being forced to use select(), but it also offers a much more
-high-performance API that makes a significant difference for applications
-using large numbers of simultaneous connections.
-
-\fIcurl_multi_socket_action(3)\fP is then used instead of
-\fIcurl_multi_perform(3)\fP.
-
-When using this API, you add easy handles to the multi handle just as with the
-normal multi interface. Then you also set two callbacks with the
-\fICURLMOPT_SOCKETFUNCTION(3)\fP and \fICURLMOPT_TIMERFUNCTION(3)\fP options
-to \fIcurl_multi_setopt(3)\fP. They are two callback functions that libcurl
-calls with information about what sockets to wait for, and for what activity,
-and what the current timeout time is - if that expires libcurl should be
-notified.
-
-The multi_socket API is designed to inform your application about which
-sockets libcurl is currently using and for what activities (read and/or write)
-on those sockets your application is expected to wait for.
-
-Your application must make sure to receive all sockets informed about in the
-\fICURLMOPT_SOCKETFUNCTION(3)\fP callback and make sure it reacts on the given
-activity on them. When a socket has the given activity, you call
-\fIcurl_multi_socket_action(3)\fP specifying which socket and action there
-are.
-
-The \fICURLMOPT_TIMERFUNCTION(3)\fP callback is called to set a timeout. When
-that timeout expires, your application should call the
-\fIcurl_multi_socket_action(3)\fP function saying it was due to a timeout.
-
-This API is typically used with an event-driven underlying functionality (like
-libevent, libev, kqueue, epoll or similar) with which the application
-"subscribes" on socket changes. This allows applications and libcurl to much
-better scale upward and beyond thousands of simultaneous transfers without
-losing performance.
-
-When you have added your initial set of handles, you call
-\fIcurl_multi_socket_action(3)\fP with CURL_SOCKET_TIMEOUT set in the
-\fIsockfd\fP argument, and you get callbacks invoked that set you up and you
-then continue to call \fIcurl_multi_socket_action(3)\fP accordingly when you
-get activity on the sockets you have been asked to wait on, or if the timeout
-timer expires.
-
-You can poll \fIcurl_multi_info_read(3)\fP to see if any transfer has
-completed, as it then has a message saying so.
-.SH "BLOCKING"
-A few areas in the code are still using blocking code, even when used from the
-multi interface. While we certainly want and intend for these to get fixed in
-the future, you should be aware of the following current restrictions:
-
-.nf
- - Name resolves unless the c-ares or threaded-resolver backends are used
- - file:// transfers
- - TELNET transfers
-.fi
-.SH "SEE ALSO"
-.BR libcurl-errors (3),
-.BR libcurl-easy (3),
-.BR libcurl (3)
diff --git a/docs/libcurl/libcurl-multi.md b/docs/libcurl/libcurl-multi.md
new file mode 100644
index 000000000..3acd13ea6
--- /dev/null
+++ b/docs/libcurl/libcurl-multi.md
@@ -0,0 +1,178 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-multi
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl (3)
+ - libcurl-easy (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+libcurl-multi - how to use the multi interface
+
+# DESCRIPTION
+
+This is an overview on how to use the libcurl multi interface in your C
+programs. There are specific man pages for each function mentioned in
+here. There is also the libcurl-tutorial(3) man page for a complete
+tutorial to programming with libcurl and the libcurl-easy(3) man page
+for an overview of the libcurl easy interface.
+
+All functions in the multi interface are prefixed with curl_multi.
+
+# OBJECTIVES
+
+The multi interface offers several abilities that the easy interface does not.
+They are mainly:
+
+1. Enable a "pull" interface. The application that uses libcurl decides where
+and when to ask libcurl to get/send data.
+
+2. Enable multiple simultaneous transfers in the same thread without making it
+complicated for the application.
+
+3. Enable the application to wait for action on its own file descriptors and
+curl's file descriptors simultaneously.
+
+4. Enable event-based handling and scaling transfers up to and beyond
+thousands of parallel connections.
+
+# ONE MULTI HANDLE MANY EASY HANDLES
+
+To use the multi interface, you must first create a 'multi handle' with
+curl_multi_init(3). This handle is then used as input to all further
+curl_multi_* functions.
+
+With a multi handle and the multi interface you can do several simultaneous
+transfers in parallel. Each single transfer is built up around an easy
+handle. You create all the easy handles you need, and setup the appropriate
+options for each easy handle using curl_easy_setopt(3).
+
+There are two flavors of the multi interface, the select() oriented one and
+the event based one we call multi_socket. You benefit from reading through the
+description of both versions to fully understand how they work and
+differentiate. We start out with the select() oriented version.
+
+When an easy handle is setup and ready for transfer, then instead of using
+curl_easy_perform(3) like when using the easy interface for transfers,
+you should add the easy handle to the multi handle with
+curl_multi_add_handle(3). You can add more easy handles to a multi
+handle at any point, even if other transfers are already running.
+
+Should you change your mind, the easy handle is again removed from the multi
+stack using curl_multi_remove_handle(3). Once removed from the multi
+handle, you can again use other easy interface functions like
+curl_easy_perform(3) on the handle or whatever you think is
+necessary. You can remove handles at any point during transfers.
+
+Adding the easy handle to the multi handle does not start the transfer.
+Remember that one of the main ideas with this interface is to let your
+application drive. You drive the transfers by invoking
+curl_multi_perform(3). libcurl then transfers data if there is anything
+available to transfer. It uses the callbacks and everything else you have
+setup in the individual easy handles. It transfers data on all current
+transfers in the multi stack that are ready to transfer anything. It may be
+all, it may be none. When there is nothing more to do for now, it returns back
+to the calling application.
+
+Your application extracts info from libcurl about when it would like to get
+invoked to transfer data or do other work. The most convenient way is to use
+curl_multi_poll(3) that helps you wait until the application should call
+libcurl again. The older API to accomplish the same thing is
+curl_multi_fdset(3) that extracts *fd_sets* from libcurl to use in
+select() or poll() calls in order to get to know when the transfers in the
+multi stack might need attention. Both these APIs allow for your program to
+wait for input on your own private file descriptors at the same time.
+curl_multi_timeout(3) also helps you with providing a suitable timeout
+period for your select() calls.
+
+curl_multi_perform(3) stores the number of still running transfers in
+one of its input arguments, and by reading that you can figure out when all
+the transfers in the multi handles are done. 'done' does not mean
+successful. One or more of the transfers may have failed.
+
+To get information about completed transfers, to figure out success or not and
+similar, curl_multi_info_read(3) should be called. It can return a
+message about a current or previous transfer. Repeated invokes of the function
+get more messages until the message queue is empty. The information you
+receive there includes an easy handle pointer which you may use to identify
+which easy handle the information regards.
+
+When a single transfer is completed, the easy handle is still left added to
+the multi stack. You need to first remove the easy handle with
+curl_multi_remove_handle(3) and then close it with
+curl_easy_cleanup(3), or possibly set new options to it and add it again
+with curl_multi_add_handle(3) to start another transfer.
+
+When all transfers in the multi stack are done, close the multi handle with
+curl_multi_cleanup(3). Be careful and please note that you **MUST**
+invoke separate curl_easy_cleanup(3) calls for every single easy handle
+to clean them up properly.
+
+If you want to reuse an easy handle that was added to the multi handle for
+transfer, you must first remove it from the multi stack and then re-add it
+again (possibly after having altered some options at your own choice).
+
+# MULTI_SOCKET
+
+curl_multi_socket_action(3) function offers a way for applications to
+not only avoid being forced to use select(), but it also offers a much more
+high-performance API that makes a significant difference for applications
+using large numbers of simultaneous connections.
+
+curl_multi_socket_action(3) is then used instead of
+curl_multi_perform(3).
+
+When using this API, you add easy handles to the multi handle just as with the
+normal multi interface. Then you also set two callbacks with the
+CURLMOPT_SOCKETFUNCTION(3) and CURLMOPT_TIMERFUNCTION(3) options
+to curl_multi_setopt(3). They are two callback functions that libcurl
+calls with information about what sockets to wait for, and for what activity,
+and what the current timeout time is - if that expires libcurl should be
+notified.
+
+The multi_socket API is designed to inform your application about which
+sockets libcurl is currently using and for what activities (read and/or write)
+on those sockets your application is expected to wait for.
+
+Your application must make sure to receive all sockets informed about in the
+CURLMOPT_SOCKETFUNCTION(3) callback and make sure it reacts on the given
+activity on them. When a socket has the given activity, you call
+curl_multi_socket_action(3) specifying which socket and action there
+are.
+
+The CURLMOPT_TIMERFUNCTION(3) callback is called to set a timeout. When
+that timeout expires, your application should call the
+curl_multi_socket_action(3) function saying it was due to a timeout.
+
+This API is typically used with an event-driven underlying functionality (like
+libevent, libev, kqueue, epoll or similar) with which the application
+"subscribes" on socket changes. This allows applications and libcurl to much
+better scale upward and beyond thousands of simultaneous transfers without
+losing performance.
+
+When you have added your initial set of handles, you call
+curl_multi_socket_action(3) with CURL_SOCKET_TIMEOUT set in the
+*sockfd* argument, and you get callbacks invoked that set you up and you
+then continue to call curl_multi_socket_action(3) accordingly when you
+get activity on the sockets you have been asked to wait on, or if the timeout
+timer expires.
+
+You can poll curl_multi_info_read(3) to see if any transfer has
+completed, as it then has a message saying so.
+
+# BLOCKING
+
+A few areas in the code are still using blocking code, even when used from the
+multi interface. While we certainly want and intend for these to get fixed in
+the future, you should be aware of the following current restrictions:
+
+~~~c
+ - Name resolves unless the c-ares or threaded-resolver backends are used
+ - file:// transfers
+ - TELNET transfers
+~~~
diff --git a/docs/libcurl/libcurl-security.3 b/docs/libcurl/libcurl-security.3
deleted file mode 100644
index 0bc056c5f..000000000
--- a/docs/libcurl/libcurl-security.3
+++ /dev/null
@@ -1,426 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH libcurl-security 3 "13 Feb 2018" "libcurl" "libcurl"
-.SH NAME
-libcurl-security \- security considerations when using libcurl
-.SH "Security"
-The libcurl project takes security seriously. The library is written with
-caution and precautions are taken to mitigate many kinds of risks encountered
-while operating with potentially malicious servers on the Internet. It is a
-powerful library, however, which allows application writers to make trade-offs
-between ease of writing and exposure to potential risky operations. If used
-the right way, you can use libcurl to transfer data pretty safely.
-
-Many applications are used in closed networks where users and servers can
-(possibly) be trusted, but many others are used on arbitrary servers and are
-fed input from potentially untrusted users. Following is a discussion about
-some risks in the ways in which applications commonly use libcurl and
-potential mitigations of those risks. It is not comprehensive, but shows
-classes of attacks that robust applications should consider. The Common
-Weakness Enumeration project at https://cwe.mitre.org/ is a good reference for
-many of these and similar types of weaknesses of which application writers
-should be aware.
-.SH "Command Lines"
-If you use a command line tool (such as curl) that uses libcurl, and you give
-options to the tool on the command line those options can get read by other
-users of your system when they use \fIps\fP or other tools to list currently
-running processes.
-
-To avoid these problems, never feed sensitive things to programs using command
-line options. Write them to a protected file and use the \-K option to avoid
-this.
-.SH ".netrc"
-\&.netrc is a pretty handy file/feature that allows you to login quickly and
-automatically to frequently visited sites. The file contains passwords in
-clear text and is a real security risk. In some cases, your .netrc is also
-stored in a home directory that is NFS mounted or used on another network
-based file system, so the clear text password flies through your network every
-time anyone reads that file.
-
-For applications that enable .netrc use, a user who manage to set the right
-URL might then be possible to pass on passwords.
-
-To avoid these problems, do not use .netrc files and never store passwords in
-plain text anywhere.
-.SH "Clear Text Passwords"
-Many of the protocols libcurl supports send name and password unencrypted as
-clear text (HTTP Basic authentication, FTP, TELNET etc). It is easy for anyone
-on your network or a network nearby yours to just fire up a network analyzer
-tool and eavesdrop on your passwords. do not let the fact that HTTP Basic uses
-base64 encoded passwords fool you. They may not look readable at a first
-glance, but they are easily "deciphered" by anyone within seconds.
-
-To avoid this problem, use an authentication mechanism or other protocol that
-does not let snoopers see your password: Digest, CRAM-MD5, Kerberos, SPNEGO or
-NTLM authentication. Or even better: use authenticated protocols that protect
-the entire connection and everything sent over it.
-.SH "Unauthenticated Connections"
-Protocols that do not have any form of cryptographic authentication cannot
-with any certainty know that they communicate with the right remote server.
-
-If your application is using a fixed scheme or fixed host name, it is not safe
-as long as the connection is unauthenticated. There can be a man-in-the-middle
-or in fact the whole server might have been replaced by an evil actor.
-
-Unauthenticated protocols are unsafe. The data that comes back to curl may
-have been injected by an attacker. The data that curl sends might be modified
-before it reaches the intended server. If it even reaches the intended server
-at all.
-
-Remedies:
-.IP "Restrict operations to authenticated transfers"
-Use authenticated protocols protected with HTTPS or SSH.
-.IP "Make sure the server's certificate etc is verified"
-Never ever switch off certificate verification.
-.SH "Redirects"
-The \fICURLOPT_FOLLOWLOCATION(3)\fP option automatically follows HTTP
-redirects sent by a remote server. These redirects can refer to any kind of
-URL, not just HTTP. libcurl restricts the protocols allowed to be used in
-redirects for security reasons: only HTTP, HTTPS, FTP and FTPS are
-enabled by default. Applications may opt to restrict that set further.
-
-A redirect to a file: URL would cause the libcurl to read (or write) arbitrary
-files from the local filesystem. If the application returns the data back to
-the user (as would happen in some kinds of CGI scripts), an attacker could
-leverage this to read otherwise forbidden data (e.g.
-\fBfile://localhost/etc/passwd\fP).
-
-If authentication credentials are stored in the ~/.netrc file, or Kerberos is
-in use, any other URL type (not just file:) that requires authentication is
-also at risk. A redirect such as ftp://some-internal-server/private-file would
-then return data even when the server is password protected.
-
-In the same way, if an unencrypted SSH private key has been configured for the
-user running the libcurl application, SCP: or SFTP: URLs could access password
-or private-key protected resources,
-e.g. \fBsftp://user@some-internal-server/etc/passwd\fP
-
-The \fICURLOPT_REDIR_PROTOCOLS(3)\fP and \fICURLOPT_NETRC(3)\fP options can be
-used to mitigate against this kind of attack.
-
-A redirect can also specify a location available only on the machine running
-libcurl, including servers hidden behind a firewall from the attacker.
-e.g. http://127.0.0.1/ or http://intranet/delete-stuff.cgi?delete=all or
-tftp://bootp-server/pc-config-data
-
-Applications can mitigate against this by disabling
-\fICURLOPT_FOLLOWLOCATION(3)\fP and handling redirects itself, sanitizing URLs
-as necessary. Alternately, an app could leave \fICURLOPT_FOLLOWLOCATION(3)\fP
-enabled but set \fICURLOPT_REDIR_PROTOCOLS(3)\fP and install a
-\fICURLOPT_OPENSOCKETFUNCTION(3)\fP or \fICURLOPT_PREREQFUNCTION(3)\fP callback
-function in which addresses are sanitized before use.
-.SH "CRLF in Headers"
-For all options in libcurl which specify headers, including but not limited to
-\fICURLOPT_HTTPHEADER(3)\fP, \fICURLOPT_PROXYHEADER(3)\fP,
-\fICURLOPT_COOKIE(3)\fP, \fICURLOPT_USERAGENT(3)\fP, \fICURLOPT_REFERER(3)\fP
-and \fICURLOPT_RANGE(3)\fP, libcurl sends the headers as-is and does not apply
-any special sanitation or normalization to them.
-
-If you allow untrusted user input into these options without sanitizing CRLF
-sequences in them, someone malicious may be able to modify the request in a
-way you did not intend such as injecting new headers.
-.SH "Local Resources"
-A user who can control the DNS server of a domain being passed in within a URL
-can change the address of the host to a local, private address which a
-server-side libcurl-using application could then use. e.g. the innocuous URL
-\fBhttp://fuzzybunnies.example.com/\fP could actually resolve to the IP
-address of a server behind a firewall, such as 127.0.0.1 or
-10.1.2.3. Applications can mitigate against this by setting a
-\fICURLOPT_OPENSOCKETFUNCTION(3)\fP or \fICURLOPT_PREREQFUNCTION(3)\fP and
-checking the address before a connection.
-
-All the malicious scenarios regarding redirected URLs apply just as well to
-non-redirected URLs, if the user is allowed to specify an arbitrary URL that
-could point to a private resource. For example, a web app providing a
-translation service might happily translate \fBfile://localhost/etc/passwd\fP
-and display the result. Applications can mitigate against this with the
-\fICURLOPT_PROTOCOLS(3)\fP option as well as by similar mitigation techniques
-for redirections.
-
-A malicious FTP server could in response to the PASV command return an IP
-address and port number for a server local to the app running libcurl but
-behind a firewall. Applications can mitigate against this by using the
-\fICURLOPT_FTP_SKIP_PASV_IP(3)\fP option or \fICURLOPT_FTPPORT(3)\fP.
-
-Local servers sometimes assume local access comes from friends and trusted
-users. An application that expects https://example.com/file_to_read that and
-instead gets http://192.168.0.1/my_router_config might print a file that would
-otherwise be protected by the firewall.
-
-Allowing your application to connect to local hosts, be it the same machine
-that runs the application or a machine on the same local network, might be
-possible to exploit by an attacker who then perhaps can "port-scan" the
-particular hosts - depending on how the application and servers acts.
-.SH "IPv4 Addresses"
-Some users might be tempted to filter access to local resources or similar
-based on numerical IPv4 addresses used in URLs. This is a bad and error-prone
-idea because of the many different ways a numerical IPv4 address can be
-specified and libcurl accepts: one to four dot-separated fields using one of
-or a mix of decimal, octal or hexadecimal encoding.
-.SH "IPv6 Addresses"
-libcurl handles IPv6 addresses transparently and just as easily as IPv4
-addresses. That means that a sanitizing function that filters out addresses
-like 127.0.0.1 is not sufficient - the equivalent IPv6 addresses \fB::1\fP,
-\fB::\fP, \fB0:00::0:1\fP, \fB::127.0.0.1\fP and \fB::ffff:7f00:1\fP supplied
-somehow by an attacker would all bypass a naive filter and could allow access
-to undesired local resources. IPv6 also has special address blocks like
-link-local and site-local that generally should not be accessed by a
-server-side libcurl-using application. A poorly configured firewall installed
-in a data center, organization or server may also be configured to limit IPv4
-connections but leave IPv6 connections wide open. In some cases, setting
-\fICURLOPT_IPRESOLVE(3)\fP to CURL_IPRESOLVE_V4 can be used to limit resolved
-addresses to IPv4 only and bypass these issues.
-.SH Uploads
-When uploading, a redirect can cause a local (or remote) file to be
-overwritten. Applications must not allow any unsanitized URL to be passed in
-for uploads. Also, \fICURLOPT_FOLLOWLOCATION(3)\fP should not be used on
-uploads. Instead, the applications should consider handling redirects itself,
-sanitizing each URL first.
-.SH Authentication
-Use of \fICURLOPT_UNRESTRICTED_AUTH(3)\fP could cause authentication
-information to be sent to an unknown second server. Applications can mitigate
-against this by disabling \fICURLOPT_FOLLOWLOCATION(3)\fP and handling
-redirects itself, sanitizing where necessary.
-
-Use of the CURLAUTH_ANY option to \fICURLOPT_HTTPAUTH(3)\fP could result in
-user name and password being sent in clear text to an HTTP server. Instead,
-use CURLAUTH_ANYSAFE which ensures that the password is encrypted over the
-network, or else fail the request.
-
-Use of the CURLUSESSL_TRY option to \fICURLOPT_USE_SSL(3)\fP could result in
-user name and password being sent in clear text to an FTP server. Instead,
-use CURLUSESSL_CONTROL to ensure that an encrypted connection is used or else
-fail the request.
-.SH Cookies
-If cookies are enabled and cached, then a user could craft a URL which
-performs some malicious action to a site whose authentication is already
-stored in a cookie. e.g. http://mail.example.com/delete-stuff.cgi?delete=all
-Applications can mitigate against this by disabling cookies or clearing them
-between requests.
-.SH "Dangerous SCP URLs"
-SCP URLs can contain raw commands within the scp: URL, which is a side effect
-of how the SCP protocol is designed. e.g.
-.nf
- scp://user:pass@host/a;date >/tmp/test;
-.fi
-Applications must not allow unsanitized SCP: URLs to be passed in for
-downloads.
-.SH "file://"
-By default curl and libcurl support file:// URLs. Such a URL is always an
-access, or attempted access, to a local resource. If your application wants to
-avoid that, keep control of what URLs to use and/or prevent curl/libcurl from
-using the protocol.
-
-By default, libcurl prohibits redirects to file:// URLs.
-
-.SH "Warning: file:// on Windows"
-The Windows operating system tries automatically, and without any way for
-applications to disable it, to establish a connection to another host over the
-network and access it (over SMB or other protocols), if only the correct file
-path is accessed.
-
-When first realizing this, the curl team tried to filter out such attempts in
-order to protect applications for inadvertent probes of for example internal
-networks etc. This resulted in CVE-2019-15601 and the associated security fix.
-
-However, we have since been made aware of the fact that the previous fix was far
-from adequate as there are several other ways to accomplish more or less the
-same thing: accessing a remote host over the network instead of the local file
-system.
-
-The conclusion we have come to is that this is a weakness or feature in the
-Windows operating system itself, that we as an application cannot safely
-protect users against. It would just be a whack-a-mole race we do not want to
-participate in. There are too many ways to do it and there is no knob we can
-use to turn off the practice.
-
-If you use curl or libcurl on Windows (any version), disable the use of the
-FILE protocol in curl or be prepared that accesses to a range of "magic paths"
-potentially make your system access other hosts on your network. curl cannot
-protect you against this.
-.SH "What if the user can set the URL"
-Applications may find it tempting to let users set the URL that it can work
-on. That is probably fine, but opens up for mischief and trickery that you as
-an application author may want to address or take precautions against.
-
-If your curl-using script allow a custom URL do you also, perhaps
-unintentionally, allow the user to pass other options to the curl command line
-if creative use of special characters are applied?
-
-If the user can set the URL, the user can also specify the scheme part to
-other protocols that you did not intend for users to use and perhaps did not
-consider. curl supports over 20 different URL schemes. "http://" might be what
-you thought, "ftp://" or "imap://" might be what the user gives your
-application. Also, cross-protocol operations might be done by using a
-particular scheme in the URL but point to a server doing a different protocol
-on a non-standard port.
-
-Remedies:
-.IP "Use --proto"
-curl command lines can use \fI--proto\fP to limit what URL schemes it accepts
-.IP "Use CURLOPT_PROTOCOLS"
-libcurl programs can use \fICURLOPT_PROTOCOLS(3)\fP to limit what URL schemes it accepts
-.IP "consider not allowing the user to set the full URL"
-Maybe just let the user provide data for parts of it? Or maybe filter input to
-only allow specific choices?
-.SH "RFC 3986 vs WHATWG URL"
-curl supports URLs mostly according to how they are defined in RFC 3986, and
-has done so since the beginning.
-
-Web browsers mostly adhere to the WHATWG URL Specification.
-
-This deviance makes some URLs copied between browsers (or returned over HTTP
-for redirection) and curl not work the same way. It can also cause problems if
-an application parses URLs differently from libcurl and makes different
-assumptions about a link. This can mislead users into getting the wrong thing,
-connecting to the wrong host or otherwise not working identically.
-
-Within an application, this can be mitigated by always using the
-\fIcurl_url(3)\fP API to parse URLs, ensuring that they are parsed the same way
-as within libcurl itself.
-.SH "FTP uses two connections"
-When performing an FTP transfer, two TCP connections are used: one for setting
-up the transfer and one for the actual data.
-
-FTP is not only unauthenticated, but the setting up of the second transfer is
-also a weak spot. The second connection to use for data, is either setup with
-the PORT/EPRT command that makes the server connect back to the client on the
-given IP+PORT, or with PASV/EPSV that makes the server setup a port to listen
-to and tells the client to connect to a given IP+PORT.
-
-Again, unauthenticated means that the connection might be meddled with by a
-man-in-the-middle or that there is a malicious server pretending to be the
-right one.
-
-A malicious FTP server can respond to PASV commands with the IP+PORT of a
-totally different machine. Perhaps even a third party host, and when there are
-many clients trying to connect to that third party, it could create a
-Distributed Denial-Of-Service attack out of it. If the client makes an upload
-operation, it can make the client send the data to another site. If the
-attacker can affect what data the client uploads, it can be made to work as a
-HTTP request and then the client could be made to issue HTTP requests to third
-party hosts.
-
-An attacker that manages to control curl's command line options can tell curl
-to send an FTP PORT command to ask the server to connect to a third party host
-instead of back to curl.
-
-The fact that FTP uses two connections makes it vulnerable in a way that is
-hard to avoid.
-.SH "Denial of Service"
-A malicious server could cause libcurl to effectively hang by sending data
-slowly, or even no data at all but just keeping the TCP connection open. This
-could effectively result in a denial-of-service attack. The
-\fICURLOPT_TIMEOUT(3)\fP and/or \fICURLOPT_LOW_SPEED_LIMIT(3)\fP options can
-be used to mitigate against this.
-
-A malicious server could cause libcurl to download an infinite amount of data,
-potentially causing all of memory or disk to be filled. Setting the
-\fICURLOPT_MAXFILESIZE_LARGE(3)\fP option is not sufficient to guard against
-this. Instead, applications should monitor the amount of data received within
-the write or progress callback and abort once the limit is reached.
-
-A malicious HTTP server could cause an infinite redirection loop, causing a
-denial-of-service. This can be mitigated by using the
-\fICURLOPT_MAXREDIRS(3)\fP option.
-.SH "Arbitrary Headers"
-User-supplied data must be sanitized when used in options like
-\fICURLOPT_USERAGENT(3)\fP, \fICURLOPT_HTTPHEADER(3)\fP,
-\fICURLOPT_POSTFIELDS(3)\fP and others that are used to generate structured
-data. Characters like embedded carriage returns or ampersands could allow the
-user to create additional headers or fields that could cause malicious
-transactions.
-.SH "Server-supplied Names"
-A server can supply data which the application may, in some cases, use as a
-file name. The curl command-line tool does this with
-\fI--remote-header-name\fP, using the Content-disposition: header to generate
-a file name. An application could also use \fICURLINFO_EFFECTIVE_URL(3)\fP to
-generate a file name from a server-supplied redirect URL. Special care must be
-taken to sanitize such names to avoid the possibility of a malicious server
-supplying one like \fB"/etc/passwd"\fP, \fB"\\autoexec.bat"\fP, \fB"prn:"\fP
-or even \fB".bashrc"\fP.
-.SH "Server Certificates"
-A secure application should never use the \fICURLOPT_SSL_VERIFYPEER(3)\fP
-option to disable certificate validation. There are numerous attacks that are
-enabled by applications that fail to properly validate server TLS/SSL
-certificates, thus enabling a malicious server to spoof a legitimate
-one. HTTPS without validated certificates is potentially as insecure as a
-plain HTTP connection.
-.SH "Showing What You Do"
-Relatedly, be aware that in situations when you have problems with libcurl and
-ask someone for help, everything you reveal in order to get best possible help
-might also impose certain security related risks. Host names, user names,
-paths, operating system specifics, etc. (not to mention passwords of course)
-may in fact be used by intruders to gain additional information of a potential
-target.
-
-Be sure to limit access to application logs if they could hold private or
-security-related data. Besides the obvious candidates like user names and
-passwords, things like URLs, cookies or even file names could also hold
-sensitive data.
-
-To avoid this problem, you must of course use your common sense. Often, you
-can just edit out the sensitive data or just search/replace your true
-information with faked data.
-.SH "setuid applications using libcurl"
-libcurl-using applications that set the 'setuid' bit to run with elevated or
-modified rights also implicitly give that extra power to libcurl and this
-should only be done after careful considerations.
-
-Giving setuid powers to the application means that libcurl can save files using
-those new rights (if for example the `SSLKEYLOGFILE` environment variable is
-set). Also: if the application wants these powers to read or manage secrets
-that the user is otherwise not able to view (like credentials for a login
-etc), it should be noted that libcurl still might understand proxy environment
-variables that allow the user to redirect libcurl operations to use a proxy
-controlled by the user.
-.SH "File descriptors, fork and NTLM"
-An application that uses libcurl and invokes \fIfork()\fP gets all file
-descriptors duplicated in the child process, including the ones libcurl
-created.
-
-libcurl itself uses \fIfork()\fP and \fIexecl()\fP if told to use the
-\fBCURLAUTH_NTLM_WB\fP authentication method which then invokes the helper
-command in a child process with file descriptors duplicated. Make sure that
-only the trusted and reliable helper program is invoked!
-.SH "Secrets in memory"
-When applications pass user names, passwords or other sensitive data to
-libcurl to be used for upcoming transfers, those secrets are kept around as-is
-in memory. In many cases they are stored in the heap for as long as the handle
-itself for which the options are set.
-
-If an attacker can access the heap, like maybe by reading swap space or via a
-core dump file, such data might be accessible.
-
-Further, when eventually closing a handle and the secrets are no longer
-needed, libcurl does not explicitly clear memory before freeing it, so
-credentials may be left in freed data.
-.SH "Saving files"
-libcurl cannot protect against attacks where an attacker has write access to
-the same directory where libcurl is directed to save files.
-.SH "Report Security Problems"
-Should you detect or just suspect a security problem in libcurl or curl,
-contact the project curl security team immediately. See
-https://curl.se/dev/secprocess.html for details.
diff --git a/docs/libcurl/libcurl-security.md b/docs/libcurl/libcurl-security.md
new file mode 100644
index 000000000..09d63f4a8
--- /dev/null
+++ b/docs/libcurl/libcurl-security.md
@@ -0,0 +1,487 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-security
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl-thread (3)
+---
+<!-- markdown-link-check-disable -->
+# NAME
+
+libcurl-security - security considerations when using libcurl
+
+# Security
+
+The libcurl project takes security seriously. The library is written with
+caution and precautions are taken to mitigate many kinds of risks encountered
+while operating with potentially malicious servers on the Internet. It is a
+powerful library, however, which allows application writers to make trade-offs
+between ease of writing and exposure to potential risky operations. If used
+the right way, you can use libcurl to transfer data pretty safely.
+
+Many applications are used in closed networks where users and servers can
+(possibly) be trusted, but many others are used on arbitrary servers and are
+fed input from potentially untrusted users. Following is a discussion about
+some risks in the ways in which applications commonly use libcurl and
+potential mitigations of those risks. It is not comprehensive, but shows
+classes of attacks that robust applications should consider. The Common
+Weakness Enumeration project at https://cwe.mitre.org/ is a good reference for
+many of these and similar types of weaknesses of which application writers
+should be aware.
+
+# Command Lines
+
+If you use a command line tool (such as curl) that uses libcurl, and you give
+options to the tool on the command line those options can get read by other
+users of your system when they use *ps* or other tools to list currently
+running processes.
+
+To avoid these problems, never feed sensitive things to programs using command
+line options. Write them to a protected file and use the -K option to avoid
+this.
+
+# .netrc
+
+.netrc is a pretty handy file/feature that allows you to login quickly and
+automatically to frequently visited sites. The file contains passwords in
+clear text and is a real security risk. In some cases, your .netrc is also
+stored in a home directory that is NFS mounted or used on another network
+based file system, so the clear text password flies through your network every
+time anyone reads that file.
+
+For applications that enable .netrc use, a user who manage to set the right
+URL might then be possible to pass on passwords.
+
+To avoid these problems, do not use .netrc files and never store passwords in
+plain text anywhere.
+
+# Clear Text Passwords
+
+Many of the protocols libcurl supports send name and password unencrypted as
+clear text (HTTP Basic authentication, FTP, TELNET etc). It is easy for anyone
+on your network or a network nearby yours to just fire up a network analyzer
+tool and eavesdrop on your passwords. Do not let the fact that HTTP Basic uses
+base64 encoded passwords fool you. They may not look readable at a first
+glance, but they are easily "deciphered" by anyone within seconds.
+
+To avoid this problem, use an authentication mechanism or other protocol that
+does not let snoopers see your password: Digest, CRAM-MD5, Kerberos, SPNEGO or
+NTLM authentication. Or even better: use authenticated protocols that protect
+the entire connection and everything sent over it.
+
+# Unauthenticated Connections
+
+Protocols that do not have any form of cryptographic authentication cannot
+with any certainty know that they communicate with the right remote server.
+
+If your application is using a fixed scheme or fixed hostname, it is not safe
+as long as the connection is unauthenticated. There can be a man-in-the-middle
+or in fact the whole server might have been replaced by an evil actor.
+
+Unauthenticated protocols are unsafe. The data that comes back to curl may
+have been injected by an attacker. The data that curl sends might be modified
+before it reaches the intended server. If it even reaches the intended server
+at all.
+
+Remedies:
+
+## Restrict operations to authenticated transfers
+
+Use authenticated protocols protected with HTTPS or SSH.
+
+## Make sure the server's certificate etc is verified
+
+Never ever switch off certificate verification.
+
+# Redirects
+
+The CURLOPT_FOLLOWLOCATION(3) option automatically follows HTTP
+redirects sent by a remote server. These redirects can refer to any kind of
+URL, not just HTTP. libcurl restricts the protocols allowed to be used in
+redirects for security reasons: only HTTP, HTTPS, FTP and FTPS are
+enabled by default. Applications may opt to restrict that set further.
+
+A redirect to a file: URL would cause the libcurl to read (or write) arbitrary
+files from the local filesystem. If the application returns the data back to
+the user (as would happen in some kinds of CGI scripts), an attacker could
+leverage this to read otherwise forbidden data (e.g.
+**file://localhost/etc/passwd**).
+
+If authentication credentials are stored in the ~/.netrc file, or Kerberos is
+in use, any other URL type (not just file:) that requires authentication is
+also at risk. A redirect such as **ftp://some-internal-server/private-file** would
+then return data even when the server is password protected.
+
+In the same way, if an unencrypted SSH private key has been configured for the
+user running the libcurl application, SCP: or SFTP: URLs could access password
+or private-key protected resources,
+e.g. **sftp://user@some-internal-server/etc/passwd**
+
+The CURLOPT_REDIR_PROTOCOLS(3) and CURLOPT_NETRC(3) options can be
+used to mitigate against this kind of attack.
+
+A redirect can also specify a location available only on the machine running
+libcurl, including servers hidden behind a firewall from the attacker.
+E.g. **http://127.0.0.1/** or **http://intranet/delete-stuff.cgi?delete=all** or
+**tftp://bootp-server/pc-config-data**
+
+Applications can mitigate against this by disabling
+CURLOPT_FOLLOWLOCATION(3) and handling redirects itself, sanitizing URLs
+as necessary. Alternately, an app could leave CURLOPT_FOLLOWLOCATION(3)
+enabled but set CURLOPT_REDIR_PROTOCOLS(3) and install a
+CURLOPT_OPENSOCKETFUNCTION(3) or CURLOPT_PREREQFUNCTION(3) callback
+function in which addresses are sanitized before use.
+
+# CRLF in Headers
+
+For all options in libcurl which specify headers, including but not limited to
+CURLOPT_HTTPHEADER(3), CURLOPT_PROXYHEADER(3),
+CURLOPT_COOKIE(3), CURLOPT_USERAGENT(3), CURLOPT_REFERER(3)
+and CURLOPT_RANGE(3), libcurl sends the headers as-is and does not apply
+any special sanitation or normalization to them.
+
+If you allow untrusted user input into these options without sanitizing CRLF
+sequences in them, someone malicious may be able to modify the request in a
+way you did not intend such as injecting new headers.
+
+# Local Resources
+
+A user who can control the DNS server of a domain being passed in within a URL
+can change the address of the host to a local, private address which a
+server-side libcurl-using application could then use. E.g. the innocuous URL
+**http://fuzzybunnies.example.com/** could actually resolve to the IP
+address of a server behind a firewall, such as 127.0.0.1 or
+10.1.2.3. Applications can mitigate against this by setting a
+CURLOPT_OPENSOCKETFUNCTION(3) or CURLOPT_PREREQFUNCTION(3) and
+checking the address before a connection.
+
+All the malicious scenarios regarding redirected URLs apply just as well to
+non-redirected URLs, if the user is allowed to specify an arbitrary URL that
+could point to a private resource. For example, a web app providing a
+translation service might happily translate **file://localhost/etc/passwd**
+and display the result. Applications can mitigate against this with the
+CURLOPT_PROTOCOLS(3) option as well as by similar mitigation techniques
+for redirections.
+
+A malicious FTP server could in response to the PASV command return an IP
+address and port number for a server local to the app running libcurl but
+behind a firewall. Applications can mitigate against this by using the
+CURLOPT_FTP_SKIP_PASV_IP(3) option or CURLOPT_FTPPORT(3).
+
+Local servers sometimes assume local access comes from friends and trusted
+users. An application that expects https://example.com/file_to_read that and
+instead gets http://192.168.0.1/my_router_config might print a file that would
+otherwise be protected by the firewall.
+
+Allowing your application to connect to local hosts, be it the same machine
+that runs the application or a machine on the same local network, might be
+possible to exploit by an attacker who then perhaps can "port-scan" the
+particular hosts - depending on how the application and servers acts.
+
+# IPv4 Addresses
+
+Some users might be tempted to filter access to local resources or similar
+based on numerical IPv4 addresses used in URLs. This is a bad and error-prone
+idea because of the many different ways a numerical IPv4 address can be
+specified and libcurl accepts: one to four dot-separated fields using one of
+or a mix of decimal, octal or hexadecimal encoding.
+
+# IPv6 Addresses
+
+libcurl handles IPv6 addresses transparently and just as easily as IPv4
+addresses. That means that a sanitizing function that filters out addresses
+like 127.0.0.1 is not sufficient - the equivalent IPv6 addresses **::1**,
+**::**, **0:00::0:1**, **::127.0.0.1** and **::ffff:7f00:1** supplied
+somehow by an attacker would all bypass a naive filter and could allow access
+to undesired local resources. IPv6 also has special address blocks like
+link-local and site-local that generally should not be accessed by a
+server-side libcurl-using application. A poorly configured firewall installed
+in a data center, organization or server may also be configured to limit IPv4
+connections but leave IPv6 connections wide open. In some cases, setting
+CURLOPT_IPRESOLVE(3) to CURL_IPRESOLVE_V4 can be used to limit resolved
+addresses to IPv4 only and bypass these issues.
+
+# Uploads
+
+When uploading, a redirect can cause a local (or remote) file to be
+overwritten. Applications must not allow any unsanitized URL to be passed in
+for uploads. Also, CURLOPT_FOLLOWLOCATION(3) should not be used on
+uploads. Instead, the applications should consider handling redirects itself,
+sanitizing each URL first.
+
+# Authentication
+
+Use of CURLOPT_UNRESTRICTED_AUTH(3) could cause authentication
+information to be sent to an unknown second server. Applications can mitigate
+against this by disabling CURLOPT_FOLLOWLOCATION(3) and handling
+redirects itself, sanitizing where necessary.
+
+Use of the CURLAUTH_ANY option to CURLOPT_HTTPAUTH(3) could result in
+user name and password being sent in clear text to an HTTP server. Instead,
+use CURLAUTH_ANYSAFE which ensures that the password is encrypted over the
+network, or else fail the request.
+
+Use of the CURLUSESSL_TRY option to CURLOPT_USE_SSL(3) could result in
+user name and password being sent in clear text to an FTP server. Instead,
+use CURLUSESSL_CONTROL to ensure that an encrypted connection is used or else
+fail the request.
+
+# Cookies
+
+If cookies are enabled and cached, then a user could craft a URL which
+performs some malicious action to a site whose authentication is already
+stored in a cookie. E.g.
+**http://mail.example.com/delete-stuff.cgi?delete=all** Applications can
+mitigate against this by disabling cookies or clearing them between requests.
+
+# Dangerous SCP URLs
+
+SCP URLs can contain raw commands within the scp: URL, which is a side effect
+of how the SCP protocol is designed. E.g.
+~~~
+ scp://user:pass@host/a;date >/tmp/test;
+~~~
+Applications must not allow unsanitized SCP: URLs to be passed in for
+downloads.
+
+# file://
+
+By default curl and libcurl support file:// URLs. Such a URL is always an
+access, or attempted access, to a local resource. If your application wants to
+avoid that, keep control of what URLs to use and/or prevent curl/libcurl from
+using the protocol.
+
+By default, libcurl prohibits redirects to file:// URLs.
+
+# Warning: file:// on Windows
+
+The Windows operating system tries automatically, and without any way for
+applications to disable it, to establish a connection to another host over the
+network and access it (over SMB or other protocols), if only the correct file
+path is accessed.
+
+When first realizing this, the curl team tried to filter out such attempts in
+order to protect applications for inadvertent probes of for example internal
+networks etc. This resulted in CVE-2019-15601 and the associated security fix.
+
+However, we have since been made aware of the fact that the previous fix was far
+from adequate as there are several other ways to accomplish more or less the
+same thing: accessing a remote host over the network instead of the local file
+system.
+
+The conclusion we have come to is that this is a weakness or feature in the
+Windows operating system itself, that we as an application cannot safely
+protect users against. It would just be a whack-a-mole race we do not want to
+participate in. There are too many ways to do it and there is no knob we can
+use to turn off the practice.
+
+If you use curl or libcurl on Windows (any version), disable the use of the
+FILE protocol in curl or be prepared that accesses to a range of "magic paths"
+potentially make your system access other hosts on your network. curl cannot
+protect you against this.
+
+# What if the user can set the URL
+
+Applications may find it tempting to let users set the URL that it can work
+on. That is probably fine, but opens up for mischief and trickery that you as
+an application author may want to address or take precautions against.
+
+If your curl-using script allow a custom URL do you also, perhaps
+unintentionally, allow the user to pass other options to the curl command line
+if creative use of special characters are applied?
+
+If the user can set the URL, the user can also specify the scheme part to
+other protocols that you did not intend for users to use and perhaps did not
+consider. curl supports over 20 different URL schemes. "http://" might be what
+you thought, "ftp://" or "imap://" might be what the user gives your
+application. Also, cross-protocol operations might be done by using a
+particular scheme in the URL but point to a server doing a different protocol
+on a non-standard port.
+
+Remedies:
+
+## Use --proto
+
+curl command lines can use *--proto* to limit what URL schemes it accepts
+
+## Use CURLOPT_PROTOCOLS
+
+libcurl programs can use CURLOPT_PROTOCOLS(3) to limit what URL schemes it accepts
+
+## consider not allowing the user to set the full URL
+
+Maybe just let the user provide data for parts of it? Or maybe filter input to
+only allow specific choices?
+
+# RFC 3986 vs WHATWG URL
+
+curl supports URLs mostly according to how they are defined in RFC 3986, and
+has done so since the beginning.
+
+Web browsers mostly adhere to the WHATWG URL Specification.
+
+This deviance makes some URLs copied between browsers (or returned over HTTP
+for redirection) and curl not work the same way. It can also cause problems if
+an application parses URLs differently from libcurl and makes different
+assumptions about a link. This can mislead users into getting the wrong thing,
+connecting to the wrong host or otherwise not working identically.
+
+Within an application, this can be mitigated by always using the
+curl_url(3) API to parse URLs, ensuring that they are parsed the same way
+as within libcurl itself.
+
+# FTP uses two connections
+
+When performing an FTP transfer, two TCP connections are used: one for setting
+up the transfer and one for the actual data.
+
+FTP is not only unauthenticated, but the setting up of the second transfer is
+also a weak spot. The second connection to use for data, is either setup with
+the PORT/EPRT command that makes the server connect back to the client on the
+given IP+PORT, or with PASV/EPSV that makes the server setup a port to listen
+to and tells the client to connect to a given IP+PORT.
+
+Again, unauthenticated means that the connection might be meddled with by a
+man-in-the-middle or that there is a malicious server pretending to be the
+right one.
+
+A malicious FTP server can respond to PASV commands with the IP+PORT of a
+totally different machine. Perhaps even a third party host, and when there are
+many clients trying to connect to that third party, it could create a
+Distributed Denial-Of-Service attack out of it. If the client makes an upload
+operation, it can make the client send the data to another site. If the
+attacker can affect what data the client uploads, it can be made to work as a
+HTTP request and then the client could be made to issue HTTP requests to third
+party hosts.
+
+An attacker that manages to control curl's command line options can tell curl
+to send an FTP PORT command to ask the server to connect to a third party host
+instead of back to curl.
+
+The fact that FTP uses two connections makes it vulnerable in a way that is
+hard to avoid.
+
+# Denial of Service
+
+A malicious server could cause libcurl to effectively hang by sending data
+slowly, or even no data at all but just keeping the TCP connection open. This
+could effectively result in a denial-of-service attack. The
+CURLOPT_TIMEOUT(3) and/or CURLOPT_LOW_SPEED_LIMIT(3) options can
+be used to mitigate against this.
+
+A malicious server could cause libcurl to download an infinite amount of data,
+potentially causing all of memory or disk to be filled. Setting the
+CURLOPT_MAXFILESIZE_LARGE(3) option is not sufficient to guard against
+this. Instead, applications should monitor the amount of data received within
+the write or progress callback and abort once the limit is reached.
+
+A malicious HTTP server could cause an infinite redirection loop, causing a
+denial-of-service. This can be mitigated by using the
+CURLOPT_MAXREDIRS(3) option.
+
+# Arbitrary Headers
+
+User-supplied data must be sanitized when used in options like
+CURLOPT_USERAGENT(3), CURLOPT_HTTPHEADER(3),
+CURLOPT_POSTFIELDS(3) and others that are used to generate structured
+data. Characters like embedded carriage returns or ampersands could allow the
+user to create additional headers or fields that could cause malicious
+transactions.
+
+# Server-supplied Names
+
+A server can supply data which the application may, in some cases, use as a
+filename. The curl command-line tool does this with *--remote-header-name*,
+using the Content-disposition: header to generate a filename. An application
+could also use CURLINFO_EFFECTIVE_URL(3) to generate a filename from a
+server-supplied redirect URL. Special care must be taken to sanitize such
+names to avoid the possibility of a malicious server supplying one like
+**"/etc/passwd"**, **"autoexec.bat"**, **"prn:"** or even **".bashrc"**.
+
+# Server Certificates
+
+A secure application should never use the CURLOPT_SSL_VERIFYPEER(3)
+option to disable certificate validation. There are numerous attacks that are
+enabled by applications that fail to properly validate server TLS/SSL
+certificates, thus enabling a malicious server to spoof a legitimate
+one. HTTPS without validated certificates is potentially as insecure as a
+plain HTTP connection.
+
+# Showing What You Do
+
+Relatedly, be aware that in situations when you have problems with libcurl and
+ask someone for help, everything you reveal in order to get best possible help
+might also impose certain security related risks. Host names, user names,
+paths, operating system specifics, etc. (not to mention passwords of course)
+may in fact be used by intruders to gain additional information of a potential
+target.
+
+Be sure to limit access to application logs if they could hold private or
+security-related data. Besides the obvious candidates like user names and
+passwords, things like URLs, cookies or even file names could also hold
+sensitive data.
+
+To avoid this problem, you must of course use your common sense. Often, you
+can just edit out the sensitive data or just search/replace your true
+information with faked data.
+
+# setuid applications using libcurl
+
+libcurl-using applications that set the 'setuid' bit to run with elevated or
+modified rights also implicitly give that extra power to libcurl and this
+should only be done after careful considerations.
+
+Giving setuid powers to the application means that libcurl can save files using
+those new rights (if for example the `SSLKEYLOGFILE` environment variable is
+set). Also: if the application wants these powers to read or manage secrets
+that the user is otherwise not able to view (like credentials for a login
+etc), it should be noted that libcurl still might understand proxy environment
+variables that allow the user to redirect libcurl operations to use a proxy
+controlled by the user.
+
+# File descriptors, fork and NTLM
+
+An application that uses libcurl and invokes *fork()* gets all file
+descriptors duplicated in the child process, including the ones libcurl
+created.
+
+libcurl itself uses *fork()* and *execl()* if told to use the
+**CURLAUTH_NTLM_WB** authentication method which then invokes the helper
+command in a child process with file descriptors duplicated. Make sure that
+only the trusted and reliable helper program is invoked!
+
+# Secrets in memory
+
+When applications pass user names, passwords or other sensitive data to
+libcurl to be used for upcoming transfers, those secrets are kept around as-is
+in memory. In many cases they are stored in the heap for as long as the handle
+itself for which the options are set.
+
+If an attacker can access the heap, like maybe by reading swap space or via a
+core dump file, such data might be accessible.
+
+Further, when eventually closing a handle and the secrets are no longer
+needed, libcurl does not explicitly clear memory before freeing it, so
+credentials may be left in freed data.
+
+# Saving files
+
+libcurl cannot protect against attacks where an attacker has write access to
+the same directory where libcurl is directed to save files.
+
+# Cookies
+
+If libcurl is built with PSL (**Public Suffix List**) support, it detects and
+discards cookies that are specified for such suffix domains that should not be
+allowed to have cookies.
+
+if libcurl is *not* built with PSL support, it has no ability to stop super
+cookies.
+
+# Report Security Problems
+
+Should you detect or just suspect a security problem in libcurl or curl,
+contact the project curl security team immediately. See
+https://curl.se/dev/secprocess.html for details.
diff --git a/docs/libcurl/libcurl-share.3 b/docs/libcurl/libcurl-share.3
deleted file mode 100644
index 7e7ee2ae6..000000000
--- a/docs/libcurl/libcurl-share.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH libcurl-share 3 "8 Aug 2003" "libcurl" "libcurl"
-.SH NAME
-libcurl-share \- how to use the share interface
-.SH DESCRIPTION
-This is an overview on how to use the libcurl share interface in your C
-programs. There are specific man pages for each function mentioned in
-here.
-
-All functions in the share interface are prefixed with curl_share.
-
-.SH "OBJECTIVES"
-The share interface was added to enable sharing of data between curl
-\&"handles".
-.SH "ONE SET OF DATA - MANY TRANSFERS"
-You can have multiple easy handles share data between them. Have them update
-and use the \fBsame\fP cookie database, DNS cache, TLS session cache and/or
-connection cache! This way, each single transfer takes advantage from data
-updates made by the other transfer(s).
-.SH "SHARE OBJECT"
-You create a shared object with \fIcurl_share_init(3)\fP. It returns a handle
-for a newly created one.
-
-You tell the shared object what data you want it to share by using
-\fIcurl_share_setopt(3)\fP.
-
-Since you can use this share from multiple threads, and libcurl has no
-internal thread synchronization, you must provide mutex callbacks if you are
-using this multi-threaded. You set lock and unlock functions with
-\fIcurl_share_setopt(3)\fP too.
-
-Then, you make an easy handle to use this share, you set the
-\fICURLOPT_SHARE(3)\fP option with \fIcurl_easy_setopt(3)\fP, and pass in
-share handle. You can make any number of easy handles share the same share
-handle.
-
-To make an easy handle stop using that particular share, you set
-\fICURLOPT_SHARE(3)\fP to NULL for that easy handle. To make a handle stop
-sharing a particular data, you can \fICURLSHOPT_UNSHARE(3)\fP it.
-
-When you are done using the share, make sure that no easy handle is still using
-it, and call \fIcurl_share_cleanup(3)\fP on the handle.
-.SH "SEE ALSO"
-.BR curl_share_init (3),
-.BR curl_share_setopt (3),
-.BR curl_share_cleanup (3),
-.BR libcurl-errors (3),
-.BR libcurl-easy (3),
-.BR libcurl-multi (3)
diff --git a/docs/libcurl/libcurl-share.md b/docs/libcurl/libcurl-share.md
new file mode 100644
index 000000000..e244b9726
--- /dev/null
+++ b/docs/libcurl/libcurl-share.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-share
+Section: 3
+Source: libcurl
+See-also:
+ - curl_share_cleanup (3)
+ - curl_share_init (3)
+ - curl_share_setopt (3)
+ - libcurl-easy (3)
+ - libcurl-errors (3)
+ - libcurl-multi (3)
+---
+
+# NAME
+
+libcurl-share - how to use the share interface
+
+# DESCRIPTION
+
+This is an overview on how to use the libcurl share interface in your C
+programs. There are specific man pages for each function mentioned in
+here.
+
+All functions in the share interface are prefixed with curl_share.
+
+# OBJECTIVES
+
+The share interface was added to enable sharing of data between curl handles.
+
+# ONE SET OF DATA - MANY TRANSFERS
+
+You can have multiple easy handles share data between them. Have them update
+and use the **same** cookie database, DNS cache, TLS session cache and/or
+connection cache! This way, each single transfer takes advantage from data
+updates made by the other transfer(s).
+
+# SHARE OBJECT
+
+You create a shared object with curl_share_init(3). It returns a handle
+for a newly created one.
+
+You tell the shared object what data you want it to share by using
+curl_share_setopt(3).
+
+Since you can use this share from multiple threads, and libcurl has no
+internal thread synchronization, you must provide mutex callbacks if you are
+using this multi-threaded. You set lock and unlock functions with
+curl_share_setopt(3) too.
+
+Then, you make an easy handle to use this share, you set the
+CURLOPT_SHARE(3) option with curl_easy_setopt(3), and pass in
+share handle. You can make any number of easy handles share the same share
+handle.
+
+To make an easy handle stop using that particular share, you set
+CURLOPT_SHARE(3) to NULL for that easy handle. To make a handle stop
+sharing a particular data, you can CURLSHOPT_UNSHARE(3) it.
+
+When you are done using the share, make sure that no easy handle is still using
+it, and call curl_share_cleanup(3) on the handle.
diff --git a/docs/libcurl/libcurl-thread.3 b/docs/libcurl/libcurl-thread.3
deleted file mode 100644
index 00e7d69d4..000000000
--- a/docs/libcurl/libcurl-thread.3
+++ /dev/null
@@ -1,123 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH libcurl-thread 3 "13 Jul 2015" "libcurl" "libcurl"
-.SH NAME
-libcurl-thread \- libcurl thread safety
-.SH "Multi-threading with libcurl"
-libcurl is thread safe but has no internal thread synchronization. You may have
-to provide your own locking should you meet any of the thread safety exceptions
-below.
-
-.SH "Handles"
-You must \fBnever\fP share the same handle in multiple threads. You can pass
-the handles around among threads, but you must never use a single handle from
-more than one thread at any given time.
-.SH "Shared objects"
-You can share certain data between multiple handles by using the share
-interface but you must provide your own locking and set
-\fIcurl_share_setopt(3)\fP CURLSHOPT_LOCKFUNC and CURLSHOPT_UNLOCKFUNC.
-
-Note that some items are specifically documented as not thread-safe in the
-share API (the connection pool and HSTS cache for example).
-.SH TLS
-If you are accessing HTTPS or FTPS URLs in a multi-threaded manner, you are
-then of course using the underlying SSL library multi-threaded and those libs
-might have their own requirements on this issue. You may need to provide one
-or two functions to allow it to function properly:
-.IP OpenSSL
-OpenSSL 1.1.0+ "can be safely used in multi-threaded applications provided that
-support for the underlying OS threading API is built-in." In that case the
-engine is used by libcurl in a way that is fully thread-safe.
-
-https://www.openssl.org/docs/man1.1.0/man3/CRYPTO_THREAD_run_once.html#DESCRIPTION
-
-OpenSSL <= 1.0.2 the user must set callbacks.
-
-https://www.openssl.org/docs/man1.0.2/man3/CRYPTO_set_locking_callback.html#DESCRIPTION
-
-https://curl.se/libcurl/c/opensslthreadlock.html
-
-.IP GnuTLS
-https://gnutls.org/manual/html_node/Thread-safety.html
-.IP NSS
-thread-safe already without anything required.
-.IP Secure-Transport
-The engine is used by libcurl in a way that is fully thread-safe.
-.IP Schannel
-The engine is used by libcurl in a way that is fully thread-safe.
-.IP wolfSSL
-The engine is used by libcurl in a way that is fully thread-safe.
-.IP BoringSSL
-The engine is used by libcurl in a way that is fully thread-safe.
-.IP AWS-LC
-The engine is used by libcurl in a way that is fully thread-safe.
-.SH "Signals"
-Signals are used for timing out name resolves (during DNS lookup) - when built
-without using either the c-ares or threaded resolver backends. On systems that
-have a signal concept.
-
-When using multiple threads you should set the \fICURLOPT_NOSIGNAL(3)\fP
-option to 1L for all handles. Everything works fine except that timeouts
-cannot be honored during DNS lookups - which you can work around by building
-libcurl with c-ares or threaded-resolver support. c-ares is a library that
-provides asynchronous name resolves. On some platforms, libcurl simply cannot
-function properly multi-threaded unless the \fICURLOPT_NOSIGNAL(3)\fP option
-is set.
-
-When \fICURLOPT_NOSIGNAL(3)\fP is set to 1L, your application needs to deal
-with the risk of a SIGPIPE (that at least the OpenSSL backend can
-trigger). Note that setting \fICURLOPT_NOSIGNAL(3)\fP to 0L does not work in a
-threaded situation as there is a race condition where libcurl risks restoring
-the former signal handler while another thread should still ignore it.
-.SH "Name resolving"
-The \fBgethostbyname\fP or \fBgetaddrinfo\fP and other name resolving system
-calls used by libcurl are provided by your operating system and must be thread
-safe. It is important that libcurl can find and use thread safe versions of
-these and other system calls, as otherwise it cannot function fully thread
-safe. Some operating systems are known to have faulty thread
-implementations. We have previously received problem reports on *BSD (at least
-in the past, they may be working fine these days). Some operating systems that
-are known to have solid and working thread support are Linux, Solaris and
-Windows.
-.SH "curl_global_* functions"
-These functions are thread-safe since libcurl 7.84.0 if
-\fIcurl_version_info(3)\fP has the \fBCURL_VERSION_THREADSAFE\fP feature bit
-set (most platforms).
-
-If these functions are not thread-safe and you are using libcurl with multiple
-threads it is especially important that before use you call
-\fIcurl_global_init(3)\fP or \fIcurl_global_init_mem(3)\fP to explicitly
-initialize the library and its dependents, rather than rely on the "lazy"
-fail-safe initialization that takes place the first time
-\fIcurl_easy_init(3)\fP is called. For an in-depth explanation refer to
-\fIlibcurl(3)\fP section \fBGLOBAL CONSTANTS\fP.
-.SH "Memory functions"
-These functions, provided either by your operating system or your own
-replacements, must be thread safe. You can use \fIcurl_global_init_mem(3)\fP
-to set your own replacement memory functions.
-.SH "Non-safe functions"
-\fICURLOPT_DNS_USE_GLOBAL_CACHE(3)\fP is not thread-safe.
-
-\fIcurl_version_info(3)\fP is not thread-safe before libcurl initialization.
diff --git a/docs/libcurl/libcurl-thread.md b/docs/libcurl/libcurl-thread.md
new file mode 100644
index 000000000..b3e9ecf82
--- /dev/null
+++ b/docs/libcurl/libcurl-thread.md
@@ -0,0 +1,99 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-thread
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl-security (3)
+---
+
+# NAME
+
+libcurl-thread - libcurl thread safety
+
+# Multi-threading with libcurl
+
+libcurl is thread safe but has no internal thread synchronization. You may have
+to provide your own locking should you meet any of the thread safety exceptions
+below.
+
+# Handles
+
+You must **never** share the same handle in multiple threads. You can pass the
+handles around among threads, but you must never use a single handle from more
+than one thread at any given time.
+
+# Shared objects
+
+You can share certain data between multiple handles by using the share
+interface but you must provide your own locking and set
+curl_share_setopt(3) CURLSHOPT_LOCKFUNC and CURLSHOPT_UNLOCKFUNC.
+
+Note that some items are specifically documented as not thread-safe in the
+share API (the connection pool and HSTS cache for example).
+
+# TLS
+
+All current TLS libraries libcurl supports are thread-safe. OpenSSL 1.1.0+ can
+be safely used in multi-threaded applications provided that support for the
+underlying OS threading API is built-in. For older versions of OpenSSL, the
+user must set mutex callbacks.
+
+# Signals
+
+Signals are used for timing out name resolves (during DNS lookup) - when built
+without using either the c-ares or threaded resolver backends. On systems that
+have a signal concept.
+
+When using multiple threads you should set the CURLOPT_NOSIGNAL(3)
+option to 1L for all handles. Everything works fine except that timeouts
+cannot be honored during DNS lookups - which you can work around by building
+libcurl with c-ares or threaded-resolver support. c-ares is a library that
+provides asynchronous name resolves. On some platforms, libcurl simply cannot
+function properly multi-threaded unless the CURLOPT_NOSIGNAL(3) option
+is set.
+
+When CURLOPT_NOSIGNAL(3) is set to 1L, your application needs to deal
+with the risk of a SIGPIPE (that at least the OpenSSL backend can
+trigger). Note that setting CURLOPT_NOSIGNAL(3) to 0L does not work in a
+threaded situation as there is a race condition where libcurl risks restoring
+the former signal handler while another thread should still ignore it.
+
+# Name resolving
+
+The **gethostbyname** or **getaddrinfo** and other name resolving system
+calls used by libcurl are provided by your operating system and must be thread
+safe. It is important that libcurl can find and use thread safe versions of
+these and other system calls, as otherwise it cannot function fully thread
+safe. Some operating systems are known to have faulty thread
+implementations. We have previously received problem reports on *BSD (at least
+in the past, they may be working fine these days). Some operating systems that
+are known to have solid and working thread support are Linux, Solaris and
+Windows.
+
+# curl_global_* functions
+
+These functions are thread-safe since libcurl 7.84.0 if
+curl_version_info(3) has the **CURL_VERSION_THREADSAFE** feature bit
+set (most platforms).
+
+If these functions are not thread-safe and you are using libcurl with multiple
+threads it is especially important that before use you call
+curl_global_init(3) or curl_global_init_mem(3) to explicitly
+initialize the library and its dependents, rather than rely on the "lazy"
+fail-safe initialization that takes place the first time
+curl_easy_init(3) is called. For an in-depth explanation refer to
+libcurl(3) section **GLOBAL CONSTANTS**.
+
+# Memory functions
+
+These functions, provided either by your operating system or your own
+replacements, must be thread safe. You can use curl_global_init_mem(3)
+to set your own replacement memory functions.
+
+# Non-safe functions
+
+CURLOPT_DNS_USE_GLOBAL_CACHE(3) is not thread-safe.
+
+curl_version_info(3) is not thread-safe before libcurl initialization.
diff --git a/docs/libcurl/libcurl-tutorial.3 b/docs/libcurl/libcurl-tutorial.3
deleted file mode 100644
index d312bd5de..000000000
--- a/docs/libcurl/libcurl-tutorial.3
+++ /dev/null
@@ -1,1398 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH libcurl-tutorial 3 "19 Sep 2014" "libcurl" "libcurl"
-.SH NAME
-libcurl-tutorial \- libcurl programming tutorial
-.SH "Objective"
-This document attempts to describe the general principles and some basic
-approaches to consider when programming with libcurl. The text focuses on the
-C interface but should apply fairly well on other language bindings as well as
-they usually follow the C API pretty closely.
-
-This document refers to 'the user' as the person writing the source code that
-uses libcurl. That would probably be you or someone in your position. What is
-generally referred to as 'the program' is the collected source code that you
-write that is using libcurl for transfers. The program is outside libcurl and
-libcurl is outside of the program.
-
-To get more details on all options and functions described herein, please
-refer to their respective man pages.
-
-.SH "Building"
-There are many different ways to build C programs. This chapter assumes a Unix
-style build process. If you use a different build system, you can still read
-this to get general information that may apply to your environment as well.
-.IP "Compiling the Program"
-Your compiler needs to know where the libcurl headers are located. Therefore
-you must set your compiler's include path to point to the directory where you
-installed them. The 'curl-config'[3] tool can be used to get this information:
-.nf
- $ curl-config --cflags
-.fi
-.IP "Linking the Program with libcurl"
-When having compiled the program, you need to link your object files to create
-a single executable. For that to succeed, you need to link with libcurl and
-possibly also with other libraries that libcurl itself depends on. Like the
-OpenSSL libraries, but even some standard OS libraries may be needed on the
-command line. To figure out which flags to use, once again the 'curl-config'
-tool comes to the rescue:
-.nf
- $ curl-config --libs
-.fi
-.IP "SSL or Not"
-libcurl can be built and customized in many ways. One of the things that
-varies from different libraries and builds is the support for SSL-based
-transfers, like HTTPS and FTPS. If a supported SSL library was detected
-properly at build-time, libcurl is built with SSL support. To figure out if an
-installed libcurl has been built with SSL support enabled, use \&'curl-config'
-like this:
-.nf
- $ curl-config --feature
-.fi
-And if SSL is supported, the keyword \fISSL\fP is written to stdout, possibly
-together with a other features that could be either on or off on for different
-libcurls.
-
-See also the "Features libcurl Provides" further down.
-.IP "autoconf macro"
-When you write your configure script to detect libcurl and setup variables
-accordingly, we offer a macro that probably does everything you need in this
-area. See docs/libcurl/libcurl.m4 file - it includes docs on how to use it.
-
-.SH "Portable Code in a Portable World"
-The people behind libcurl have put a considerable effort to make libcurl work
-on a large amount of different operating systems and environments.
-
-You program libcurl the same way on all platforms that libcurl runs on. There
-are only a few minor details that differ. If you just make sure to write your
-code portable enough, you can create a portable program. libcurl should not
-stop you from that.
-
-.SH "Global Preparation"
-The program must initialize some of the libcurl functionality globally. That
-means it should be done exactly once, no matter how many times you intend to
-use the library. Once for your program's entire life time. This is done using
-.nf
- curl_global_init()
-.fi
-and it takes one parameter which is a bit pattern that tells libcurl what to
-initialize. Using \fICURL_GLOBAL_ALL\fP makes it initialize all known internal
-sub modules, and might be a good default option. The current two bits that are
-specified are:
-.RS
-.IP "CURL_GLOBAL_WIN32"
-which only does anything on Windows machines. When used on a Windows machine,
-it makes libcurl initialize the win32 socket stuff. Without having that
-initialized properly, your program cannot use sockets properly. You should
-only do this once for each application, so if your program already does this
-or of another library in use does it, you should not tell libcurl to do this
-as well.
-.IP CURL_GLOBAL_SSL
-which only does anything on libcurls compiled and built SSL-enabled. On these
-systems, this makes libcurl initialize the SSL library properly for this
-application. This only needs to be done once for each application so if your
-program or another library already does this, this bit should not be needed.
-.RE
-
-libcurl has a default protection mechanism that detects if
-\fIcurl_global_init(3)\fP has not been called by the time
-\fIcurl_easy_perform(3)\fP is called and if that is the case, libcurl runs the
-function itself with a guessed bit pattern. Please note that depending solely
-on this is not considered nice nor good.
-
-When the program no longer uses libcurl, it should call
-\fIcurl_global_cleanup(3)\fP, which is the opposite of the init call. It
-performs the reversed operations to cleanup the resources the
-\fIcurl_global_init(3)\fP call initialized.
-
-Repeated calls to \fIcurl_global_init(3)\fP and \fIcurl_global_cleanup(3)\fP
-should be avoided. They should only be called once each.
-
-.SH "Features libcurl Provides"
-It is considered best-practice to determine libcurl features at runtime rather
-than at build-time (if possible of course). By calling
-\fIcurl_version_info(3)\fP and checking out the details of the returned
-struct, your program can figure out exactly what the currently running libcurl
-supports.
-
-.SH "Two Interfaces"
-libcurl first introduced the so called easy interface. All operations in the
-easy interface are prefixed with 'curl_easy'. The easy interface lets you do
-single transfers with a synchronous and blocking function call.
-
-libcurl also offers another interface that allows multiple simultaneous
-transfers in a single thread, the so called multi interface. More about that
-interface is detailed in a separate chapter further down. You still need to
-understand the easy interface first, so please continue reading for better
-understanding.
-.SH "Handle the Easy libcurl"
-To use the easy interface, you must first create yourself an easy handle. You
-need one handle for each easy session you want to perform. Basically, you
-should use one handle for every thread you plan to use for transferring. You
-must never share the same handle in multiple threads.
-
-Get an easy handle with
-.nf
- handle = curl_easy_init();
-.fi
-It returns an easy handle. Using that you proceed to the next step: setting
-up your preferred actions. A handle is just a logic entity for the upcoming
-transfer or series of transfers.
-
-You set properties and options for this handle using
-\fIcurl_easy_setopt(3)\fP. They control how the subsequent transfer or
-transfers using this handle are made. Options remain set in the handle until
-set again to something different. They are sticky. Multiple requests using the
-same handle use the same options.
-
-If you at any point would like to blank all previously set options for a
-single easy handle, you can call \fIcurl_easy_reset(3)\fP and you can also
-make a clone of an easy handle (with all its set options) using
-\fIcurl_easy_duphandle(3)\fP.
-
-Many of the options you set in libcurl are "strings", pointers to data
-terminated with a zero byte. When you set strings with
-\fIcurl_easy_setopt(3)\fP, libcurl makes its own copy so that they do not need
-to be kept around in your application after being set[4].
-
-One of the most basic properties to set in the handle is the URL. You set your
-preferred URL to transfer with \fICURLOPT_URL(3)\fP in a manner similar to:
-
-.nf
- curl_easy_setopt(handle, CURLOPT_URL, "http://domain.com/");
-.fi
-
-Let's assume for a while that you want to receive data as the URL identifies a
-remote resource you want to get here. Since you write a sort of application
-that needs this transfer, I assume that you would like to get the data passed
-to you directly instead of simply getting it passed to stdout. So, you write
-your own function that matches this prototype:
-.nf
- size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
-.fi
-You tell libcurl to pass all data to this function by issuing a function
-similar to this:
-.nf
- curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
-.fi
-You can control what data your callback function gets in the fourth argument
-by setting another property:
-.nf
- curl_easy_setopt(handle, CURLOPT_WRITEDATA, &internal_struct);
-.fi
-Using that property, you can easily pass local data between your application
-and the function that gets invoked by libcurl. libcurl itself does not touch
-the data you pass with \fICURLOPT_WRITEDATA(3)\fP.
-
-libcurl offers its own default internal callback that takes care of the data
-if you do not set the callback with \fICURLOPT_WRITEFUNCTION(3)\fP. It simply
-outputs the received data to stdout. You can have the default callback write
-the data to a different file handle by passing a 'FILE *' to a file opened for
-writing with the \fICURLOPT_WRITEDATA(3)\fP option.
-
-Now, we need to take a step back and take a deep breath. Here is one of those
-rare platform-dependent nitpicks. Did you spot it? On some platforms[2],
-libcurl is not able to operate on file handles opened by the
-program. Therefore, if you use the default callback and pass in an open file
-handle with \fICURLOPT_WRITEDATA(3)\fP, libcurl crashes. You should avoid this
-to make your program run fine virtually everywhere.
-
-(\fICURLOPT_WRITEDATA(3)\fP was formerly known as \fICURLOPT_FILE\fP. Both
-names still work and do the same thing).
-
-If you are using libcurl as a win32 DLL, you MUST use the
-\fICURLOPT_WRITEFUNCTION(3)\fP if you set \fICURLOPT_WRITEDATA(3)\fP - or
-experience crashes.
-
-There are of course many more options you can set, and we get back to a few of
-them later. Let's instead continue to the actual transfer:
-.nf
- success = curl_easy_perform(handle);
-.fi
-\fIcurl_easy_perform(3)\fP connects to the remote site, does the necessary
-commands and performs the transfer. Whenever it receives data, it calls the
-callback function we previously set. The function may get one byte at a time,
-or it may get many kilobytes at once. libcurl delivers as much as possible as
-often as possible. Your callback function should return the number of bytes it
-\&"took care of". If that is not the same amount of bytes that was passed to
-it, libcurl aborts the operation and returns with an error code.
-
-When the transfer is complete, the function returns a return code that informs
-you if it succeeded in its mission or not. If a return code is not enough for
-you, you can use the \fICURLOPT_ERRORBUFFER(3)\fP to point libcurl to a buffer
-of yours where it stores a human readable error message as well.
-
-If you then want to transfer another file, the handle is ready to be used
-again. It is even preferred and encouraged that you reuse an existing handle
-if you intend to make another transfer. libcurl then attempts to reuse a
-previous connection.
-
-For some protocols, downloading a file can involve a complicated process of
-logging in, setting the transfer mode, changing the current directory and
-finally transferring the file data. libcurl takes care of all that
-complication for you. Given simply the URL to a file, libcurl takes care of
-all the details needed to get the file moved from one machine to another.
-
-.SH "Multi-threading Issues"
-libcurl is thread safe but there are a few exceptions. Refer to
-\fIlibcurl-thread(3)\fP for more information.
-
-.SH "When It does not Work"
-There are times when the transfer fails for some reason. You might have set
-the wrong libcurl option or misunderstood what the libcurl option actually
-does, or the remote server might return non-standard replies that confuse the
-library which then confuses your program.
-
-There is one golden rule when these things occur: set the
-\fICURLOPT_VERBOSE(3)\fP option to 1. it causes the library to spew out the
-entire protocol details it sends, some internal info and some received
-protocol data as well (especially when using FTP). If you are using HTTP,
-adding the headers in the received output to study is also a clever way to get
-a better understanding why the server behaves the way it does. Include headers
-in the normal body output with \fICURLOPT_HEADER(3)\fP set 1.
-
-Of course, there are bugs left. We need to know about them to be able to fix
-them, so we are quite dependent on your bug reports. When you do report
-suspected bugs in libcurl, please include as many details as you possibly can:
-a protocol dump that \fICURLOPT_VERBOSE(3)\fP produces, library version, as
-much as possible of your code that uses libcurl, operating system name and
-version, compiler name and version etc.
-
-If \fICURLOPT_VERBOSE(3)\fP is not enough, you increase the level of debug
-data your application receive by using the \fICURLOPT_DEBUGFUNCTION(3)\fP.
-
-Getting some in-depth knowledge about the protocols involved is never wrong,
-and if you are trying to do funny things, you might understand libcurl and how
-to use it better if you study the appropriate RFC documents at least briefly.
-
-.SH "Upload Data to a Remote Site"
-libcurl tries to keep a protocol independent approach to most transfers, thus
-uploading to a remote FTP site is similar to uploading data to an HTTP server
-with a PUT request.
-
-Of course, first you either create an easy handle or you reuse one existing
-one. Then you set the URL to operate on just like before. This is the remote
-URL, that we now upload.
-
-Since we write an application, we most likely want libcurl to get the upload
-data by asking us for it. To make it do that, we set the read callback and the
-custom pointer libcurl passes to our read callback. The read callback should
-have a prototype similar to:
-.nf
- size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
-.fi
-Where \fIbufptr\fP is the pointer to a buffer we fill in with data to upload
-and \fIsize*nitems\fP is the size of the buffer and therefore also the maximum
-amount of data we can return to libcurl in this call. The \fIuserp\fP pointer
-is the custom pointer we set to point to a struct of ours to pass private data
-between the application and the callback.
-.nf
- curl_easy_setopt(handle, CURLOPT_READFUNCTION, read_function);
-
- curl_easy_setopt(handle, CURLOPT_READDATA, &filedata);
-.fi
-Tell libcurl that we want to upload:
-.nf
- curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
-.fi
-A few protocols do not behave properly when uploads are done without any prior
-knowledge of the expected file size. So, set the upload file size using the
-\fICURLOPT_INFILESIZE_LARGE(3)\fP for all known file sizes like this[1]:
-
-.nf
- /* in this example, file_size must be an curl_off_t variable */
- curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, file_size);
-.fi
-
-When you call \fIcurl_easy_perform(3)\fP this time, it performs all the
-necessary operations and when it has invoked the upload it calls your supplied
-callback to get the data to upload. The program should return as much data as
-possible in every invoke, as that is likely to make the upload perform as fast
-as possible. The callback should return the number of bytes it wrote in the
-buffer. Returning 0 signals the end of the upload.
-
-.SH "Passwords"
-Many protocols use or even require that user name and password are provided
-to be able to download or upload the data of your choice. libcurl offers
-several ways to specify them.
-
-Most protocols support that you specify the name and password in the URL
-itself. libcurl detects this and use them accordingly. This is written like
-this:
-.nf
- protocol://user:password@example.com/path/
-.fi
-If you need any odd letters in your user name or password, you should enter
-them URL encoded, as %XX where XX is a two-digit hexadecimal number.
-
-libcurl also provides options to set various passwords. The user name and
-password as shown embedded in the URL can instead get set with the
-\fICURLOPT_USERPWD(3)\fP option. The argument passed to libcurl should be a
-char * to a string in the format "user:password". In a manner like this:
-.nf
- curl_easy_setopt(handle, CURLOPT_USERPWD, "myname:thesecret");
-.fi
-Another case where name and password might be needed at times, is for those
-users who need to authenticate themselves to a proxy they use. libcurl offers
-another option for this, the \fICURLOPT_PROXYUSERPWD(3)\fP. It is used quite
-similar to the \fICURLOPT_USERPWD(3)\fP option like this:
-.nf
- curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, "myname:thesecret");
-.fi
-There is a long time Unix "standard" way of storing FTP user names and
-passwords, namely in the $HOME/.netrc file (on Windows, libcurl also checks
-the \fI%USERPROFILE% environment\fP variable if \fI%HOME%\fP is unset, and
-tries "_netrc" as name). The file should be made private so that only the user
-may read it (see also the "Security Considerations" chapter), as it might
-contain the password in plain text. libcurl has the ability to use this file
-to figure out what set of user name and password to use for a particular
-host. As an extension to the normal functionality, libcurl also supports this
-file for non-FTP protocols such as HTTP. To make curl use this file, use the
-\fICURLOPT_NETRC(3)\fP option:
-.nf
- curl_easy_setopt(handle, CURLOPT_NETRC, 1L);
-.fi
-And a basic example of how such a .netrc file may look like:
-
-.nf
- machine myhost.mydomain.com
- login userlogin
- password secretword
-.fi
-
-All these examples have been cases where the password has been optional, or
-at least you could leave it out and have libcurl attempt to do its job
-without it. There are times when the password is not optional, like when
-you are using an SSL private key for secure transfers.
-
-To pass the known private key password to libcurl:
-.nf
- curl_easy_setopt(handle, CURLOPT_KEYPASSWD, "keypassword");
-.fi
-.SH "HTTP Authentication"
-The previous chapter showed how to set user name and password for getting URLs
-that require authentication. When using the HTTP protocol, there are many
-different ways a client can provide those credentials to the server and you
-can control which way libcurl uses them. The default HTTP authentication
-method is called 'Basic', which is sending the name and password in clear-text
-in the HTTP request, base64-encoded. This is insecure.
-
-At the time of this writing, libcurl can be built to use: Basic, Digest, NTLM,
-Negotiate (SPNEGO). You can tell libcurl which one to use
-with \fICURLOPT_HTTPAUTH(3)\fP as in:
-.nf
- curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
-.fi
-And when you send authentication to a proxy, you can also set authentication
-type the same way but instead with \fICURLOPT_PROXYAUTH(3)\fP:
-.nf
- curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
-.fi
-Both these options allow you to set multiple types (by ORing them together),
-to make libcurl pick the most secure one out of the types the server/proxy
-claims to support. This method does however add a round-trip since libcurl
-must first ask the server what it supports:
-.nf
- curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
-.fi
-For convenience, you can use the \fICURLAUTH_ANY\fP define (instead of a list
-with specific types) which allows libcurl to use whatever method it wants.
-
-When asking for multiple types, libcurl picks the available one it considers
-"best" in its own internal order of preference.
-
-.SH "HTTP POSTing"
-We get many questions regarding how to issue HTTP POSTs with libcurl the
-proper way. This chapter thus includes examples using both different versions
-of HTTP POST that libcurl supports.
-
-The first version is the simple POST, the most common version, that most HTML
-pages using the <form> tag uses. We provide a pointer to the data and tell
-libcurl to post it all to the remote site:
-
-.nf
- char *data="name=daniel&project=curl";
- curl_easy_setopt(handle, CURLOPT_POSTFIELDS, data);
- curl_easy_setopt(handle, CURLOPT_URL, "http://posthere.com/");
-
- curl_easy_perform(handle); /* post away! */
-.fi
-
-Simple enough, huh? Since you set the POST options with the
-\fICURLOPT_POSTFIELDS(3)\fP, this automatically switches the handle to use
-POST in the upcoming request.
-
-What if you want to post binary data that also requires you to set the
-Content-Type: header of the post? Well, binary posts prevent libcurl from being
-able to do strlen() on the data to figure out the size, so therefore we must
-tell libcurl the size of the post data. Setting headers in libcurl requests are
-done in a generic way, by building a list of our own headers and then passing
-that list to libcurl.
-
-.nf
- struct curl_slist *headers=NULL;
- headers = curl_slist_append(headers, "Content-Type: text/xml");
-
- /* post binary data */
- curl_easy_setopt(handle, CURLOPT_POSTFIELDS, binaryptr);
-
- /* set the size of the postfields data */
- curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, 23L);
-
- /* pass our list of custom made headers */
- curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
-
- curl_easy_perform(handle); /* post away! */
-
- curl_slist_free_all(headers); /* free the header list */
-.fi
-
-While the simple examples above cover the majority of all cases where HTTP
-POST operations are required, they do not do multi-part formposts. Multi-part
-formposts were introduced as a better way to post (possibly large) binary data
-and were first documented in the RFC 1867 (updated in RFC 2388). they are
-called multi-part because they are built by a chain of parts, each part being
-a single unit of data. Each part has its own name and contents. You can in
-fact create and post a multi-part formpost with the regular libcurl POST
-support described above, but that would require that you build a formpost
-yourself and provide to libcurl. To make that easier, libcurl provides a MIME
-API consisting in several functions: using those, you can create and fill a
-multi-part form. Function \fIcurl_mime_init(3)\fP creates a multi-part body;
-you can then append new parts to a multi-part body using
-\fIcurl_mime_addpart(3)\fP. There are three possible data sources for a part:
-memory using \fIcurl_mime_data(3)\fP, file using \fIcurl_mime_filedata(3)\fP
-and user-defined data read callback using \fIcurl_mime_data_cb(3)\fP.
-\fIcurl_mime_name(3)\fP sets a part's (i.e.: form field) name, while
-\fIcurl_mime_filename(3)\fP fills in the remote file name. With
-\fIcurl_mime_type(3)\fP, you can tell the MIME type of a part,
-\fIcurl_mime_headers(3)\fP allows defining the part's headers. When a
-multi-part body is no longer needed, you can destroy it using
-\fIcurl_mime_free(3)\fP.
-
-The following example sets two simple text parts with plain textual contents,
-and then a file with binary contents and uploads the whole thing.
-
-.nf
- curl_mime *multipart = curl_mime_init(handle);
- curl_mimepart *part = curl_mime_addpart(multipart);
- curl_mime_name(part, "name");
- curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "project");
- curl_mime_data(part, "curl", CURL_ZERO_TERMINATED);
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "logotype-image");
- curl_mime_filedata(part, "curl.png");
-
- /* Set the form info */
- curl_easy_setopt(handle, CURLOPT_MIMEPOST, multipart);
-
- curl_easy_perform(handle); /* post away! */
-
- /* free the post data again */
- curl_mime_free(multipart);
-.fi
-
-To post multiple files for a single form field, you must supply each file in
-a separate part, all with the same field name. Although function
-\fIcurl_mime_subparts(3)\fP implements nested multi-parts, this way of
-multiple files posting is deprecated by RFC 7578, chapter 4.3.
-
-To set the data source from an already opened FILE pointer, use:
-
-.nf
- curl_mime_data_cb(part, filesize, (curl_read_callback) fread,
- (curl_seek_callback) fseek, NULL, filepointer);
-.fi
-
-A deprecated \fIcurl_formadd(3)\fP function is still supported in libcurl.
-It should however not be used anymore for new designs and programs using it
-ought to be converted to the MIME API. It is however described here as an
-aid to conversion.
-
-Using \fIcurl_formadd\fP, you add parts to the form. When you are done adding
-parts, you post the whole form.
-
-The MIME API example above is expressed as follows using this function:
-
-.nf
- struct curl_httppost *post=NULL;
- struct curl_httppost *last=NULL;
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "name",
- CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "project",
- CURLFORM_COPYCONTENTS, "curl", CURLFORM_END);
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "logotype-image",
- CURLFORM_FILECONTENT, "curl.png", CURLFORM_END);
-
- /* Set the form info */
- curl_easy_setopt(handle, CURLOPT_HTTPPOST, post);
-
- curl_easy_perform(handle); /* post away! */
-
- /* free the post data again */
- curl_formfree(post);
-.fi
-
-Multipart formposts are chains of parts using MIME-style separators and
-headers. It means that each one of these separate parts get a few headers set
-that describe the individual content-type, size etc. To enable your
-application to handicraft this formpost even more, libcurl allows you to
-supply your own set of custom headers to such an individual form part. You can
-of course supply headers to as many parts as you like, but this little example
-shows how you set headers to one specific part when you add that to the post
-handle:
-
-.nf
- struct curl_slist *headers=NULL;
- headers = curl_slist_append(headers, "Content-Type: text/xml");
-
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "logotype-image",
- CURLFORM_FILECONTENT, "curl.xml",
- CURLFORM_CONTENTHEADER, headers,
- CURLFORM_END);
-
- curl_easy_perform(handle); /* post away! */
-
- curl_formfree(post); /* free post */
- curl_slist_free_all(headers); /* free custom header list */
-.fi
-
-Since all options on an easy handle are "sticky", they remain the same until
-changed even if you do call \fIcurl_easy_perform(3)\fP, you may need to tell
-curl to go back to a plain GET request if you intend to do one as your next
-request. You force an easy handle to go back to GET by using the
-\fICURLOPT_HTTPGET(3)\fP option:
-.nf
- curl_easy_setopt(handle, CURLOPT_HTTPGET, 1L);
-.fi
-Just setting \fICURLOPT_POSTFIELDS(3)\fP to "" or NULL does *not* stop libcurl
-from doing a POST. It just makes it POST without any data to send!
-
-.SH "Converting from deprecated form API to MIME API"
-Four rules have to be respected in building the multi-part:
-.br
-- The easy handle must be created before building the multi-part.
-.br
-- The multi-part is always created by a call to curl_mime_init(handle).
-.br
-- Each part is created by a call to curl_mime_addpart(multipart).
-.br
-- When complete, the multi-part must be bound to the easy handle using
-\fICURLOPT_MIMEPOST(3)\fP instead of \fICURLOPT_HTTPPOST(3)\fP.
-
-Here are some example of \fIcurl_formadd\fP calls to MIME API sequences:
-
-.nf
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "id",
- CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
- CURLFORM_CONTENTHEADER, headers,
- CURLFORM_END);
-.fi
-becomes:
-.nf
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "id");
- curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
- curl_mime_headers(part, headers, FALSE);
-.fi
-
-Setting the last \fIcurl_mime_headers(3)\fP argument to TRUE would have caused
-the headers to be automatically released upon destroyed the multi-part, thus
-saving a clean-up call to \fIcurl_slist_free_all(3)\fP.
-
-.nf
- curl_formadd(&post, &last,
- CURLFORM_PTRNAME, "logotype-image",
- CURLFORM_FILECONTENT, "-",
- CURLFORM_END);
-.fi
-becomes:
-.nf
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "logotype-image");
- curl_mime_data_cb(part, (curl_off_t) -1, fread, fseek, NULL, stdin);
-.fi
-
-\fIcurl_mime_name(3)\fP always copies the field name. The special file name
-"-" is not supported by \fIcurl_mime_filename(3)\fP: to read an open file, use
-a callback source using fread(). The transfer is be chunk-encoded since the
-data size is unknown.
-
-.nf
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "datafile[]",
- CURLFORM_FILE, "file1",
- CURLFORM_FILE, "file2",
- CURLFORM_END);
-.fi
-becomes:
-.nf
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "datafile[]");
- curl_mime_filedata(part, "file1");
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "datafile[]");
- curl_mime_filedata(part, "file2");
-.fi
-
-The deprecated multipart/mixed implementation of multiple files field is
-translated to two distinct parts with the same name.
-
-.nf
- curl_easy_setopt(handle, CURLOPT_READFUNCTION, myreadfunc);
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "stream",
- CURLFORM_STREAM, arg,
- CURLFORM_CONTENTLEN, (curl_off_t) datasize,
- CURLFORM_FILENAME, "archive.zip",
- CURLFORM_CONTENTTYPE, "application/zip",
- CURLFORM_END);
-.fi
-becomes:
-.nf
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "stream");
- curl_mime_data_cb(part, (curl_off_t) datasize,
- myreadfunc, NULL, NULL, arg);
- curl_mime_filename(part, "archive.zip");
- curl_mime_type(part, "application/zip");
-.fi
-
-\fICURLOPT_READFUNCTION(3)\fP callback is not used: it is replace by directly
-setting the part source data from the callback read function.
-
-.nf
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "memfile",
- CURLFORM_BUFFER, "memfile.bin",
- CURLFORM_BUFFERPTR, databuffer,
- CURLFORM_BUFFERLENGTH, (long) sizeof databuffer,
- CURLFORM_END);
-.fi
-becomes:
-.nf
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "memfile");
- curl_mime_data(part, databuffer, (curl_off_t) sizeof databuffer);
- curl_mime_filename(part, "memfile.bin");
-.fi
-
-\fIcurl_mime_data(3)\fP always copies the initial data: data buffer is thus
-free for immediate reuse.
-
-.nf
- curl_formadd(&post, &last,
- CURLFORM_COPYNAME, "message",
- CURLFORM_FILECONTENT, "msg.txt",
- CURLFORM_END);
-.fi
-becomes:
-.nf
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "message");
- curl_mime_filedata(part, "msg.txt");
- curl_mime_filename(part, NULL);
-.fi
-
-Use of \fIcurl_mime_filedata(3)\fP sets the remote file name as a side effect:
-it is therefore necessary to clear it for \fICURLFORM_FILECONTENT\fP
-emulation.
-
-.SH "Showing Progress"
-
-For historical and traditional reasons, libcurl has a built-in progress meter
-that can be switched on and then makes it present a progress meter in your
-terminal.
-
-Switch on the progress meter by, oddly enough, setting
-\fICURLOPT_NOPROGRESS(3)\fP to zero. This option is set to 1 by default.
-
-For most applications however, the built-in progress meter is useless and what
-instead is interesting is the ability to specify a progress callback. The
-function pointer you pass to libcurl is then called on irregular intervals
-with information about the current transfer.
-
-Set the progress callback by using \fICURLOPT_PROGRESSFUNCTION(3)\fP. And pass
-a pointer to a function that matches this prototype:
-
-.nf
- int progress_callback(void *clientp,
- double dltotal,
- double dlnow,
- double ultotal,
- double ulnow);
-.fi
-
-If any of the input arguments is unknown, a 0 is provided. The first argument,
-the 'clientp' is the pointer you pass to libcurl with
-\fICURLOPT_PROGRESSDATA(3)\fP. libcurl does not touch it.
-
-.SH "libcurl with C++"
-
-There is basically only one thing to keep in mind when using C++ instead of C
-when interfacing libcurl:
-
-The callbacks CANNOT be non-static class member functions
-
-Example C++ code:
-
-.nf
-class AClass {
- static size_t write_data(void *ptr, size_t size, size_t nmemb,
- void *ourpointer)
- {
- /* do what you want with the data */
- }
- }
-.fi
-
-.SH "Proxies"
-
-What "proxy" means according to Merriam-Webster: "a person authorized to act
-for another" but also "the agency, function, or office of a deputy who acts as
-a substitute for another".
-
-Proxies are exceedingly common these days. Companies often only offer Internet
-access to employees through their proxies. Network clients or user-agents ask
-the proxy for documents, the proxy does the actual request and then it returns
-them.
-
-libcurl supports SOCKS and HTTP proxies. When a given URL is wanted, libcurl
-asks the proxy for it instead of trying to connect to the actual remote host
-identified in the URL.
-
-If you are using a SOCKS proxy, you may find that libcurl does not quite support
-all operations through it.
-
-For HTTP proxies: the fact that the proxy is an HTTP proxy puts certain
-restrictions on what can actually happen. A requested URL that might not be a
-HTTP URL is passed to the HTTP proxy to deliver back to libcurl. This happens
-transparently, and an application may not need to know. I say "may", because
-at times it is important to understand that all operations over an HTTP proxy
-use the HTTP protocol. For example, you cannot invoke your own custom FTP
-commands or even proper FTP directory listings.
-
-.IP "Proxy Options"
-
-To tell libcurl to use a proxy at a given port number:
-.nf
- curl_easy_setopt(handle, CURLOPT_PROXY, "proxy-host.com:8080");
-.fi
-Some proxies require user authentication before allowing a request, and you
-pass that information similar to this:
-.nf
- curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, "user:password");
-.fi
-If you want to, you can specify the host name only in the
-\fICURLOPT_PROXY(3)\fP option, and set the port number separately with
-\fICURLOPT_PROXYPORT(3)\fP.
-
-Tell libcurl what kind of proxy it is with \fICURLOPT_PROXYTYPE(3)\fP (if not,
-it defaults to assuming an HTTP proxy):
-.nf
- curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
-.fi
-.IP "Environment Variables"
-
-libcurl automatically checks and uses a set of environment variables to know
-what proxies to use for certain protocols. The names of the variables are
-following an old tradition and are built up as "[protocol]_proxy" (note the
-lower casing). Which makes the variable \&'http_proxy' checked for a name of a
-proxy to use when the input URL is HTTP. Following the same rule, the variable
-named 'ftp_proxy' is checked for FTP URLs. Again, the proxies are always HTTP
-proxies, the different names of the variables simply allows different HTTP
-proxies to be used.
-
-The proxy environment variable contents should be in the format
-\&"[protocol://][user:password@]machine[:port]". Where the protocol:// part
-specifies which type of proxy it is, and the optional port number specifies on
-which port the proxy operates. If not specified, the internal default port
-number is used and that is most likely not the one you would like it to be.
-
-There are two special environment variables. 'all_proxy' is what sets proxy
-for any URL in case the protocol specific variable was not set, and
-\&'no_proxy' defines a list of hosts that should not use a proxy even though a
-variable may say so. If 'no_proxy' is a plain asterisk ("*") it matches all
-hosts.
-
-To explicitly disable libcurl's checking for and using the proxy environment
-variables, set the proxy name to "" - an empty string - with
-\fICURLOPT_PROXY(3)\fP.
-.IP "SSL and Proxies"
-
-SSL is for secure point-to-point connections. This involves strong encryption
-and similar things, which effectively makes it impossible for a proxy to
-operate as a "man in between" which the proxy's task is, as previously
-discussed. Instead, the only way to have SSL work over an HTTP proxy is to ask
-the proxy to tunnel everything through without being able to check or fiddle
-with the traffic.
-
-Opening an SSL connection over an HTTP proxy is therefore a matter of asking the
-proxy for a straight connection to the target host on a specified port. This
-is made with the HTTP request CONNECT. ("please dear proxy, connect me to that
-remote host").
-
-Because of the nature of this operation, where the proxy has no idea what kind
-of data that is passed in and out through this tunnel, this breaks some of the
-few advantages that come from using a proxy, such as caching. Many
-organizations prevent this kind of tunneling to other destination port numbers
-than 443 (which is the default HTTPS port number).
-
-.IP "Tunneling Through Proxy"
-As explained above, tunneling is required for SSL to work and often even
-restricted to the operation intended for SSL; HTTPS.
-
-This is however not the only time proxy-tunneling might offer benefits to
-you or your application.
-
-As tunneling opens a direct connection from your application to the remote
-machine, it suddenly also re-introduces the ability to do non-HTTP
-operations over an HTTP proxy. You can in fact use things such as FTP
-upload or FTP custom commands this way.
-
-Again, this is often prevented by the administrators of proxies and is
-rarely allowed.
-
-Tell libcurl to use proxy tunneling like this:
-.nf
- curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1L);
-.fi
-In fact, there might even be times when you want to do plain HTTP operations
-using a tunnel like this, as it then enables you to operate on the remote
-server instead of asking the proxy to do so. libcurl does not stand in the way
-for such innovative actions either!
-
-.IP "Proxy Auto-Config"
-
-Netscape first came up with this. It is basically a web page (usually using a
-\&.pac extension) with a JavaScript that when executed by the browser with the
-requested URL as input, returns information to the browser on how to connect
-to the URL. The returned information might be "DIRECT" (which means no proxy
-should be used), "PROXY host:port" (to tell the browser where the proxy for
-this particular URL is) or "SOCKS host:port" (to direct the browser to a SOCKS
-proxy).
-
-libcurl has no means to interpret or evaluate JavaScript and thus it does not
-support this. If you get yourself in a position where you face this nasty
-invention, the following advice have been mentioned and used in the past:
-
-- Depending on the JavaScript complexity, write up a script that translates it
-to another language and execute that.
-
-- Read the JavaScript code and rewrite the same logic in another language.
-
-- Implement a JavaScript interpreter; people have successfully used the
-Mozilla JavaScript engine in the past.
-
-- Ask your admins to stop this, for a static proxy setup or similar.
-
-.SH "Persistence Is The Way to Happiness"
-
-Re-cycling the same easy handle several times when doing multiple requests is
-the way to go.
-
-After each single \fIcurl_easy_perform(3)\fP operation, libcurl keeps the
-connection alive and open. A subsequent request using the same easy handle to
-the same host might just be able to use the already open connection! This
-reduces network impact a lot.
-
-Even if the connection is dropped, all connections involving SSL to the same
-host again, benefit from libcurl's session ID cache that drastically reduces
-re-connection time.
-
-FTP connections that are kept alive save a lot of time, as the command-
-response round-trips are skipped, and also you do not risk getting blocked
-without permission to login again like on many FTP servers only allowing N
-persons to be logged in at the same time.
-
-libcurl caches DNS name resolving results, to make lookups of a previously
-looked up name a lot faster.
-
-Other interesting details that improve performance for subsequent requests
-may also be added in the future.
-
-Each easy handle attempts to keep the last few connections alive for a while
-in case they are to be used again. You can set the size of this "cache" with
-the \fICURLOPT_MAXCONNECTS(3)\fP option. Default is 5. There is rarely any
-point in changing this value, and if you think of changing this it is often
-just a matter of thinking again.
-
-To force your upcoming request to not use an already existing connection, you
-can do that by setting \fICURLOPT_FRESH_CONNECT(3)\fP to 1. In a similar
-spirit, you can also forbid the upcoming request to be "lying" around and
-possibly get reused after the request by setting
-\fICURLOPT_FORBID_REUSE(3)\fP to 1.
-
-.SH "HTTP Headers Used by libcurl"
-When you use libcurl to do HTTP requests, it passes along a series of headers
-automatically. It might be good for you to know and understand these. You can
-replace or remove them by using the \fICURLOPT_HTTPHEADER(3)\fP option.
-
-.IP "Host"
-This header is required by HTTP 1.1 and even many 1.0 servers and should be
-the name of the server we want to talk to. This includes the port number if
-anything but default.
-
-.IP "Accept"
-\&"*/*".
-
-.IP "Expect"
-When doing POST requests, libcurl sets this header to \&"100-continue" to ask
-the server for an "OK" message before it proceeds with sending the data part
-of the post. If the posted data amount is deemed "small", libcurl does not use
-this header.
-
-.SH "Customizing Operations"
-There is an ongoing development today where more and more protocols are built
-upon HTTP for transport. This has obvious benefits as HTTP is a tested and
-reliable protocol that is widely deployed and has excellent proxy-support.
-
-When you use one of these protocols, and even when doing other kinds of
-programming you may need to change the traditional HTTP (or FTP or...)
-manners. You may need to change words, headers or various data.
-
-libcurl is your friend here too.
-
-.IP CUSTOMREQUEST
-If just changing the actual HTTP request keyword is what you want, like when
-GET, HEAD or POST is not good enough for you, \fICURLOPT_CUSTOMREQUEST(3)\fP
-is there for you. It is simple to use:
-.nf
- curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MYOWNREQUEST");
-.fi
-When using the custom request, you change the request keyword of the actual
-request you are performing. Thus, by default you make a GET request but you can
-also make a POST operation (as described before) and then replace the POST
-keyword if you want to. you are the boss.
-
-.IP "Modify Headers"
-HTTP-like protocols pass a series of headers to the server when doing the
-request, and you are free to pass any amount of extra headers that you
-think fit. Adding headers is this easy:
-
-.nf
- struct curl_slist *headers=NULL; /* init to NULL is important */
-
- headers = curl_slist_append(headers, "Hey-server-hey: how are you?");
- headers = curl_slist_append(headers, "X-silly-content: yes");
-
- /* pass our list of custom made headers */
- curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
-
- curl_easy_perform(handle); /* transfer http */
-
- curl_slist_free_all(headers); /* free the header list */
-.fi
-
-\&... and if you think some of the internally generated headers, such as
-Accept: or Host: do not contain the data you want them to contain, you can
-replace them by simply setting them too:
-
-.nf
- headers = curl_slist_append(headers, "Accept: Agent-007");
- headers = curl_slist_append(headers, "Host: munged.host.line");
-.fi
-
-.IP "Delete Headers"
-If you replace an existing header with one with no contents, you prevent the
-header from being sent. For instance, if you want to completely prevent the
-\&"Accept:" header from being sent, you can disable it with code similar to
-this:
-
- headers = curl_slist_append(headers, "Accept:");
-
-Both replacing and canceling internal headers should be done with careful
-consideration and you should be aware that you may violate the HTTP protocol
-when doing so.
-
-.IP "Enforcing chunked transfer-encoding"
-
-By making sure a request uses the custom header "Transfer-Encoding: chunked"
-when doing a non-GET HTTP operation, libcurl switches over to "chunked"
-upload, even though the size of the data to upload might be known. By default,
-libcurl usually switches over to chunked upload automatically if the upload
-data size is unknown.
-
-.IP "HTTP Version"
-
-All HTTP requests includes the version number to tell the server which version
-we support. libcurl speaks HTTP 1.1 by default. Some old servers do not like
-getting 1.1-requests and when dealing with stubborn old things like that, you
-can tell libcurl to use 1.0 instead by doing something like this:
-
- curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
-
-.IP "FTP Custom Commands"
-
-Not all protocols are HTTP-like, and thus the above may not help you when
-you want to make, for example, your FTP transfers to behave differently.
-
-Sending custom commands to an FTP server means that you need to send the
-commands exactly as the FTP server expects them (RFC 959 is a good guide
-here), and you can only use commands that work on the control-connection
-alone. All kinds of commands that require data interchange and thus need a
-data-connection must be left to libcurl's own judgment. Also be aware that
-libcurl does its best to change directory to the target directory before doing
-any transfer, so if you change directory (with CWD or similar) you might
-confuse libcurl and then it might not attempt to transfer the file in the
-correct remote directory.
-
-A little example that deletes a given file before an operation:
-
-.nf
- headers = curl_slist_append(headers, "DELE file-to-remove");
-
- /* pass the list of custom commands to the handle */
- curl_easy_setopt(handle, CURLOPT_QUOTE, headers);
-
- curl_easy_perform(handle); /* transfer ftp data! */
-
- curl_slist_free_all(headers); /* free the header list */
-.fi
-
-If you would instead want this operation (or chain of operations) to happen
-_after_ the data transfer took place the option to \fIcurl_easy_setopt(3)\fP
-would instead be called \fICURLOPT_POSTQUOTE(3)\fP and used the exact same
-way.
-
-The custom FTP commands are issued to the server in the same order they are
-added to the list, and if a command gets an error code returned back from the
-server, no more commands are issued and libcurl bails out with an error code
-(CURLE_QUOTE_ERROR). Note that if you use \fICURLOPT_QUOTE(3)\fP to send
-commands before a transfer, no transfer actually takes place when a quote
-command has failed.
-
-If you set the \fICURLOPT_HEADER(3)\fP to 1, you tell libcurl to get
-information about the target file and output "headers" about it. The headers
-are in "HTTP-style", looking like they do in HTTP.
-
-The option to enable headers or to run custom FTP commands may be useful to
-combine with \fICURLOPT_NOBODY(3)\fP. If this option is set, no actual file
-content transfer is performed.
-
-.IP "FTP Custom CUSTOMREQUEST"
-If you do want to list the contents of an FTP directory using your own defined
-FTP command, \fICURLOPT_CUSTOMREQUEST(3)\fP does just that. "NLST" is the
-default one for listing directories but you are free to pass in your idea of a
-good alternative.
-
-.SH "Cookies Without Chocolate Chips"
-In the HTTP sense, a cookie is a name with an associated value. A server sends
-the name and value to the client, and expects it to get sent back on every
-subsequent request to the server that matches the particular conditions
-set. The conditions include that the domain name and path match and that the
-cookie has not become too old.
-
-In real-world cases, servers send new cookies to replace existing ones to
-update them. Server use cookies to "track" users and to keep "sessions".
-
-Cookies are sent from server to clients with the header Set-Cookie: and
-they are sent from clients to servers with the Cookie: header.
-
-To just send whatever cookie you want to a server, you can use
-\fICURLOPT_COOKIE(3)\fP to set a cookie string like this:
-.nf
- curl_easy_setopt(handle, CURLOPT_COOKIE, "name1=var1; name2=var2;");
-.fi
-In many cases, that is not enough. You might want to dynamically save
-whatever cookies the remote server passes to you, and make sure those cookies
-are then used accordingly on later requests.
-
-One way to do this, is to save all headers you receive in a plain file and
-when you make a request, you tell libcurl to read the previous headers to
-figure out which cookies to use. Set the header file to read cookies from with
-\fICURLOPT_COOKIEFILE(3)\fP.
-
-The \fICURLOPT_COOKIEFILE(3)\fP option also automatically enables the cookie
-parser in libcurl. Until the cookie parser is enabled, libcurl does not parse
-or understand incoming cookies and they are just be ignored. However, when the
-parser is enabled the cookies are understood and the cookies are kept in
-memory and used properly in subsequent requests when the same handle is
-used. Many times this is enough, and you may not have to save the cookies to
-disk at all. Note that the file you specify to \fICURLOPT_COOKIEFILE(3)\fP
-does not have to exist to enable the parser, so a common way to just enable
-the parser and not read any cookies is to use the name of a file you know does
-not exist.
-
-If you would rather use existing cookies that you have previously received
-with your Netscape or Mozilla browsers, you can make libcurl use that cookie
-file as input. The \fICURLOPT_COOKIEFILE(3)\fP is used for that too, as
-libcurl automatically finds out what kind of file it is and acts accordingly.
-
-Perhaps the most advanced cookie operation libcurl offers, is saving the
-entire internal cookie state back into a Netscape/Mozilla formatted cookie
-file. We call that the cookie-jar. When you set a file name with
-\fICURLOPT_COOKIEJAR(3)\fP, that file name is created and all received cookies
-get stored in it when \fIcurl_easy_cleanup(3)\fP is called. This enables
-cookies to get passed on properly between multiple handles without any
-information getting lost.
-
-.SH "FTP Peculiarities We Need"
-
-FTP transfers use a second TCP/IP connection for the data transfer. This is
-usually a fact you can forget and ignore but at times this detail comes back
-to haunt you. libcurl offers several different ways to customize how the
-second connection is being made.
-
-libcurl can either connect to the server a second time or tell the server to
-connect back to it. The first option is the default and it is also what works
-best for all the people behind firewalls, NATs or IP-masquerading setups.
-libcurl then tells the server to open up a new port and wait for a second
-connection. This is by default attempted with EPSV first, and if that does not
-work it tries PASV instead. (EPSV is an extension to the original FTP spec
-and does not exist nor work on all FTP servers.)
-
-You can prevent libcurl from first trying the EPSV command by setting
-\fICURLOPT_FTP_USE_EPSV(3)\fP to zero.
-
-In some cases, you want to have the server connect back to you for the second
-connection. This might be when the server is perhaps behind a firewall or
-something and only allows connections on a single port. libcurl then informs
-the remote server which IP address and port number to connect to. This is
-made with the \fICURLOPT_FTPPORT(3)\fP option. If you set it to "-", libcurl
-uses your system's "default IP address". If you want to use a particular IP,
-you can set the full IP address, a host name to resolve to an IP address or
-even a local network interface name that libcurl gets the IP address from.
-
-When doing the "PORT" approach, libcurl attempts to use the EPRT and the LPRT
-before trying PORT, as they work with more protocols. You can disable this
-behavior by setting \fICURLOPT_FTP_USE_EPRT(3)\fP to zero.
-
-.SH "MIME API revisited for SMTP and IMAP"
-In addition to support HTTP multi-part form fields, the MIME API can be used
-to build structured email messages and send them via SMTP or append such
-messages to IMAP directories.
-
-A structured email message may contain several parts: some are displayed
-inline by the MUA, some are attachments. Parts can also be structured as
-multi-part, for example to include another email message or to offer several
-text formats alternatives. This can be nested to any level.
-
-To build such a message, you prepare the nth-level multi-part and then include
-it as a source to the parent multi-part using function
-\fIcurl_mime_subparts(3)\fP. Once it has been
-bound to its parent multi-part, a nth-level multi-part belongs to it and
-should not be freed explicitly.
-
-Email messages data is not supposed to be non-ascii and line length is
-limited: fortunately, some transfer encodings are defined by the standards to
-support the transmission of such incompatible data. Function
-\fIcurl_mime_encoder(3)\fP tells a part that its source data must be encoded
-before being sent. It also generates the corresponding header for that part.
-If the part data you want to send is already encoded in such a scheme, do not
-use this function (this would over-encode it), but explicitly set the
-corresponding part header.
-
-Upon sending such a message, libcurl prepends it with the header list
-set with \fICURLOPT_HTTPHEADER(3)\fP, as zero level mime part headers.
-
-Here is an example building an email message with an inline plain/html text
-alternative and a file attachment encoded in base64:
-
-.nf
- curl_mime *message = curl_mime_init(handle);
-
- /* The inline part is an alternative proposing the html and the text
- versions of the email. */
- curl_mime *alt = curl_mime_init(handle);
-
- /* HTML message. */
- curl_mimepart *part = curl_mime_addpart(alt);
- curl_mime_data(part, "<html><body><p>This is HTML</p></body></html>",
- CURL_ZERO_TERMINATED);
- curl_mime_type(part, "text/html");
-
- /* Text message. */
- part = curl_mime_addpart(alt);
- curl_mime_data(part, "This is plain text message",
- CURL_ZERO_TERMINATED);
-
- /* Create the inline part. */
- part = curl_mime_addpart(message);
- curl_mime_subparts(part, alt);
- curl_mime_type(part, "multipart/alternative");
- struct curl_slist *headers = curl_slist_append(NULL,
- "Content-Disposition: inline");
- curl_mime_headers(part, headers, TRUE);
-
- /* Add the attachment. */
- part = curl_mime_addpart(message);
- curl_mime_filedata(part, "manual.pdf");
- curl_mime_encoder(part, "base64");
-
- /* Build the mail headers. */
- headers = curl_slist_append(NULL, "From: me@example.com");
- headers = curl_slist_append(headers, "To: you@example.com");
-
- /* Set these into the easy handle. */
- curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
- curl_easy_setopt(handle, CURLOPT_MIMEPOST, mime);
-.fi
-
-It should be noted that appending a message to an IMAP directory requires
-the message size to be known prior upload. It is therefore not possible to
-include parts with unknown data size in this context.
-
-.SH "Headers Equal Fun"
-
-Some protocols provide "headers", meta-data separated from the normal
-data. These headers are by default not included in the normal data stream, but
-you can make them appear in the data stream by setting \fICURLOPT_HEADER(3)\fP
-to 1.
-
-What might be even more useful, is libcurl's ability to separate the headers
-from the data and thus make the callbacks differ. You can for example set a
-different pointer to pass to the ordinary write callback by setting
-\fICURLOPT_HEADERDATA(3)\fP.
-
-Or, you can set an entirely separate function to receive the headers, by using
-\fICURLOPT_HEADERFUNCTION(3)\fP.
-
-The headers are passed to the callback function one by one, and you can
-depend on that fact. It makes it easier for you to add custom header parsers
-etc.
-
-\&"Headers" for FTP transfers equal all the FTP server responses. They are not
-actually true headers, but in this case we pretend they are! ;-)
-
-.SH "Post Transfer Information"
-See \fIcurl_easy_getinfo(3)\fP.
-.SH "The multi Interface"
-The easy interface as described in detail in this document is a synchronous
-interface that transfers one file at a time and does not return until it is
-done.
-
-The multi interface, on the other hand, allows your program to transfer
-multiple files in both directions at the same time, without forcing you to use
-multiple threads. The name might make it seem that the multi interface is for
-multi-threaded programs, but the truth is almost the reverse. The multi
-interface allows a single-threaded application to perform the same kinds of
-multiple, simultaneous transfers that multi-threaded programs can perform. It
-allows many of the benefits of multi-threaded transfers without the complexity
-of managing and synchronizing many threads.
-
-To complicate matters somewhat more, there are even two versions of the multi
-interface. The event based one, also called multi_socket and the "normal one"
-designed for using with select(). See the libcurl-multi.3 man page for details
-on the multi_socket event based API, this description here is for the select()
-oriented one.
-
-To use this interface, you are better off if you first understand the basics
-of how to use the easy interface. The multi interface is simply a way to make
-multiple transfers at the same time by adding up multiple easy handles into
-a "multi stack".
-
-You create the easy handles you want, one for each concurrent transfer, and
-you set all the options just like you learned above, and then you create a
-multi handle with \fIcurl_multi_init(3)\fP and add all those easy handles to
-that multi handle with \fIcurl_multi_add_handle(3)\fP.
-
-When you have added the handles you have for the moment (you can still add new
-ones at any time), you start the transfers by calling
-\fIcurl_multi_perform(3)\fP.
-
-\fIcurl_multi_perform(3)\fP is asynchronous. It only performs what can be done
-now and then return control to your program. It is designed to never
-block. You need to keep calling the function until all transfers are
-completed.
-
-The best usage of this interface is when you do a select() on all possible
-file descriptors or sockets to know when to call libcurl again. This also
-makes it easy for you to wait and respond to actions on your own application's
-sockets/handles. You figure out what to select() for by using
-\fIcurl_multi_fdset(3)\fP, that fills in a set of \fIfd_set\fP variables for
-you with the particular file descriptors libcurl uses for the moment.
-
-When you then call select(), it returns when one of the file handles signal
-action and you then call \fIcurl_multi_perform(3)\fP to allow libcurl to do
-what it wants to do. Take note that libcurl does also feature some time-out
-code so we advise you to never use long timeouts on select() before you call
-\fIcurl_multi_perform(3)\fP again. \fIcurl_multi_timeout(3)\fP is provided to
-help you get a suitable timeout period.
-
-Another precaution you should use: always call \fIcurl_multi_fdset(3)\fP
-immediately before the select() call since the current set of file descriptors
-may change in any curl function invoke.
-
-If you want to stop the transfer of one of the easy handles in the stack, you
-can use \fIcurl_multi_remove_handle(3)\fP to remove individual easy
-handles. Remember that easy handles should be \fIcurl_easy_cleanup(3)\fPed.
-
-When a transfer within the multi stack has finished, the counter of running
-transfers (as filled in by \fIcurl_multi_perform(3)\fP) decreases. When the
-number reaches zero, all transfers are done.
-
-\fIcurl_multi_info_read(3)\fP can be used to get information about completed
-transfers. It then returns the CURLcode for each easy transfer, to allow you
-to figure out success on each individual transfer.
-
-.SH "SSL, Certificates and Other Tricks"
-
- [ seeding, passwords, keys, certificates, ENGINE, ca certs ]
-
-.SH "Sharing Data Between Easy Handles"
-You can share some data between easy handles when the easy interface is used,
-and some data is share automatically when you use the multi interface.
-
-When you add easy handles to a multi handle, these easy handles automatically
-share a lot of the data that otherwise would be kept on a per-easy handle
-basis when the easy interface is used.
-
-The DNS cache is shared between handles within a multi handle, making
-subsequent name resolving faster, and the connection pool that is kept to
-better allow persistent connections and connection reuse is also shared. If
-you are using the easy interface, you can still share these between specific
-easy handles by using the share interface, see \fIlibcurl-share(3)\fP.
-
-Some things are never shared automatically, not within multi handles, like for
-example cookies so the only way to share that is with the share interface.
-.SH "Footnotes"
-
-.IP "[1]"
-libcurl 7.10.3 and later have the ability to switch over to chunked
-Transfer-Encoding in cases where HTTP uploads are done with data of an unknown
-size.
-.IP "[2]"
-This happens on Windows machines when libcurl is built and used as a
-DLL. However, you can still do this on Windows if you link with a static
-library.
-.IP "[3]"
-The curl-config tool is generated at build-time (on Unix-like systems) and
-should be installed with the 'make install' or similar instruction that
-installs the library, header files, man pages etc.
-.IP "[4]"
-This behavior was different in versions before 7.17.0, where strings had to
-remain valid past the end of the \fIcurl_easy_setopt(3)\fP call.
-.SH "SEE ALSO"
-.BR libcurl-easy (3),
-.BR libcurl-errors (3),
-.BR libcurl-multi (3),
-.BR libcurl-url (3)
diff --git a/docs/libcurl/libcurl-tutorial.md b/docs/libcurl/libcurl-tutorial.md
new file mode 100644
index 000000000..2bf5f0547
--- /dev/null
+++ b/docs/libcurl/libcurl-tutorial.md
@@ -0,0 +1,1451 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-tutorial
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl-easy (3)
+ - libcurl-errors (3)
+ - libcurl-multi (3)
+ - libcurl-url (3)
+---
+
+# NAME
+
+libcurl-tutorial - libcurl programming tutorial
+
+# Objective
+
+This document attempts to describe the general principles and some basic
+approaches to consider when programming with libcurl. The text focuses on the
+C interface but should apply fairly well on other language bindings as well as
+they usually follow the C API pretty closely.
+
+This document refers to 'the user' as the person writing the source code that
+uses libcurl. That would probably be you or someone in your position. What is
+generally referred to as 'the program' is the collected source code that you
+write that is using libcurl for transfers. The program is outside libcurl and
+libcurl is outside of the program.
+
+To get more details on all options and functions described herein, please
+refer to their respective man pages.
+
+# Building
+
+There are many different ways to build C programs. This chapter assumes a Unix
+style build process. If you use a different build system, you can still read
+this to get general information that may apply to your environment as well.
+
+## Compiling the Program
+
+Your compiler needs to know where the libcurl headers are located. Therefore
+you must set your compiler's include path to point to the directory where you
+installed them. The 'curl-config'[3] tool can be used to get this information:
+~~~c
+ $ curl-config --cflags
+~~~
+
+## Linking the Program with libcurl
+
+When having compiled the program, you need to link your object files to create
+a single executable. For that to succeed, you need to link with libcurl and
+possibly also with other libraries that libcurl itself depends on. Like the
+OpenSSL libraries, but even some standard OS libraries may be needed on the
+command line. To figure out which flags to use, once again the 'curl-config'
+tool comes to the rescue:
+~~~c
+ $ curl-config --libs
+~~~
+
+## SSL or Not
+
+libcurl can be built and customized in many ways. One of the things that
+varies from different libraries and builds is the support for SSL-based
+transfers, like HTTPS and FTPS. If a supported SSL library was detected
+properly at build-time, libcurl is built with SSL support. To figure out if an
+installed libcurl has been built with SSL support enabled, use *curl-config*
+like this:
+
+~~~c
+ $ curl-config --feature
+~~~
+
+If SSL is supported, the keyword *SSL* is written to stdout, possibly together
+with a other features that could be either on or off on for different
+libcurls.
+
+See also the "Features libcurl Provides" further down.
+
+## autoconf macro
+
+When you write your configure script to detect libcurl and setup variables
+accordingly, we offer a macro that probably does everything you need in this
+area. See docs/libcurl/libcurl.m4 file - it includes docs on how to use it.
+
+# Portable Code in a Portable World
+
+The people behind libcurl have put a considerable effort to make libcurl work
+on a large amount of different operating systems and environments.
+
+You program libcurl the same way on all platforms that libcurl runs on. There
+are only a few minor details that differ. If you just make sure to write your
+code portable enough, you can create a portable program. libcurl should not
+stop you from that.
+
+# Global Preparation
+
+The program must initialize some of the libcurl functionality globally. That
+means it should be done exactly once, no matter how many times you intend to
+use the library. Once for your program's entire life time. This is done using
+~~~c
+ curl_global_init()
+~~~
+and it takes one parameter which is a bit pattern that tells libcurl what to
+initialize. Using *CURL_GLOBAL_ALL* makes it initialize all known internal
+sub modules, and might be a good default option. The current two bits that are
+specified are:
+
+## CURL_GLOBAL_WIN32
+
+which only does anything on Windows machines. When used on a Windows machine,
+it makes libcurl initialize the win32 socket stuff. Without having that
+initialized properly, your program cannot use sockets properly. You should
+only do this once for each application, so if your program already does this
+or of another library in use does it, you should not tell libcurl to do this
+as well.
+
+## CURL_GLOBAL_SSL
+
+which only does anything on libcurls compiled and built SSL-enabled. On these
+systems, this makes libcurl initialize the SSL library properly for this
+application. This only needs to be done once for each application so if your
+program or another library already does this, this bit should not be needed.
+
+libcurl has a default protection mechanism that detects if
+curl_global_init(3) has not been called by the time
+curl_easy_perform(3) is called and if that is the case, libcurl runs the
+function itself with a guessed bit pattern. Please note that depending solely
+on this is not considered nice nor good.
+
+When the program no longer uses libcurl, it should call
+curl_global_cleanup(3), which is the opposite of the init call. It
+performs the reversed operations to cleanup the resources the
+curl_global_init(3) call initialized.
+
+Repeated calls to curl_global_init(3) and curl_global_cleanup(3)
+should be avoided. They should only be called once each.
+
+# Features libcurl Provides
+
+It is considered best-practice to determine libcurl features at runtime rather
+than at build-time (if possible of course). By calling
+curl_version_info(3) and checking out the details of the returned
+struct, your program can figure out exactly what the currently running libcurl
+supports.
+
+# Two Interfaces
+
+libcurl first introduced the so called easy interface. All operations in the
+easy interface are prefixed with 'curl_easy'. The easy interface lets you do
+single transfers with a synchronous and blocking function call.
+
+libcurl also offers another interface that allows multiple simultaneous
+transfers in a single thread, the so called multi interface. More about that
+interface is detailed in a separate chapter further down. You still need to
+understand the easy interface first, so please continue reading for better
+understanding.
+
+# Handle the Easy libcurl
+
+To use the easy interface, you must first create yourself an easy handle. You
+need one handle for each easy session you want to perform. Basically, you
+should use one handle for every thread you plan to use for transferring. You
+must never share the same handle in multiple threads.
+
+Get an easy handle with
+~~~c
+ handle = curl_easy_init();
+~~~
+It returns an easy handle. Using that you proceed to the next step: setting
+up your preferred actions. A handle is just a logic entity for the upcoming
+transfer or series of transfers.
+
+You set properties and options for this handle using
+curl_easy_setopt(3). They control how the subsequent transfer or
+transfers using this handle are made. Options remain set in the handle until
+set again to something different. They are sticky. Multiple requests using the
+same handle use the same options.
+
+If you at any point would like to blank all previously set options for a
+single easy handle, you can call curl_easy_reset(3) and you can also
+make a clone of an easy handle (with all its set options) using
+curl_easy_duphandle(3).
+
+Many of the options you set in libcurl are "strings", pointers to data
+terminated with a zero byte. When you set strings with
+curl_easy_setopt(3), libcurl makes its own copy so that they do not need
+to be kept around in your application after being set[4].
+
+One of the most basic properties to set in the handle is the URL. You set your
+preferred URL to transfer with CURLOPT_URL(3) in a manner similar to:
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_URL, "http://domain.com/");
+~~~
+
+Let's assume for a while that you want to receive data as the URL identifies a
+remote resource you want to get here. Since you write a sort of application
+that needs this transfer, I assume that you would like to get the data passed
+to you directly instead of simply getting it passed to stdout. So, you write
+your own function that matches this prototype:
+~~~c
+ size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
+~~~
+You tell libcurl to pass all data to this function by issuing a function
+similar to this:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_data);
+~~~
+You can control what data your callback function gets in the fourth argument
+by setting another property:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_WRITEDATA, &internal_struct);
+~~~
+Using that property, you can easily pass local data between your application
+and the function that gets invoked by libcurl. libcurl itself does not touch
+the data you pass with CURLOPT_WRITEDATA(3).
+
+libcurl offers its own default internal callback that takes care of the data
+if you do not set the callback with CURLOPT_WRITEFUNCTION(3). It simply
+outputs the received data to stdout. You can have the default callback write
+the data to a different file handle by passing a 'FILE *' to a file opened for
+writing with the CURLOPT_WRITEDATA(3) option.
+
+Now, we need to take a step back and take a deep breath. Here is one of those
+rare platform-dependent nitpicks. Did you spot it? On some platforms[2],
+libcurl is not able to operate on file handles opened by the
+program. Therefore, if you use the default callback and pass in an open file
+handle with CURLOPT_WRITEDATA(3), libcurl crashes. You should avoid this
+to make your program run fine virtually everywhere.
+
+(CURLOPT_WRITEDATA(3) was formerly known as *CURLOPT_FILE*. Both names still
+work and do the same thing).
+
+If you are using libcurl as a win32 DLL, you MUST use the
+CURLOPT_WRITEFUNCTION(3) if you set CURLOPT_WRITEDATA(3) - or experience
+crashes.
+
+There are of course many more options you can set, and we get back to a few of
+them later. Let's instead continue to the actual transfer:
+
+~~~c
+ success = curl_easy_perform(handle);
+~~~
+
+curl_easy_perform(3) connects to the remote site, does the necessary commands
+and performs the transfer. Whenever it receives data, it calls the callback
+function we previously set. The function may get one byte at a time, or it may
+get many kilobytes at once. libcurl delivers as much as possible as often as
+possible. Your callback function should return the number of bytes it "took
+care of". If that is not the same amount of bytes that was passed to it,
+libcurl aborts the operation and returns with an error code.
+
+When the transfer is complete, the function returns a return code that informs
+you if it succeeded in its mission or not. If a return code is not enough for
+you, you can use the CURLOPT_ERRORBUFFER(3) to point libcurl to a buffer of
+yours where it stores a human readable error message as well.
+
+If you then want to transfer another file, the handle is ready to be used
+again. It is even preferred and encouraged that you reuse an existing handle
+if you intend to make another transfer. libcurl then attempts to reuse a
+previous connection.
+
+For some protocols, downloading a file can involve a complicated process of
+logging in, setting the transfer mode, changing the current directory and
+finally transferring the file data. libcurl takes care of all that
+complication for you. Given simply the URL to a file, libcurl takes care of
+all the details needed to get the file moved from one machine to another.
+
+# Multi-threading Issues
+
+libcurl is thread safe but there are a few exceptions. Refer to
+libcurl-thread(3) for more information.
+
+# When It does not Work
+
+There are times when the transfer fails for some reason. You might have set
+the wrong libcurl option or misunderstood what the libcurl option actually
+does, or the remote server might return non-standard replies that confuse the
+library which then confuses your program.
+
+There is one golden rule when these things occur: set the
+CURLOPT_VERBOSE(3) option to 1. it causes the library to spew out the
+entire protocol details it sends, some internal info and some received
+protocol data as well (especially when using FTP). If you are using HTTP,
+adding the headers in the received output to study is also a clever way to get
+a better understanding why the server behaves the way it does. Include headers
+in the normal body output with CURLOPT_HEADER(3) set 1.
+
+Of course, there are bugs left. We need to know about them to be able to fix
+them, so we are quite dependent on your bug reports. When you do report
+suspected bugs in libcurl, please include as many details as you possibly can:
+a protocol dump that CURLOPT_VERBOSE(3) produces, library version, as
+much as possible of your code that uses libcurl, operating system name and
+version, compiler name and version etc.
+
+If CURLOPT_VERBOSE(3) is not enough, you increase the level of debug
+data your application receive by using the CURLOPT_DEBUGFUNCTION(3).
+
+Getting some in-depth knowledge about the protocols involved is never wrong,
+and if you are trying to do funny things, you might understand libcurl and how
+to use it better if you study the appropriate RFC documents at least briefly.
+
+# Upload Data to a Remote Site
+
+libcurl tries to keep a protocol independent approach to most transfers, thus
+uploading to a remote FTP site is similar to uploading data to an HTTP server
+with a PUT request.
+
+Of course, first you either create an easy handle or you reuse one existing
+one. Then you set the URL to operate on just like before. This is the remote
+URL, that we now upload.
+
+Since we write an application, we most likely want libcurl to get the upload
+data by asking us for it. To make it do that, we set the read callback and the
+custom pointer libcurl passes to our read callback. The read callback should
+have a prototype similar to:
+~~~c
+ size_t function(char *bufptr, size_t size, size_t nitems, void *userp);
+~~~
+Where *bufptr* is the pointer to a buffer we fill in with data to upload
+and *size*nitems* is the size of the buffer and therefore also the maximum
+amount of data we can return to libcurl in this call. The *userp* pointer
+is the custom pointer we set to point to a struct of ours to pass private data
+between the application and the callback.
+~~~c
+ curl_easy_setopt(handle, CURLOPT_READFUNCTION, read_function);
+
+ curl_easy_setopt(handle, CURLOPT_READDATA, &filedata);
+~~~
+Tell libcurl that we want to upload:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);
+~~~
+A few protocols do not behave properly when uploads are done without any prior
+knowledge of the expected file size. So, set the upload file size using the
+CURLOPT_INFILESIZE_LARGE(3) for all known file sizes like this[1]:
+
+~~~c
+ /* in this example, file_size must be an curl_off_t variable */
+ curl_easy_setopt(handle, CURLOPT_INFILESIZE_LARGE, file_size);
+~~~
+
+When you call curl_easy_perform(3) this time, it performs all the
+necessary operations and when it has invoked the upload it calls your supplied
+callback to get the data to upload. The program should return as much data as
+possible in every invoke, as that is likely to make the upload perform as fast
+as possible. The callback should return the number of bytes it wrote in the
+buffer. Returning 0 signals the end of the upload.
+
+# Passwords
+
+Many protocols use or even require that user name and password are provided
+to be able to download or upload the data of your choice. libcurl offers
+several ways to specify them.
+
+Most protocols support that you specify the name and password in the URL
+itself. libcurl detects this and use them accordingly. This is written like
+this:
+~~~c
+ protocol://user:password@example.com/path/
+~~~
+If you need any odd letters in your user name or password, you should enter
+them URL encoded, as %XX where XX is a two-digit hexadecimal number.
+
+libcurl also provides options to set various passwords. The user name and
+password as shown embedded in the URL can instead get set with the
+CURLOPT_USERPWD(3) option. The argument passed to libcurl should be a
+char * to a string in the format "user:password". In a manner like this:
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_USERPWD, "myname:thesecret");
+~~~
+
+Another case where name and password might be needed at times, is for those
+users who need to authenticate themselves to a proxy they use. libcurl offers
+another option for this, the CURLOPT_PROXYUSERPWD(3). It is used quite similar
+to the CURLOPT_USERPWD(3) option like this:
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, "myname:thesecret");
+~~~
+
+There is a long time Unix "standard" way of storing FTP user names and
+passwords, namely in the $HOME/.netrc file (on Windows, libcurl also checks
+the *%USERPROFILE% environment* variable if *%HOME%* is unset, and tries
+"_netrc" as name). The file should be made private so that only the user may
+read it (see also the "Security Considerations" chapter), as it might contain
+the password in plain text. libcurl has the ability to use this file to figure
+out what set of user name and password to use for a particular host. As an
+extension to the normal functionality, libcurl also supports this file for
+non-FTP protocols such as HTTP. To make curl use this file, use the
+CURLOPT_NETRC(3) option:
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_NETRC, 1L);
+~~~
+
+A basic example of how such a .netrc file may look like:
+
+~~~c
+ machine myhost.mydomain.com
+ login userlogin
+ password secretword
+~~~
+
+All these examples have been cases where the password has been optional, or
+at least you could leave it out and have libcurl attempt to do its job
+without it. There are times when the password is not optional, like when
+you are using an SSL private key for secure transfers.
+
+To pass the known private key password to libcurl:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_KEYPASSWD, "keypassword");
+~~~
+
+# HTTP Authentication
+
+The previous chapter showed how to set user name and password for getting URLs
+that require authentication. When using the HTTP protocol, there are many
+different ways a client can provide those credentials to the server and you
+can control which way libcurl uses them. The default HTTP authentication
+method is called 'Basic', which is sending the name and password in clear-text
+in the HTTP request, base64-encoded. This is insecure.
+
+At the time of this writing, libcurl can be built to use: Basic, Digest, NTLM,
+Negotiate (SPNEGO). You can tell libcurl which one to use with
+CURLOPT_HTTPAUTH(3) as in:
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+
+~~~
+
+When you send authentication to a proxy, you can also set authentication type
+the same way but instead with CURLOPT_PROXYAUTH(3):
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
+~~~
+
+Both these options allow you to set multiple types (by ORing them together),
+to make libcurl pick the most secure one out of the types the server/proxy
+claims to support. This method does however add a round-trip since libcurl
+must first ask the server what it supports:
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST|CURLAUTH_BASIC);
+~~~
+
+For convenience, you can use the *CURLAUTH_ANY* define (instead of a list with
+specific types) which allows libcurl to use whatever method it wants.
+
+When asking for multiple types, libcurl picks the available one it considers
+"best" in its own internal order of preference.
+
+# HTTP POSTing
+
+We get many questions regarding how to issue HTTP POSTs with libcurl the
+proper way. This chapter thus includes examples using both different versions
+of HTTP POST that libcurl supports.
+
+The first version is the simple POST, the most common version, that most HTML
+pages using the <form> tag uses. We provide a pointer to the data and tell
+libcurl to post it all to the remote site:
+
+~~~c
+ char *data="name=daniel&project=curl";
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDS, data);
+ curl_easy_setopt(handle, CURLOPT_URL, "http://posthere.com/");
+
+ curl_easy_perform(handle); /* post away! */
+~~~
+
+Simple enough, huh? Since you set the POST options with the
+CURLOPT_POSTFIELDS(3), this automatically switches the handle to use
+POST in the upcoming request.
+
+What if you want to post binary data that also requires you to set the
+Content-Type: header of the post? Well, binary posts prevent libcurl from being
+able to do strlen() on the data to figure out the size, so therefore we must
+tell libcurl the size of the post data. Setting headers in libcurl requests are
+done in a generic way, by building a list of our own headers and then passing
+that list to libcurl.
+
+~~~c
+ struct curl_slist *headers=NULL;
+ headers = curl_slist_append(headers, "Content-Type: text/xml");
+
+ /* post binary data */
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDS, binaryptr);
+
+ /* set the size of the postfields data */
+ curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, 23L);
+
+ /* pass our list of custom made headers */
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+
+ curl_easy_perform(handle); /* post away! */
+
+ curl_slist_free_all(headers); /* free the header list */
+~~~
+
+While the simple examples above cover the majority of all cases where HTTP
+POST operations are required, they do not do multi-part formposts. Multi-part
+formposts were introduced as a better way to post (possibly large) binary data
+and were first documented in the RFC 1867 (updated in RFC 2388). They are
+called multi-part because they are built by a chain of parts, each part being
+a single unit of data. Each part has its own name and contents. You can in
+fact create and post a multi-part formpost with the regular libcurl POST
+support described above, but that would require that you build a formpost
+yourself and provide to libcurl.
+
+To make that easier, libcurl provides a MIME API consisting in several
+functions: using those, you can create and fill a multi-part form. Function
+curl_mime_init(3) creates a multi-part body; you can then append new parts
+to a multi-part body using curl_mime_addpart(3).
+
+There are three possible data sources for a part: memory using
+curl_mime_data(3), file using curl_mime_filedata(3) and user-defined data
+read callback using curl_mime_data_cb(3). curl_mime_name(3) sets a part's
+(i.e.: form field) name, while curl_mime_filename(3) fills in the remote
+filename. With curl_mime_type(3), you can tell the MIME type of a part,
+curl_mime_headers(3) allows defining the part's headers. When a multi-part
+body is no longer needed, you can destroy it using curl_mime_free(3).
+
+The following example sets two simple text parts with plain textual contents,
+and then a file with binary contents and uploads the whole thing.
+
+~~~c
+ curl_mime *multipart = curl_mime_init(handle);
+ curl_mimepart *part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "name");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "project");
+ curl_mime_data(part, "curl", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_filedata(part, "curl.png");
+
+ /* Set the form info */
+ curl_easy_setopt(handle, CURLOPT_MIMEPOST, multipart);
+
+ curl_easy_perform(handle); /* post away! */
+
+ /* free the post data again */
+ curl_mime_free(multipart);
+~~~
+
+To post multiple files for a single form field, you must supply each file in
+a separate part, all with the same field name. Although function
+curl_mime_subparts(3) implements nested multi-parts, this way of
+multiple files posting is deprecated by RFC 7578, chapter 4.3.
+
+To set the data source from an already opened FILE pointer, use:
+
+~~~c
+ curl_mime_data_cb(part, filesize, (curl_read_callback) fread,
+ (curl_seek_callback) fseek, NULL, filepointer);
+~~~
+
+A deprecated curl_formadd(3) function is still supported in libcurl.
+It should however not be used anymore for new designs and programs using it
+ought to be converted to the MIME API. It is however described here as an
+aid to conversion.
+
+Using *curl_formadd*, you add parts to the form. When you are done adding
+parts, you post the whole form.
+
+The MIME API example above is expressed as follows using this function:
+
+~~~c
+ struct curl_httppost *post=NULL;
+ struct curl_httppost *last=NULL;
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "name",
+ CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "project",
+ CURLFORM_COPYCONTENTS, "curl", CURLFORM_END);
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "logotype-image",
+ CURLFORM_FILECONTENT, "curl.png", CURLFORM_END);
+
+ /* Set the form info */
+ curl_easy_setopt(handle, CURLOPT_HTTPPOST, post);
+
+ curl_easy_perform(handle); /* post away! */
+
+ /* free the post data again */
+ curl_formfree(post);
+~~~
+
+Multipart formposts are chains of parts using MIME-style separators and
+headers. It means that each one of these separate parts get a few headers set
+that describe the individual content-type, size etc. To enable your
+application to handicraft this formpost even more, libcurl allows you to
+supply your own set of custom headers to such an individual form part. You can
+of course supply headers to as many parts as you like, but this little example
+shows how you set headers to one specific part when you add that to the post
+handle:
+
+~~~c
+ struct curl_slist *headers=NULL;
+ headers = curl_slist_append(headers, "Content-Type: text/xml");
+
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "logotype-image",
+ CURLFORM_FILECONTENT, "curl.xml",
+ CURLFORM_CONTENTHEADER, headers,
+ CURLFORM_END);
+
+ curl_easy_perform(handle); /* post away! */
+
+ curl_formfree(post); /* free post */
+ curl_slist_free_all(headers); /* free custom header list */
+~~~
+
+Since all options on an easy handle are "sticky", they remain the same until
+changed even if you do call curl_easy_perform(3), you may need to tell
+curl to go back to a plain GET request if you intend to do one as your next
+request. You force an easy handle to go back to GET by using the
+CURLOPT_HTTPGET(3) option:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_HTTPGET, 1L);
+~~~
+Just setting CURLOPT_POSTFIELDS(3) to "" or NULL does *not* stop libcurl
+from doing a POST. It just makes it POST without any data to send!
+
+# Converting from deprecated form API to MIME API
+
+Four rules have to be respected in building the multi-part:
+
+- The easy handle must be created before building the multi-part.
+
+- The multi-part is always created by a call to curl_mime_init(handle).
+
+- Each part is created by a call to curl_mime_addpart(multipart).
+
+- When complete, the multi-part must be bound to the easy handle using
+CURLOPT_MIMEPOST(3) instead of CURLOPT_HTTPPOST(3).
+
+Here are some example of *curl_formadd* calls to MIME API sequences:
+
+~~~c
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "id",
+ CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
+ CURLFORM_CONTENTHEADER, headers,
+ CURLFORM_END);
+~~~
+becomes:
+~~~c
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "id");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ curl_mime_headers(part, headers, FALSE);
+~~~
+
+Setting the last curl_mime_headers(3) argument to TRUE would have caused
+the headers to be automatically released upon destroyed the multi-part, thus
+saving a clean-up call to curl_slist_free_all(3).
+
+~~~c
+ curl_formadd(&post, &last,
+ CURLFORM_PTRNAME, "logotype-image",
+ CURLFORM_FILECONTENT, "-",
+ CURLFORM_END);
+~~~
+becomes:
+~~~c
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_data_cb(part, (curl_off_t) -1, fread, fseek, NULL, stdin);
+~~~
+
+curl_mime_name(3) always copies the field name. The special file name
+"-" is not supported by curl_mime_filename(3): to read an open file, use
+a callback source using fread(). The transfer is be chunk-encoded since the
+data size is unknown.
+
+~~~c
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "datafile[]",
+ CURLFORM_FILE, "file1",
+ CURLFORM_FILE, "file2",
+ CURLFORM_END);
+~~~
+becomes:
+~~~c
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "datafile[]");
+ curl_mime_filedata(part, "file1");
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "datafile[]");
+ curl_mime_filedata(part, "file2");
+~~~
+
+The deprecated multipart/mixed implementation of multiple files field is
+translated to two distinct parts with the same name.
+
+~~~c
+ curl_easy_setopt(handle, CURLOPT_READFUNCTION, myreadfunc);
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "stream",
+ CURLFORM_STREAM, arg,
+ CURLFORM_CONTENTLEN, (curl_off_t) datasize,
+ CURLFORM_FILENAME, "archive.zip",
+ CURLFORM_CONTENTTYPE, "application/zip",
+ CURLFORM_END);
+~~~
+becomes:
+~~~c
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "stream");
+ curl_mime_data_cb(part, (curl_off_t) datasize,
+ myreadfunc, NULL, NULL, arg);
+ curl_mime_filename(part, "archive.zip");
+ curl_mime_type(part, "application/zip");
+~~~
+
+CURLOPT_READFUNCTION(3) callback is not used: it is replace by directly
+setting the part source data from the callback read function.
+
+~~~c
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "memfile",
+ CURLFORM_BUFFER, "memfile.bin",
+ CURLFORM_BUFFERPTR, databuffer,
+ CURLFORM_BUFFERLENGTH, (long) sizeof databuffer,
+ CURLFORM_END);
+~~~
+becomes:
+~~~c
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "memfile");
+ curl_mime_data(part, databuffer, (curl_off_t) sizeof databuffer);
+ curl_mime_filename(part, "memfile.bin");
+~~~
+
+curl_mime_data(3) always copies the initial data: data buffer is thus
+free for immediate reuse.
+
+~~~c
+ curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, "message",
+ CURLFORM_FILECONTENT, "msg.txt",
+ CURLFORM_END);
+~~~
+becomes:
+~~~c
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "message");
+ curl_mime_filedata(part, "msg.txt");
+ curl_mime_filename(part, NULL);
+~~~
+
+Use of curl_mime_filedata(3) sets the remote filename as a side effect: it is
+therefore necessary to clear it for *CURLFORM_FILECONTENT* emulation.
+
+# Showing Progress
+
+For historical and traditional reasons, libcurl has a built-in progress meter
+that can be switched on and then makes it present a progress meter in your
+terminal.
+
+Switch on the progress meter by, oddly enough, setting
+CURLOPT_NOPROGRESS(3) to zero. This option is set to 1 by default.
+
+For most applications however, the built-in progress meter is useless and what
+instead is interesting is the ability to specify a progress callback. The
+function pointer you pass to libcurl is then called on irregular intervals
+with information about the current transfer.
+
+Set the progress callback by using CURLOPT_PROGRESSFUNCTION(3). Pass a pointer
+to a function that matches this prototype:
+
+~~~c
+ int progress_callback(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow);
+~~~
+
+If any of the input arguments is unknown, a 0 is provided. The first argument,
+the 'clientp' is the pointer you pass to libcurl with
+CURLOPT_PROGRESSDATA(3). libcurl does not touch it.
+
+# libcurl with C++
+
+There is basically only one thing to keep in mind when using C++ instead of C
+when interfacing libcurl:
+
+The callbacks CANNOT be non-static class member functions
+
+Example C++ code:
+
+~~~c
+class AClass {
+ static size_t write_data(void *ptr, size_t size, size_t nmemb,
+ void *ourpointer)
+ {
+ /* do what you want with the data */
+ }
+ }
+~~~
+
+# Proxies
+
+What "proxy" means according to Merriam-Webster: "a person authorized to act
+for another" but also "the agency, function, or office of a deputy who acts as
+a substitute for another".
+
+Proxies are exceedingly common these days. Companies often only offer Internet
+access to employees through their proxies. Network clients or user-agents ask
+the proxy for documents, the proxy does the actual request and then it returns
+them.
+
+libcurl supports SOCKS and HTTP proxies. When a given URL is wanted, libcurl
+asks the proxy for it instead of trying to connect to the actual remote host
+identified in the URL.
+
+If you are using a SOCKS proxy, you may find that libcurl does not quite support
+all operations through it.
+
+For HTTP proxies: the fact that the proxy is an HTTP proxy puts certain
+restrictions on what can actually happen. A requested URL that might not be a
+HTTP URL is passed to the HTTP proxy to deliver back to libcurl. This happens
+transparently, and an application may not need to know. I say "may", because
+at times it is important to understand that all operations over an HTTP proxy
+use the HTTP protocol. For example, you cannot invoke your own custom FTP
+commands or even proper FTP directory listings.
+
+## Proxy Options
+
+To tell libcurl to use a proxy at a given port number:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_PROXY, "proxy-host.com:8080");
+~~~
+Some proxies require user authentication before allowing a request, and you
+pass that information similar to this:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, "user:password");
+~~~
+If you want to, you can specify the hostname only in the
+CURLOPT_PROXY(3) option, and set the port number separately with
+CURLOPT_PROXYPORT(3).
+
+Tell libcurl what kind of proxy it is with CURLOPT_PROXYTYPE(3) (if not,
+it defaults to assuming an HTTP proxy):
+~~~c
+ curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+~~~
+
+## Environment Variables
+
+libcurl automatically checks and uses a set of environment variables to know
+what proxies to use for certain protocols. The names of the variables are
+following an old tradition and are built up as "[protocol]_proxy" (note the
+lower casing). Which makes the variable 'http_proxy' checked for a name of a
+proxy to use when the input URL is HTTP. Following the same rule, the variable
+named 'ftp_proxy' is checked for FTP URLs. Again, the proxies are always HTTP
+proxies, the different names of the variables simply allows different HTTP
+proxies to be used.
+
+The proxy environment variable contents should be in the format
+"[protocol://][user:password@]machine[:port]". Where the protocol:// part
+specifies which type of proxy it is, and the optional port number specifies on
+which port the proxy operates. If not specified, the internal default port
+number is used and that is most likely not the one you would like it to be.
+
+There are two special environment variables. 'all_proxy' is what sets proxy
+for any URL in case the protocol specific variable was not set, and 'no_proxy'
+defines a list of hosts that should not use a proxy even though a variable may
+say so. If 'no_proxy' is a plain asterisk ("*") it matches all hosts.
+
+To explicitly disable libcurl's checking for and using the proxy environment
+variables, set the proxy name to "" - an empty string - with
+CURLOPT_PROXY(3).
+
+## SSL and Proxies
+
+SSL is for secure point-to-point connections. This involves strong encryption
+and similar things, which effectively makes it impossible for a proxy to
+operate as a "man in between" which the proxy's task is, as previously
+discussed. Instead, the only way to have SSL work over an HTTP proxy is to ask
+the proxy to tunnel everything through without being able to check or fiddle
+with the traffic.
+
+Opening an SSL connection over an HTTP proxy is therefore a matter of asking the
+proxy for a straight connection to the target host on a specified port. This
+is made with the HTTP request CONNECT. ("please dear proxy, connect me to that
+remote host").
+
+Because of the nature of this operation, where the proxy has no idea what kind
+of data that is passed in and out through this tunnel, this breaks some of the
+few advantages that come from using a proxy, such as caching. Many
+organizations prevent this kind of tunneling to other destination port numbers
+than 443 (which is the default HTTPS port number).
+
+## Tunneling Through Proxy
+
+As explained above, tunneling is required for SSL to work and often even
+restricted to the operation intended for SSL; HTTPS.
+
+This is however not the only time proxy-tunneling might offer benefits to
+you or your application.
+
+As tunneling opens a direct connection from your application to the remote
+machine, it suddenly also re-introduces the ability to do non-HTTP
+operations over an HTTP proxy. You can in fact use things such as FTP
+upload or FTP custom commands this way.
+
+Again, this is often prevented by the administrators of proxies and is
+rarely allowed.
+
+Tell libcurl to use proxy tunneling like this:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1L);
+~~~
+In fact, there might even be times when you want to do plain HTTP operations
+using a tunnel like this, as it then enables you to operate on the remote
+server instead of asking the proxy to do so. libcurl does not stand in the way
+for such innovative actions either!
+
+## Proxy Auto-Config
+
+Netscape first came up with this. It is basically a webpage (usually using a
+.pac extension) with a JavaScript that when executed by the browser with the
+requested URL as input, returns information to the browser on how to connect
+to the URL. The returned information might be "DIRECT" (which means no proxy
+should be used), "PROXY host:port" (to tell the browser where the proxy for
+this particular URL is) or "SOCKS host:port" (to direct the browser to a SOCKS
+proxy).
+
+libcurl has no means to interpret or evaluate JavaScript and thus it does not
+support this. If you get yourself in a position where you face this nasty
+invention, the following advice have been mentioned and used in the past:
+
+- Depending on the JavaScript complexity, write up a script that translates it
+to another language and execute that.
+
+- Read the JavaScript code and rewrite the same logic in another language.
+
+- Implement a JavaScript interpreter; people have successfully used the
+Mozilla JavaScript engine in the past.
+
+- Ask your admins to stop this, for a static proxy setup or similar.
+
+# Persistence Is The Way to Happiness
+
+Re-cycling the same easy handle several times when doing multiple requests is
+the way to go.
+
+After each single curl_easy_perform(3) operation, libcurl keeps the
+connection alive and open. A subsequent request using the same easy handle to
+the same host might just be able to use the already open connection! This
+reduces network impact a lot.
+
+Even if the connection is dropped, all connections involving SSL to the same
+host again, benefit from libcurl's session ID cache that drastically reduces
+re-connection time.
+
+FTP connections that are kept alive save a lot of time, as the command-
+response round-trips are skipped, and also you do not risk getting blocked
+without permission to login again like on many FTP servers only allowing N
+persons to be logged in at the same time.
+
+libcurl caches DNS name resolving results, to make lookups of a previously
+looked up name a lot faster.
+
+Other interesting details that improve performance for subsequent requests
+may also be added in the future.
+
+Each easy handle attempts to keep the last few connections alive for a while
+in case they are to be used again. You can set the size of this "cache" with
+the CURLOPT_MAXCONNECTS(3) option. Default is 5. There is rarely any
+point in changing this value, and if you think of changing this it is often
+just a matter of thinking again.
+
+To force your upcoming request to not use an already existing connection, you
+can do that by setting CURLOPT_FRESH_CONNECT(3) to 1. In a similar
+spirit, you can also forbid the upcoming request to be "lying" around and
+possibly get reused after the request by setting
+CURLOPT_FORBID_REUSE(3) to 1.
+
+# HTTP Headers Used by libcurl
+
+When you use libcurl to do HTTP requests, it passes along a series of headers
+automatically. It might be good for you to know and understand these. You can
+replace or remove them by using the CURLOPT_HTTPHEADER(3) option.
+
+## Host
+
+This header is required by HTTP 1.1 and even many 1.0 servers and should be
+the name of the server we want to talk to. This includes the port number if
+anything but default.
+
+## Accept
+
+"*/*"
+
+## Expect
+
+When doing POST requests, libcurl sets this header to "100-continue" to ask
+the server for an "OK" message before it proceeds with sending the data part
+of the post. If the posted data amount is deemed "small", libcurl does not use
+this header.
+
+# Customizing Operations
+
+There is an ongoing development today where more and more protocols are built
+upon HTTP for transport. This has obvious benefits as HTTP is a tested and
+reliable protocol that is widely deployed and has excellent proxy-support.
+
+When you use one of these protocols, and even when doing other kinds of
+programming you may need to change the traditional HTTP (or FTP or...)
+manners. You may need to change words, headers or various data.
+
+libcurl is your friend here too.
+
+## CUSTOMREQUEST
+
+If just changing the actual HTTP request keyword is what you want, like when
+GET, HEAD or POST is not good enough for you, CURLOPT_CUSTOMREQUEST(3)
+is there for you. It is simple to use:
+~~~c
+curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "MYOWNREQUEST");
+~~~
+When using the custom request, you change the request keyword of the actual
+request you are performing. Thus, by default you make a GET request but you
+can also make a POST operation (as described before) and then replace the POST
+keyword if you want to. You are the boss.
+
+## Modify Headers
+
+HTTP-like protocols pass a series of headers to the server when doing the
+request, and you are free to pass any amount of extra headers that you
+think fit. Adding headers is this easy:
+
+~~~c
+struct curl_slist *headers=NULL; /* init to NULL is important */
+
+headers = curl_slist_append(headers, "Hey-server-hey: how are you?");
+headers = curl_slist_append(headers, "X-silly-content: yes");
+
+/* pass our list of custom made headers */
+curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+
+curl_easy_perform(handle); /* transfer http */
+
+curl_slist_free_all(headers); /* free the header list */
+~~~
+
+... and if you think some of the internally generated headers, such as Accept:
+or Host: do not contain the data you want them to contain, you can replace
+them by simply setting them too:
+
+~~~c
+headers = curl_slist_append(headers, "Accept: Agent-007");
+headers = curl_slist_append(headers, "Host: munged.host.line");
+~~~
+
+## Delete Headers
+
+If you replace an existing header with one with no contents, you prevent the
+header from being sent. For instance, if you want to completely prevent the
+"Accept:" header from being sent, you can disable it with code similar to
+this:
+
+ headers = curl_slist_append(headers, "Accept:");
+
+Both replacing and canceling internal headers should be done with careful
+consideration and you should be aware that you may violate the HTTP protocol
+when doing so.
+
+## Enforcing chunked transfer-encoding
+
+By making sure a request uses the custom header "Transfer-Encoding: chunked"
+when doing a non-GET HTTP operation, libcurl switches over to "chunked"
+upload, even though the size of the data to upload might be known. By default,
+libcurl usually switches over to chunked upload automatically if the upload
+data size is unknown.
+
+## HTTP Version
+
+All HTTP requests includes the version number to tell the server which version
+we support. libcurl speaks HTTP 1.1 by default. Some old servers do not like
+getting 1.1-requests and when dealing with stubborn old things like that, you
+can tell libcurl to use 1.0 instead by doing something like this:
+
+ curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+
+## FTP Custom Commands
+
+Not all protocols are HTTP-like, and thus the above may not help you when
+you want to make, for example, your FTP transfers to behave differently.
+
+Sending custom commands to an FTP server means that you need to send the
+commands exactly as the FTP server expects them (RFC 959 is a good guide
+here), and you can only use commands that work on the control-connection
+alone. All kinds of commands that require data interchange and thus need a
+data-connection must be left to libcurl's own judgment. Also be aware that
+libcurl does its best to change directory to the target directory before doing
+any transfer, so if you change directory (with CWD or similar) you might
+confuse libcurl and then it might not attempt to transfer the file in the
+correct remote directory.
+
+A little example that deletes a given file before an operation:
+
+~~~c
+ headers = curl_slist_append(headers, "DELE file-to-remove");
+
+ /* pass the list of custom commands to the handle */
+ curl_easy_setopt(handle, CURLOPT_QUOTE, headers);
+
+ curl_easy_perform(handle); /* transfer ftp data! */
+
+ curl_slist_free_all(headers); /* free the header list */
+~~~
+
+If you would instead want this operation (or chain of operations) to happen
+_after_ the data transfer took place the option to curl_easy_setopt(3)
+would instead be called CURLOPT_POSTQUOTE(3) and used the exact same
+way.
+
+The custom FTP commands are issued to the server in the same order they are
+added to the list, and if a command gets an error code returned back from the
+server, no more commands are issued and libcurl bails out with an error code
+(CURLE_QUOTE_ERROR). Note that if you use CURLOPT_QUOTE(3) to send
+commands before a transfer, no transfer actually takes place when a quote
+command has failed.
+
+If you set the CURLOPT_HEADER(3) to 1, you tell libcurl to get
+information about the target file and output "headers" about it. The headers
+are in "HTTP-style", looking like they do in HTTP.
+
+The option to enable headers or to run custom FTP commands may be useful to
+combine with CURLOPT_NOBODY(3). If this option is set, no actual file
+content transfer is performed.
+
+## FTP Custom CUSTOMREQUEST
+
+If you do want to list the contents of an FTP directory using your own defined
+FTP command, CURLOPT_CUSTOMREQUEST(3) does just that. "NLST" is the
+default one for listing directories but you are free to pass in your idea of a
+good alternative.
+
+# Cookies Without Chocolate Chips
+
+In the HTTP sense, a cookie is a name with an associated value. A server sends
+the name and value to the client, and expects it to get sent back on every
+subsequent request to the server that matches the particular conditions
+set. The conditions include that the domain name and path match and that the
+cookie has not become too old.
+
+In real-world cases, servers send new cookies to replace existing ones to
+update them. Server use cookies to "track" users and to keep "sessions".
+
+Cookies are sent from server to clients with the header Set-Cookie: and
+they are sent from clients to servers with the Cookie: header.
+
+To just send whatever cookie you want to a server, you can use
+CURLOPT_COOKIE(3) to set a cookie string like this:
+~~~c
+ curl_easy_setopt(handle, CURLOPT_COOKIE, "name1=var1; name2=var2;");
+~~~
+In many cases, that is not enough. You might want to dynamically save
+whatever cookies the remote server passes to you, and make sure those cookies
+are then used accordingly on later requests.
+
+One way to do this, is to save all headers you receive in a plain file and
+when you make a request, you tell libcurl to read the previous headers to
+figure out which cookies to use. Set the header file to read cookies from with
+CURLOPT_COOKIEFILE(3).
+
+The CURLOPT_COOKIEFILE(3) option also automatically enables the cookie
+parser in libcurl. Until the cookie parser is enabled, libcurl does not parse
+or understand incoming cookies and they are just be ignored. However, when the
+parser is enabled the cookies are understood and the cookies are kept in
+memory and used properly in subsequent requests when the same handle is
+used. Many times this is enough, and you may not have to save the cookies to
+disk at all. Note that the file you specify to CURLOPT_COOKIEFILE(3)
+does not have to exist to enable the parser, so a common way to just enable
+the parser and not read any cookies is to use the name of a file you know does
+not exist.
+
+If you would rather use existing cookies that you have previously received
+with your Netscape or Mozilla browsers, you can make libcurl use that cookie
+file as input. The CURLOPT_COOKIEFILE(3) is used for that too, as
+libcurl automatically finds out what kind of file it is and acts accordingly.
+
+Perhaps the most advanced cookie operation libcurl offers, is saving the
+entire internal cookie state back into a Netscape/Mozilla formatted cookie
+file. We call that the cookie-jar. When you set a filename with
+CURLOPT_COOKIEJAR(3), that filename is created and all received cookies get
+stored in it when curl_easy_cleanup(3) is called. This enables cookies to get
+passed on properly between multiple handles without any information getting
+lost.
+
+# FTP Peculiarities We Need
+
+FTP transfers use a second TCP/IP connection for the data transfer. This is
+usually a fact you can forget and ignore but at times this detail comes back
+to haunt you. libcurl offers several different ways to customize how the
+second connection is being made.
+
+libcurl can either connect to the server a second time or tell the server to
+connect back to it. The first option is the default and it is also what works
+best for all the people behind firewalls, NATs or IP-masquerading setups.
+libcurl then tells the server to open up a new port and wait for a second
+connection. This is by default attempted with EPSV first, and if that does not
+work it tries PASV instead. (EPSV is an extension to the original FTP spec
+and does not exist nor work on all FTP servers.)
+
+You can prevent libcurl from first trying the EPSV command by setting
+CURLOPT_FTP_USE_EPSV(3) to zero.
+
+In some cases, you want to have the server connect back to you for the second
+connection. This might be when the server is perhaps behind a firewall or
+something and only allows connections on a single port. libcurl then informs
+the remote server which IP address and port number to connect to. This is made
+with the CURLOPT_FTPPORT(3) option. If you set it to "-", libcurl uses your
+system's "default IP address". If you want to use a particular IP, you can set
+the full IP address, a hostname to resolve to an IP address or even a local
+network interface name that libcurl gets the IP address from.
+
+When doing the "PORT" approach, libcurl attempts to use the EPRT and the LPRT
+before trying PORT, as they work with more protocols. You can disable this
+behavior by setting CURLOPT_FTP_USE_EPRT(3) to zero.
+
+# MIME API revisited for SMTP and IMAP
+
+In addition to support HTTP multi-part form fields, the MIME API can be used
+to build structured email messages and send them via SMTP or append such
+messages to IMAP directories.
+
+A structured email message may contain several parts: some are displayed
+inline by the MUA, some are attachments. Parts can also be structured as
+multi-part, for example to include another email message or to offer several
+text formats alternatives. This can be nested to any level.
+
+To build such a message, you prepare the nth-level multi-part and then include
+it as a source to the parent multi-part using function
+curl_mime_subparts(3). Once it has been
+bound to its parent multi-part, a nth-level multi-part belongs to it and
+should not be freed explicitly.
+
+Email messages data is not supposed to be non-ascii and line length is
+limited: fortunately, some transfer encodings are defined by the standards to
+support the transmission of such incompatible data. Function
+curl_mime_encoder(3) tells a part that its source data must be encoded
+before being sent. It also generates the corresponding header for that part.
+If the part data you want to send is already encoded in such a scheme, do not
+use this function (this would over-encode it), but explicitly set the
+corresponding part header.
+
+Upon sending such a message, libcurl prepends it with the header list
+set with CURLOPT_HTTPHEADER(3), as zero level mime part headers.
+
+Here is an example building an email message with an inline plain/html text
+alternative and a file attachment encoded in base64:
+
+~~~c
+ curl_mime *message = curl_mime_init(handle);
+
+ /* The inline part is an alternative proposing the html and the text
+ versions of the email. */
+ curl_mime *alt = curl_mime_init(handle);
+
+ /* HTML message. */
+ curl_mimepart *part = curl_mime_addpart(alt);
+ curl_mime_data(part, "<html><body><p>This is HTML</p></body></html>",
+ CURL_ZERO_TERMINATED);
+ curl_mime_type(part, "text/html");
+
+ /* Text message. */
+ part = curl_mime_addpart(alt);
+ curl_mime_data(part, "This is plain text message",
+ CURL_ZERO_TERMINATED);
+
+ /* Create the inline part. */
+ part = curl_mime_addpart(message);
+ curl_mime_subparts(part, alt);
+ curl_mime_type(part, "multipart/alternative");
+ struct curl_slist *headers = curl_slist_append(NULL,
+ "Content-Disposition: inline");
+ curl_mime_headers(part, headers, TRUE);
+
+ /* Add the attachment. */
+ part = curl_mime_addpart(message);
+ curl_mime_filedata(part, "manual.pdf");
+ curl_mime_encoder(part, "base64");
+
+ /* Build the mail headers. */
+ headers = curl_slist_append(NULL, "From: me@example.com");
+ headers = curl_slist_append(headers, "To: you@example.com");
+
+ /* Set these into the easy handle. */
+ curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(handle, CURLOPT_MIMEPOST, mime);
+~~~
+
+It should be noted that appending a message to an IMAP directory requires
+the message size to be known prior upload. It is therefore not possible to
+include parts with unknown data size in this context.
+
+# Headers Equal Fun
+
+Some protocols provide "headers", meta-data separated from the normal
+data. These headers are by default not included in the normal data stream, but
+you can make them appear in the data stream by setting CURLOPT_HEADER(3)
+to 1.
+
+What might be even more useful, is libcurl's ability to separate the headers
+from the data and thus make the callbacks differ. You can for example set a
+different pointer to pass to the ordinary write callback by setting
+CURLOPT_HEADERDATA(3).
+
+Or, you can set an entirely separate function to receive the headers, by using
+CURLOPT_HEADERFUNCTION(3).
+
+The headers are passed to the callback function one by one, and you can
+depend on that fact. It makes it easier for you to add custom header parsers
+etc.
+
+"Headers" for FTP transfers equal all the FTP server responses. They are not
+actually true headers, but in this case we pretend they are! ;-)
+
+# Post Transfer Information
+
+See curl_easy_getinfo(3).
+
+# The multi Interface
+
+The easy interface as described in detail in this document is a synchronous
+interface that transfers one file at a time and does not return until it is
+done.
+
+The multi interface, on the other hand, allows your program to transfer
+multiple files in both directions at the same time, without forcing you to use
+multiple threads. The name might make it seem that the multi interface is for
+multi-threaded programs, but the truth is almost the reverse. The multi
+interface allows a single-threaded application to perform the same kinds of
+multiple, simultaneous transfers that multi-threaded programs can perform. It
+allows many of the benefits of multi-threaded transfers without the complexity
+of managing and synchronizing many threads.
+
+To complicate matters somewhat more, there are even two versions of the multi
+interface. The event based one, also called multi_socket and the "normal one"
+designed for using with select(). See the libcurl-multi.3 man page for details
+on the multi_socket event based API, this description here is for the select()
+oriented one.
+
+To use this interface, you are better off if you first understand the basics
+of how to use the easy interface. The multi interface is simply a way to make
+multiple transfers at the same time by adding up multiple easy handles into
+a "multi stack".
+
+You create the easy handles you want, one for each concurrent transfer, and
+you set all the options just like you learned above, and then you create a
+multi handle with curl_multi_init(3) and add all those easy handles to
+that multi handle with curl_multi_add_handle(3).
+
+When you have added the handles you have for the moment (you can still add new
+ones at any time), you start the transfers by calling
+curl_multi_perform(3).
+
+curl_multi_perform(3) is asynchronous. It only performs what can be done
+now and then return control to your program. It is designed to never
+block. You need to keep calling the function until all transfers are
+completed.
+
+The best usage of this interface is when you do a select() on all possible
+file descriptors or sockets to know when to call libcurl again. This also
+makes it easy for you to wait and respond to actions on your own application's
+sockets/handles. You figure out what to select() for by using
+curl_multi_fdset(3), that fills in a set of *fd_set* variables for
+you with the particular file descriptors libcurl uses for the moment.
+
+When you then call select(), it returns when one of the file handles signal
+action and you then call curl_multi_perform(3) to allow libcurl to do
+what it wants to do. Take note that libcurl does also feature some time-out
+code so we advise you to never use long timeouts on select() before you call
+curl_multi_perform(3) again. curl_multi_timeout(3) is provided to
+help you get a suitable timeout period.
+
+Another precaution you should use: always call curl_multi_fdset(3)
+immediately before the select() call since the current set of file descriptors
+may change in any curl function invoke.
+
+If you want to stop the transfer of one of the easy handles in the stack, you
+can use curl_multi_remove_handle(3) to remove individual easy
+handles. Remember that easy handles should be curl_easy_cleanup(3)ed.
+
+When a transfer within the multi stack has finished, the counter of running
+transfers (as filled in by curl_multi_perform(3)) decreases. When the
+number reaches zero, all transfers are done.
+
+curl_multi_info_read(3) can be used to get information about completed
+transfers. It then returns the CURLcode for each easy transfer, to allow you
+to figure out success on each individual transfer.
+
+# SSL, Certificates and Other Tricks
+
+ [ seeding, passwords, keys, certificates, ENGINE, ca certs ]
+
+# Sharing Data Between Easy Handles
+
+You can share some data between easy handles when the easy interface is used,
+and some data is share automatically when you use the multi interface.
+
+When you add easy handles to a multi handle, these easy handles automatically
+share a lot of the data that otherwise would be kept on a per-easy handle
+basis when the easy interface is used.
+
+The DNS cache is shared between handles within a multi handle, making
+subsequent name resolving faster, and the connection pool that is kept to
+better allow persistent connections and connection reuse is also shared. If
+you are using the easy interface, you can still share these between specific
+easy handles by using the share interface, see libcurl-share(3).
+
+Some things are never shared automatically, not within multi handles, like for
+example cookies so the only way to share that is with the share interface.
+
+# Footnotes
+
+## [1]
+
+libcurl 7.10.3 and later have the ability to switch over to chunked
+Transfer-Encoding in cases where HTTP uploads are done with data of an unknown
+size.
+
+## [2]
+
+This happens on Windows machines when libcurl is built and used as a
+DLL. However, you can still do this on Windows if you link with a static
+library.
+
+## [3]
+
+The curl-config tool is generated at build-time (on Unix-like systems) and
+should be installed with the 'make install' or similar instruction that
+installs the library, header files, man pages etc.
+
+## [4]
+
+This behavior was different in versions before 7.17.0, where strings had to
+remain valid past the end of the curl_easy_setopt(3) call.
diff --git a/docs/libcurl/libcurl-url.3 b/docs/libcurl/libcurl-url.3
deleted file mode 100644
index fb96a1f03..000000000
--- a/docs/libcurl/libcurl-url.3
+++ /dev/null
@@ -1,151 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH libcurl 3 "10 Sep 2018" "libcurl" "libcurl"
-.SH NAME
-libcurl-url \- URL interface overview
-.SH DESCRIPTION
-The URL interface provides functions for parsing and generating URLs.
-.SH INCLUDE
-You still only include <curl/curl.h> in your code.
-.SH CREATE
-Create a handle that holds URL info and resources with \fIcurl_url(3)\fP:
-.nf
- CURLU *h = curl_url();
-.fi
-.SH CLEANUP
-When done with it, clean it up with \fIcurl_url_cleanup(3)\fP
-.nf
- curl_url_cleanup(h);
-.fi
-.SH DUPLICATE
-When you need a copy of a handle, just duplicate it with \fIcurl_url_dup(3)\fP:
-.nf
- CURLU *nh = curl_url_dup(h);
-.fi
-.SH PARSING
-By setting a URL to the handle with \fIcurl_url_set(3)\fP, the URL is parsed
-and stored in the handle. If the URL is not syntactically correct it returns
-an error instead.
-.nf
- rc = curl_url_set(h, CURLUPART_URL,
- "https://example.com:449/foo/bar?name=moo", 0);
-.fi
-
-The zero in the fourth argument is a bitmask for changing specific features.
-
-If successful, this stores the URL in its individual parts within the handle.
-.SH REDIRECT
-When a handle already contains info about a URL, setting a relative URL makes
-it "redirect" to that.
-.nf
- rc = curl_url_set(h, CURLUPART_URL, "../test?another", 0);
-.fi
-.SH "GET URL"
-The \fBCURLU\fP handle represents a URL and you can easily extract that with
-\fIcurl_url_get(3)\fP:
-.nf
- char *url;
- rc = curl_url_get(h, CURLUPART_URL, &url, 0);
- curl_free(url);
-.fi
-The zero in the fourth argument is a bitmask for changing specific features.
-.SH "GET PARTS"
-When a URL has been parsed or parts have been set, you can extract those
-pieces from the handle at any time.
-
-.nf
- rc = curl_url_get(h, CURLUPART_FRAGMENT, &fragment, 0);
- rc = curl_url_get(h, CURLUPART_HOST, &host, 0);
- rc = curl_url_get(h, CURLUPART_PASSWORD, &password, 0);
- rc = curl_url_get(h, CURLUPART_PATH, &path, 0);
- rc = curl_url_get(h, CURLUPART_PORT, &port, 0);
- rc = curl_url_get(h, CURLUPART_QUERY, &query, 0);
- rc = curl_url_get(h, CURLUPART_SCHEME, &scheme, 0);
- rc = curl_url_get(h, CURLUPART_USER, &user, 0);
- rc = curl_url_get(h, CURLUPART_ZONEID, &zoneid, 0);
-.fi
-
-Extracted parts are not URL decoded unless the user also asks for it with the
-\fICURLU_URLDECODE\fP flag set in the fourth bitmask argument.
-
-Remember to free the returned string with \fIcurl_free(3)\fP when you are done
-with it!
-.SH "SET PARTS"
-A user set individual URL parts, either after having parsed a full URL or
-instead of parsing such.
-
-.nf
- rc = curl_url_set(urlp, CURLUPART_FRAGMENT, "anchor", 0);
- rc = curl_url_set(urlp, CURLUPART_HOST, "www.example.com", 0);
- rc = curl_url_set(urlp, CURLUPART_PASSWORD, "doe", 0);
- rc = curl_url_set(urlp, CURLUPART_PATH, "/index.html", 0);
- rc = curl_url_set(urlp, CURLUPART_PORT, "443", 0);
- rc = curl_url_set(urlp, CURLUPART_QUERY, "name=john", 0);
- rc = curl_url_set(urlp, CURLUPART_SCHEME, "https", 0);
- rc = curl_url_set(urlp, CURLUPART_USER, "john", 0);
- rc = curl_url_set(urlp, CURLUPART_ZONEID, "eth0", 0);
-.fi
-
-Set parts are not URL encoded unless the user asks for it with the
-\fICURLU_URLENCODE\fP flag.
-.SH "CURLU_APPENDQUERY"
-An application can append a string to the right end of the query part with the
-\fICURLU_APPENDQUERY\fP flag to \fIcurl_url_set(3)\fP.
-
-Imagine a handle that holds the URL "https://example.com/?shoes=2". An
-application can then add the string "hat=1" to the query part like this:
-
-.nf
- rc = curl_url_set(urlp, CURLUPART_QUERY, "hat=1", CURLU_APPENDQUERY);
-.fi
-
-It notices the lack of an ampersand (&) separator and injects one, and the
-handle's full URL then equals "https://example.com/?shoes=2&hat=1".
-
-The appended string can of course also get URL encoded on add, and if asked to
-URL encode, the encoding process skips the '=' character. For example, append
-"candy=N&N" to what we already have, and URL encode it to deal with the
-ampersand in the data:
-.nf
- rc = curl_url_set(urlp, CURLUPART_QUERY, "candy=N&N",
- CURLU_APPENDQUERY | CURLU_URLENCODE);
-.fi
-
-Now the URL looks like
-.nf
- https://example.com/?shoes=2&hat=1&candy=N%26N
-.fi
-.SH AVAILABILITY
-The URL API was introduced in libcurl 7.62.0.
-
-A URL with a literal IPv6 address can be parsed even when IPv6 support is not
-enabled.
-.SH "SEE ALSO"
-.BR curl_url (3),
-.BR curl_url_cleanup (3),
-.BR curl_url_dup (3),
-.BR curl_url_get (3),
-.BR curl_url_set (3),
-.BR curl_url_strerror (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/libcurl-url.md b/docs/libcurl/libcurl-url.md
new file mode 100644
index 000000000..a2948001a
--- /dev/null
+++ b/docs/libcurl/libcurl-url.md
@@ -0,0 +1,162 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_URL (3)
+ - curl_url (3)
+ - curl_url_cleanup (3)
+ - curl_url_dup (3)
+ - curl_url_get (3)
+ - curl_url_set (3)
+ - curl_url_strerror (3)
+---
+
+# NAME
+
+libcurl-url - URL interface overview
+
+# DESCRIPTION
+
+The URL interface provides functions for parsing and generating URLs.
+
+# INCLUDE
+
+You still only include <curl/curl.h> in your code.
+
+# CREATE
+
+Create a handle that holds URL info and resources with curl_url(3):
+~~~c
+ CURLU *h = curl_url();
+~~~
+
+# CLEANUP
+
+When done with it, clean it up with curl_url_cleanup(3)
+~~~c
+ curl_url_cleanup(h);
+~~~
+
+# DUPLICATE
+
+When you need a copy of a handle, just duplicate it with curl_url_dup(3):
+~~~c
+ CURLU *nh = curl_url_dup(h);
+~~~
+
+# PARSING
+
+By setting a URL to the handle with curl_url_set(3), the URL is parsed
+and stored in the handle. If the URL is not syntactically correct it returns
+an error instead.
+~~~c
+ rc = curl_url_set(h, CURLUPART_URL,
+ "https://example.com:449/foo/bar?name=moo", 0);
+~~~
+
+The zero in the fourth argument is a bitmask for changing specific features.
+
+If successful, this stores the URL in its individual parts within the handle.
+
+# REDIRECT
+
+When a handle already contains info about a URL, setting a relative URL makes
+it "redirect" to that.
+~~~c
+ rc = curl_url_set(h, CURLUPART_URL, "../test?another", 0);
+~~~
+
+# GET URL
+
+The **CURLU** handle represents a URL and you can easily extract that with
+curl_url_get(3):
+~~~c
+ char *url;
+ rc = curl_url_get(h, CURLUPART_URL, &url, 0);
+ curl_free(url);
+~~~
+The zero in the fourth argument is a bitmask for changing specific features.
+
+# GET PARTS
+
+When a URL has been parsed or parts have been set, you can extract those
+pieces from the handle at any time.
+
+~~~c
+ rc = curl_url_get(h, CURLUPART_FRAGMENT, &fragment, 0);
+ rc = curl_url_get(h, CURLUPART_HOST, &host, 0);
+ rc = curl_url_get(h, CURLUPART_PASSWORD, &password, 0);
+ rc = curl_url_get(h, CURLUPART_PATH, &path, 0);
+ rc = curl_url_get(h, CURLUPART_PORT, &port, 0);
+ rc = curl_url_get(h, CURLUPART_QUERY, &query, 0);
+ rc = curl_url_get(h, CURLUPART_SCHEME, &scheme, 0);
+ rc = curl_url_get(h, CURLUPART_USER, &user, 0);
+ rc = curl_url_get(h, CURLUPART_ZONEID, &zoneid, 0);
+~~~
+
+Extracted parts are not URL decoded unless the user also asks for it with the
+*CURLU_URLDECODE* flag set in the fourth bitmask argument.
+
+Remember to free the returned string with curl_free(3) when you are done
+with it!
+
+# SET PARTS
+
+A user set individual URL parts, either after having parsed a full URL or
+instead of parsing such.
+
+~~~c
+ rc = curl_url_set(urlp, CURLUPART_FRAGMENT, "anchor", 0);
+ rc = curl_url_set(urlp, CURLUPART_HOST, "www.example.com", 0);
+ rc = curl_url_set(urlp, CURLUPART_PASSWORD, "doe", 0);
+ rc = curl_url_set(urlp, CURLUPART_PATH, "/index.html", 0);
+ rc = curl_url_set(urlp, CURLUPART_PORT, "443", 0);
+ rc = curl_url_set(urlp, CURLUPART_QUERY, "name=john", 0);
+ rc = curl_url_set(urlp, CURLUPART_SCHEME, "https", 0);
+ rc = curl_url_set(urlp, CURLUPART_USER, "john", 0);
+ rc = curl_url_set(urlp, CURLUPART_ZONEID, "eth0", 0);
+~~~
+
+Set parts are not URL encoded unless the user asks for it with the
+*CURLU_URLENCODE* flag.
+
+# CURLU_APPENDQUERY
+
+An application can append a string to the right end of the query part with the
+*CURLU_APPENDQUERY* flag to curl_url_set(3).
+
+Imagine a handle that holds the URL "https://example.com/?shoes=2". An
+application can then add the string "hat=1" to the query part like this:
+
+~~~c
+ rc = curl_url_set(urlp, CURLUPART_QUERY, "hat=1", CURLU_APPENDQUERY);
+~~~
+
+It notices the lack of an ampersand (&) separator and injects one, and the
+handle's full URL then equals "https://example.com/?shoes=2&hat=1".
+
+The appended string can of course also get URL encoded on add, and if asked to
+URL encode, the encoding process skips the '=' character. For example, append
+"candy=N&N" to what we already have, and URL encode it to deal with the
+ampersand in the data:
+
+~~~c
+ rc = curl_url_set(urlp, CURLUPART_QUERY, "candy=N&N",
+ CURLU_APPENDQUERY | CURLU_URLENCODE);
+~~~
+
+Now the URL looks like
+
+~~~c
+ https://example.com/?shoes=2&hat=1&candy=N%26N
+~~~
+
+# AVAILABILITY
+
+The URL API was introduced in libcurl 7.62.0.
+
+A URL with a literal IPv6 address can be parsed even when IPv6 support is not
+enabled.
diff --git a/docs/libcurl/libcurl-ws.3 b/docs/libcurl/libcurl-ws.3
deleted file mode 100644
index 2a96b8bc4..000000000
--- a/docs/libcurl/libcurl-ws.3
+++ /dev/null
@@ -1,118 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH libcurl 3 "10 Sep 2018" "libcurl" "libcurl"
-.SH NAME
-libcurl-ws \- WebSocket interface overview
-.SH DESCRIPTION
-The WebSocket interface provides functions for receiving and sending WebSocket
-data.
-.SH INCLUDE
-You still only include <curl/curl.h> in your code.
-.SH SETUP
-WebSocket is also often known as \fIWebSockets\fP, in plural. It is done by
-upgrading a regular HTTP(S) GET request to a WebSocket connection.
-
-WebSocket is a TCP-like message-based communication protocol done over HTTP,
-specified in RFC 6455.
-
-To initiate a WebSocket session with libcurl, setup an easy handle to use a
-URL with a "WS://" or "WSS://" scheme. "WS" is for cleartext communication
-over HTTP and "WSS" is for doing WebSocket securely over HTTPS.
-
-A WebSocket request is done as an HTTP/1 GET request with an "Upgrade
-WebSocket" request header field. When the upgrade is accepted by the server,
-it responds with a 101 Switching and then the client can speak WebSocket with
-the server. The communication can happen in both directions at the same time.
-.SH MESSAGES
-WebSocket communication is message based. That means that both ends send and
-receive entire messages, not streams like TCP. A WebSocket message is sent
-over the wire in one or more frames. Each frame in a message can have a size
-up to 2^63 bytes.
-
-libcurl delivers WebSocket data as frame fragments. It might send a whole
-frame, but it might also deliver them in pieces depending on size and network
-patterns. It makes sure to provide the API user about the exact specifics
-about the fragment: type, offset, size and how much data there is pending to
-arrive for the same frame.
-
-A message has an unknown size until the last frame header for the message has
-been received since only frames have set sizes.
-.SH "Raw mode"
-libcurl can be told to speak WebSocket in "raw mode" by setting the
-\fBCURLWS_RAW_MODE\fP bit to the \fICURLOPT_WS_OPTIONS(3)\fP option.
-
-Raw WebSocket means that libcurl passes on the data from the network without
-parsing it leaving that entirely to the application. This mode assumes that
-the user of this knows WebSocket and can parse and figure out the data all by
-itself.
-
-This mode is intended for applications that already have a WebSocket
-parser/engine that want to switch over to use libcurl for enabling WebSocket,
-but keep parts of the existing software architecture.
-.SH PING
-WebSocket is designed to allow long-lived sessions and in order to keep the
-connections alive, both ends can send PING messages for the other end to
-respond with a PONG.
-
-libcurl automatically responds to server PING messages with a PONG. It does
-not send any PING messages automatically.
-.SH MODELS
-Because of the many different ways WebSocket can be used, which is much more
-flexible than limited to plain downloads or uploads, libcurl offers two
-different API models to use it:
-
-1. Using a write callback with \fICURLOPT_WRITEFUNCTION(3)\fP much like other
-downloads for when the traffic is download oriented.
-
-2. Using \fICURLOPT_CONNECT_ONLY(3)\fP and use the WebSocket recv/send
-functions.
-.SH "Callback model"
-When a write callback is set and a WebSocket transfer is performed, the
-callback is called to deliver all WebSocket data that arrives.
-
-The callback can then call \fIcurl_ws_meta(3)\fP to learn about the details of
-the incoming data fragment.
-.SH "CONNECT_ONLY model"
-By setting \fICURLOPT_CONNECT_ONLY(3)\fP to \fB2L\fP, the transfer only
-establishes and setups the WebSocket communication and then returns control
-back to the application.
-
-Once such a setup has been successfully performed, the application can proceed
-and use \fIcurl_ws_recv(3)\fP and \fIcurl_ws_send(3)\fP freely to exchange
-WebSocket messages with the server.
-.SH AVAILABILITY
-The WebSocket API was introduced as experimental in 7.86.0 and is still
-experimental today.
-
-It is only built-in if explicitly opted in at build time. We discourage use of
-the WebSocket API in production because of its experimental state. We might
-change API, ABI and behavior before this "goes live".
-.SH "SEE ALSO"
-.BR curl_easy_init (3),
-.BR curl_ws_meta (3),
-.BR curl_ws_recv (3),
-.BR curl_ws_send (3),
-.BR CURLOPT_CONNECT_ONLY (3),
-.BR CURLOPT_WRITEFUNCTION (3),
-.BR CURLOPT_WS_OPTIONS (3)
diff --git a/docs/libcurl/libcurl-ws.md b/docs/libcurl/libcurl-ws.md
new file mode 100644
index 000000000..40f7c039c
--- /dev/null
+++ b/docs/libcurl/libcurl-ws.md
@@ -0,0 +1,123 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECT_ONLY (3)
+ - CURLOPT_WRITEFUNCTION (3)
+ - CURLOPT_WS_OPTIONS (3)
+ - curl_easy_init (3)
+ - curl_ws_meta (3)
+ - curl_ws_recv (3)
+ - curl_ws_send (3)
+---
+
+# NAME
+
+libcurl-ws - WebSocket interface overview
+
+# DESCRIPTION
+
+The WebSocket interface provides functions for receiving and sending WebSocket
+data.
+
+# INCLUDE
+
+You still only include <curl/curl.h> in your code.
+
+# SETUP
+
+WebSocket is also often known as *WebSockets*, in plural. It is done by
+upgrading a regular HTTP(S) GET request to a WebSocket connection.
+
+WebSocket is a TCP-like message-based communication protocol done over HTTP,
+specified in RFC 6455.
+
+To initiate a WebSocket session with libcurl, setup an easy handle to use a
+URL with a "WS://" or "WSS://" scheme. "WS" is for cleartext communication
+over HTTP and "WSS" is for doing WebSocket securely over HTTPS.
+
+A WebSocket request is done as an HTTP/1 GET request with an "Upgrade
+WebSocket" request header field. When the upgrade is accepted by the server,
+it responds with a 101 Switching and then the client can speak WebSocket with
+the server. The communication can happen in both directions at the same time.
+
+# MESSAGES
+
+WebSocket communication is message based. That means that both ends send and
+receive entire messages, not streams like TCP. A WebSocket message is sent
+over the wire in one or more frames. Each frame in a message can have a size
+up to 2^63 bytes.
+
+libcurl delivers WebSocket data as frame fragments. It might send a whole
+frame, but it might also deliver them in pieces depending on size and network
+patterns. It makes sure to provide the API user about the exact specifics
+about the fragment: type, offset, size and how much data there is pending to
+arrive for the same frame.
+
+A message has an unknown size until the last frame header for the message has
+been received since only frames have set sizes.
+
+# Raw mode
+
+libcurl can be told to speak WebSocket in "raw mode" by setting the
+**CURLWS_RAW_MODE** bit to the CURLOPT_WS_OPTIONS(3) option.
+
+Raw WebSocket means that libcurl passes on the data from the network without
+parsing it leaving that entirely to the application. This mode assumes that
+the user of this knows WebSocket and can parse and figure out the data all by
+itself.
+
+This mode is intended for applications that already have a WebSocket
+parser/engine that want to switch over to use libcurl for enabling WebSocket,
+and keep parts of the existing software architecture.
+
+# PING
+
+WebSocket is designed to allow long-lived sessions and in order to keep the
+connections alive, both ends can send PING messages for the other end to
+respond with a PONG.
+
+libcurl automatically responds to server PING messages with a PONG. It does
+not send any PING messages automatically.
+
+# MODELS
+
+Because of the many different ways WebSocket can be used, which is much more
+flexible than limited to plain downloads or uploads, libcurl offers two
+different API models to use it:
+
+1. Using a write callback with CURLOPT_WRITEFUNCTION(3) much like other
+downloads for when the traffic is download oriented.
+
+2. Using CURLOPT_CONNECT_ONLY(3) and use the WebSocket recv/send
+functions.
+
+# Callback model
+
+When a write callback is set and a WebSocket transfer is performed, the
+callback is called to deliver all WebSocket data that arrives.
+
+The callback can then call curl_ws_meta(3) to learn about the details of
+the incoming data fragment.
+
+# CONNECT_ONLY model
+
+By setting CURLOPT_CONNECT_ONLY(3) to **2L**, the transfer only
+establishes and setups the WebSocket communication and then returns control
+back to the application.
+
+Once such a setup has been successfully performed, the application can proceed
+and use curl_ws_recv(3) and curl_ws_send(3) freely to exchange
+WebSocket messages with the server.
+
+# AVAILABILITY
+
+The WebSocket API was introduced as experimental in 7.86.0 and is still
+experimental today.
+
+It is only built-in if explicitly opted in at build time. We discourage use of
+the WebSocket API in production because of its experimental state. We might
+change API, ABI and behavior before this "goes live".
diff --git a/docs/libcurl/libcurl.3 b/docs/libcurl/libcurl.3
deleted file mode 100644
index 1c1740663..000000000
--- a/docs/libcurl/libcurl.3
+++ /dev/null
@@ -1,228 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH libcurl 3 "March 19, 2002" "libcurl" "libcurl"
-.SH NAME
-libcurl \- client-side URL transfers
-.SH DESCRIPTION
-This is a short overview on how to use libcurl in your C programs. There are
-specific man pages for each function mentioned in here. See
-\fIlibcurl-easy(3)\fP, \fIlibcurl-multi(3)\fP, \fIlibcurl-share(3)\fP,
-\fIlibcurl-url(3)\fP, \fIlibcurl-ws(3)\fP and \fIlibcurl-tutorial(3)\fP for
-in-depth understanding on how to program with libcurl.
-
-There are many bindings available that bring libcurl access to your favorite
-language. Look elsewhere for documentation on those.
-.SH TRANSFERS
-To transfer files, you create an "easy handle" using \fIcurl_easy_init(3)\fP
-for a single individual transfer (in either direction). You then set your
-desired set of options in that handle with \fIcurl_easy_setopt(3)\fP. Options
-you set with \fIcurl_easy_setopt(3)\fP stick. They are then used for every
-repeated use of this handle until you either change the option, or you reset
-them all with \fIcurl_easy_reset(3)\fP.
-
-To actually transfer data you have the option of using the "easy" interface,
-or the "multi" interface.
-
-The easy interface is a synchronous interface with which you call
-\fIcurl_easy_perform(3)\fP and let it perform the transfer. When it is
-completed, the function returns and you can continue. More details are found in
-the \fIlibcurl-easy(3)\fP man page.
-
-The multi interface on the other hand is an asynchronous interface, that you
-call and that performs only a little piece of the transfer on each invoke. It
-is perfect if you want to do things while the transfer is in progress, or
-similar. The multi interface allows you to select() on libcurl action, and
-even to easily download multiple files simultaneously using a single
-thread. See further details in the \fIlibcurl-multi(3)\fP man page.
-
-.SH "SUPPORT INTERFACES"
-There is also a series of other helpful functions and interface families to
-use, including these:
-.RS
-.IP curl_version_info()
-gets detailed libcurl (and other used libraries) version info. See
-\fIcurl_version_info(3)\fP
-.IP curl_getdate()
-converts a date string to time_t. See \fIcurl_getdate(3)\fP
-.IP curl_easy_getinfo()
-get information about a performed transfer. See \fIcurl_easy_getinfo(3)\fP
-.IP curl_mime_addpart()
-helps building an HTTP form POST. See \fIcurl_mime_addpart(3)\fP
-.IP curl_slist_append()
-builds a linked list. See \fIcurl_slist_append(3)\fP
-.IP Sharing data between transfers
-You can have multiple easy handles share certain data, even if they are used
-in different threads. This magic is setup using the share interface, as
-described in the \fIlibcurl-share(3)\fP man page.
-.IP "URL Parsing"
-URL parsing and manipulations. See \fIlibcurl-url(3)\fP
-.IP "WebSocket communication"
-See \fIlibcurl-ws(3)\fP
-.RE
-
-.SH "LINKING WITH LIBCURL"
-On unix-like machines, there is a tool named curl-config that gets installed
-with the rest of the curl stuff when 'make install' is performed.
-
-curl-config is added to make it easier for applications to link with libcurl
-and developers to learn about libcurl and how to use it.
-
-Run 'curl-config --libs' to get the (additional) linker options you need to
-link with the particular version of libcurl you have installed. See the
-\fIcurl-config(1)\fP man page for further details.
-
-Unix-like operating system that ship libcurl as part of their distributions
-often do not provide the curl-config tool, but simply install the library and
-headers in the common path for this purpose.
-
-Many Linux and similar systems use pkg-config to provide build and link
-options about libraries and libcurl supports that as well.
-.SH "LIBCURL SYMBOL NAMES"
-All public functions in the libcurl interface are prefixed with 'curl_' (with
-a lowercase c). You can find other functions in the library source code, but
-other prefixes indicate that the functions are private and may change without
-further notice in the next release.
-
-Only use documented functions and functionality!
-.SH "PORTABILITY"
-libcurl works
-.B exactly
-the same, on any of the platforms it compiles and builds on.
-.SH "THREADS"
-libcurl is thread safe but there are a few exceptions. Refer to
-\fIlibcurl-thread(3)\fP for more information.
-
-.SH "PERSISTENT CONNECTIONS"
-Persistent connections means that libcurl can reuse the same connection for
-several transfers, if the conditions are right.
-
-libcurl always attempts to use persistent connections. Whenever you use
-\fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP etc, libcurl
-attempts to use an existing connection to do the transfer, and if none exists
-it opens a new one that is subject for reuse on a possible following call to
-\fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP.
-
-To allow libcurl to take full advantage of persistent connections, you should
-do as many of your file transfers as possible using the same handle.
-
-If you use the easy interface, and you call \fIcurl_easy_cleanup(3)\fP, all
-the possibly open connections held by libcurl are closed and forgotten.
-
-When you have created a multi handle and are using the multi interface, the
-connection pool is instead kept in the multi handle so closing and creating
-new easy handles to do transfers do not affect them. Instead all added easy
-handles can take advantage of the single shared pool.
-.SH "GLOBAL CONSTANTS"
-There are a variety of constants that libcurl uses, mainly through its
-internal use of other libraries, which are too complicated for the
-library loader to set up. Therefore, a program must call a library
-function after the program is loaded and running to finish setting up
-the library code. For example, when libcurl is built for SSL
-capability via the GNU TLS library, there is an elaborate tree inside
-that library that describes the SSL protocol.
-
-\fIcurl_global_init(3)\fP is the function that you must call. This may
-allocate resources (e.g. the memory for the GNU TLS tree mentioned above), so
-the companion function \fIcurl_global_cleanup(3)\fP releases them.
-
-If libcurl was compiled with support for multiple SSL backends, the function
-\fIcurl_global_sslset(3)\fP can be called before \fIcurl_global_init(3)\fP
-to select the active SSL backend.
-
-The global constant functions are thread-safe since libcurl 7.84.0 if
-\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
-(most platforms). Read \fIlibcurl-thread(3)\fP for thread safety guidelines.
-
-If the global constant functions are \fInot thread safe\fP, then you must
-not call them when any other thread in the program is running. It
-is not good enough that no other thread is using libcurl at the time,
-because these functions internally call similar functions of other
-libraries, and those functions are similarly thread-unsafe. You cannot
-generally know what these libraries are, or whether other threads are
-using them.
-
-If the global constant functions are \fInot thread safe\fP, then the basic rule
-for constructing a program that uses libcurl is this: Call
-\fIcurl_global_init(3)\fP, with a \fICURL_GLOBAL_ALL\fP argument, immediately
-after the program starts, while it is still only one thread and before it uses
-libcurl at all. Call \fIcurl_global_cleanup(3)\fP immediately before the
-program exits, when the program is again only one thread and after its last
-use of libcurl.
-
-It is not actually required that the functions be called at the beginning
-and end of the program -- that is just usually the easiest way to do it.
-
-You can call both of these multiple times, as long as all calls meet
-these requirements and the number of calls to each is the same.
-
-The global constant situation merits special consideration when the
-code you are writing to use libcurl is not the main program, but rather
-a modular piece of a program, e.g. another library. As a module,
-your code does not know about other parts of the program -- it does not
-know whether they use libcurl or not. And its code does not necessarily
-run at the start and end of the whole program.
-
-A module like this must have global constant functions of its own, just like
-\fIcurl_global_init(3)\fP and \fIcurl_global_cleanup(3)\fP. The module thus
-has control at the beginning and end of the program and has a place to call
-the libcurl functions. If multiple modules in the program use libcurl, they
-all separately call the libcurl functions, and that is OK because only the
-first \fIcurl_global_init(3)\fP and the last \fIcurl_global_cleanup(3)\fP in a
-program change anything. (libcurl uses a reference count in static memory).
-
-In a C++ module, it is common to deal with the global constant situation by
-defining a special class that represents the global constant environment of
-the module. A program always has exactly one object of the class, in static
-storage. That way, the program automatically calls the constructor of the
-object as the program starts up and the destructor as it terminates. As the
-author of this libcurl-using module, you can make the constructor call
-\fIcurl_global_init(3)\fP and the destructor call \fIcurl_global_cleanup(3)\fP
-and satisfy libcurl's requirements without your user having to think about it.
-(Caveat: If you are initializing libcurl from a Windows DLL you should not
-initialize it from \fIDllMain\fP or a static initializer because Windows holds
-the loader lock during that time and it could cause a deadlock.)
-
-\fIcurl_global_init(3)\fP has an argument that tells what particular parts of
-the global constant environment to set up. In order to successfully use any
-value except \fICURL_GLOBAL_ALL\fP (which says to set up the whole thing), you
-must have specific knowledge of internal workings of libcurl and all other
-parts of the program of which it is part.
-
-A special part of the global constant environment is the identity of the
-memory allocator. \fIcurl_global_init(3)\fP selects the system default memory
-allocator, but you can use \fIcurl_global_init_mem(3)\fP to supply one of your
-own. However, there is no way to use \fIcurl_global_init_mem(3)\fP in a
-modular program -- all modules in the program that might use libcurl would
-have to agree on one allocator.
-
-There is a failsafe in libcurl that makes it usable in simple situations
-without you having to worry about the global constant environment at all:
-\fIcurl_easy_init(3)\fP sets up the environment itself if it has not been done
-yet. The resources it acquires to do so get released by the operating system
-automatically when the program exits.
-
-This failsafe feature exists mainly for backward compatibility because there
-was a time when the global functions did not exist. Because it is sufficient
-only in the simplest of programs, it is not recommended for any program to
-rely on it.
diff --git a/docs/libcurl/libcurl.md b/docs/libcurl/libcurl.md
new file mode 100644
index 000000000..1f7c97eaa
--- /dev/null
+++ b/docs/libcurl/libcurl.md
@@ -0,0 +1,247 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl-easy (3)
+ - libcurl-multi (3)
+ - libcurl-security (3)
+ - libcurl-thread (3)
+---
+
+# NAME
+
+libcurl - client-side URL transfers
+
+# DESCRIPTION
+
+This is a short overview on how to use libcurl in your C programs. There are
+specific man pages for each function mentioned in here. See
+libcurl-easy(3), libcurl-multi(3), libcurl-share(3),
+libcurl-url(3), libcurl-ws(3) and libcurl-tutorial(3) for
+in-depth understanding on how to program with libcurl.
+
+There are many bindings available that bring libcurl access to your favorite
+language. Look elsewhere for documentation on those.
+
+# TRANSFERS
+
+To transfer files, you create an "easy handle" using curl_easy_init(3)
+for a single individual transfer (in either direction). You then set your
+desired set of options in that handle with curl_easy_setopt(3). Options
+you set with curl_easy_setopt(3) stick. They are then used for every
+repeated use of this handle until you either change the option, or you reset
+them all with curl_easy_reset(3).
+
+To actually transfer data you have the option of using the "easy" interface,
+or the "multi" interface.
+
+The easy interface is a synchronous interface with which you call
+curl_easy_perform(3) and let it perform the transfer. When it is
+completed, the function returns and you can continue. More details are found in
+the libcurl-easy(3) man page.
+
+The multi interface on the other hand is an asynchronous interface, that you
+call and that performs only a little piece of the transfer on each invoke. It
+is perfect if you want to do things while the transfer is in progress, or
+similar. The multi interface allows you to select() on libcurl action, and
+even to easily download multiple files simultaneously using a single
+thread. See further details in the libcurl-multi(3) man page.
+
+# SUPPORT INTERFACES
+
+There is also a series of other helpful functions and interface families to
+use, including these:
+
+## curl_version_info()
+
+gets detailed libcurl (and other used libraries) version info. See
+curl_version_info(3)
+
+## curl_getdate()
+
+converts a date string to time_t. See curl_getdate(3)
+
+## curl_easy_getinfo()
+
+get information about a performed transfer. See curl_easy_getinfo(3)
+
+## curl_mime_addpart()
+
+helps building an HTTP form POST. See curl_mime_addpart(3)
+
+## curl_slist_append()
+
+builds a linked list. See curl_slist_append(3)
+
+## Sharing data between transfers
+
+You can have multiple easy handles share certain data, even if they are used
+in different threads. This magic is setup using the share interface, as
+described in the libcurl-share(3) man page.
+
+## URL Parsing
+
+URL parsing and manipulations. See libcurl-url(3)
+
+## WebSocket communication
+
+See libcurl-ws(3)
+
+# LINKING WITH LIBCURL
+
+On unix-like machines, there is a tool named curl-config that gets installed
+with the rest of the curl stuff when 'make install' is performed.
+
+curl-config is added to make it easier for applications to link with libcurl
+and developers to learn about libcurl and how to use it.
+
+Run 'curl-config --libs' to get the (additional) linker options you need to
+link with the particular version of libcurl you have installed. See the
+*curl-config(1)* man page for further details.
+
+Unix-like operating system that ship libcurl as part of their distributions
+often do not provide the curl-config tool, but simply install the library and
+headers in the common path for this purpose.
+
+Many Linux and similar systems use pkg-config to provide build and link
+options about libraries and libcurl supports that as well.
+
+# LIBCURL SYMBOL NAMES
+
+All public functions in the libcurl interface are prefixed with 'curl_' (with
+a lowercase c). You can find other functions in the library source code, but
+other prefixes indicate that the functions are private and may change without
+further notice in the next release.
+
+Only use documented functions and functionality!
+
+# PORTABILITY
+
+libcurl works
+**exactly**
+the same, on any of the platforms it compiles and builds on.
+
+# THREADS
+
+libcurl is thread safe but there are a few exceptions. Refer to
+libcurl-thread(3) for more information.
+
+# PERSISTENT CONNECTIONS
+
+Persistent connections means that libcurl can reuse the same connection for
+several transfers, if the conditions are right.
+
+libcurl always attempts to use persistent connections. Whenever you use
+curl_easy_perform(3) or curl_multi_perform(3) etc, libcurl
+attempts to use an existing connection to do the transfer, and if none exists
+it opens a new one that is subject for reuse on a possible following call to
+curl_easy_perform(3) or curl_multi_perform(3).
+
+To allow libcurl to take full advantage of persistent connections, you should
+do as many of your file transfers as possible using the same handle.
+
+If you use the easy interface, and you call curl_easy_cleanup(3), all
+the possibly open connections held by libcurl are closed and forgotten.
+
+When you have created a multi handle and are using the multi interface, the
+connection pool is instead kept in the multi handle so closing and creating
+new easy handles to do transfers do not affect them. Instead all added easy
+handles can take advantage of the single shared pool.
+
+# GLOBAL CONSTANTS
+
+There are a variety of constants that libcurl uses, mainly through its
+internal use of other libraries, which are too complicated for the
+library loader to set up. Therefore, a program must call a library
+function after the program is loaded and running to finish setting up
+the library code. For example, when libcurl is built for SSL
+capability via the GNU TLS library, there is an elaborate tree inside
+that library that describes the SSL protocol.
+
+curl_global_init(3) is the function that you must call. This may
+allocate resources (e.g. the memory for the GNU TLS tree mentioned above), so
+the companion function curl_global_cleanup(3) releases them.
+
+If libcurl was compiled with support for multiple SSL backends, the function
+curl_global_sslset(3) can be called before curl_global_init(3)
+to select the active SSL backend.
+
+The global constant functions are thread-safe since libcurl 7.84.0 if
+curl_version_info(3) has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms). Read libcurl-thread(3) for thread safety guidelines.
+
+If the global constant functions are *not thread safe*, then you must
+not call them when any other thread in the program is running. It
+is not good enough that no other thread is using libcurl at the time,
+because these functions internally call similar functions of other
+libraries, and those functions are similarly thread-unsafe. You cannot
+generally know what these libraries are, or whether other threads are
+using them.
+
+If the global constant functions are *not thread safe*, then the basic rule
+for constructing a program that uses libcurl is this: Call
+curl_global_init(3), with a *CURL_GLOBAL_ALL* argument, immediately
+after the program starts, while it is still only one thread and before it uses
+libcurl at all. Call curl_global_cleanup(3) immediately before the
+program exits, when the program is again only one thread and after its last
+use of libcurl.
+
+It is not actually required that the functions be called at the beginning
+and end of the program -- that is just usually the easiest way to do it.
+
+You can call both of these multiple times, as long as all calls meet
+these requirements and the number of calls to each is the same.
+
+The global constant situation merits special consideration when the code you
+are writing to use libcurl is not the main program, but rather a modular piece
+of a program, e.g. another library. As a module, your code does not know about
+other parts of the program -- it does not know whether they use libcurl or
+not. Its code does not necessarily run at the start and end of the whole
+program.
+
+A module like this must have global constant functions of its own, just like
+curl_global_init(3) and curl_global_cleanup(3). The module thus
+has control at the beginning and end of the program and has a place to call
+the libcurl functions. If multiple modules in the program use libcurl, they
+all separately call the libcurl functions, and that is OK because only the
+first curl_global_init(3) and the last curl_global_cleanup(3) in a
+program change anything. (libcurl uses a reference count in static memory).
+
+In a C++ module, it is common to deal with the global constant situation by
+defining a special class that represents the global constant environment of
+the module. A program always has exactly one object of the class, in static
+storage. That way, the program automatically calls the constructor of the
+object as the program starts up and the destructor as it terminates. As the
+author of this libcurl-using module, you can make the constructor call
+curl_global_init(3) and the destructor call curl_global_cleanup(3)
+and satisfy libcurl's requirements without your user having to think about it.
+(Caveat: If you are initializing libcurl from a Windows DLL you should not
+initialize it from *DllMain* or a static initializer because Windows holds
+the loader lock during that time and it could cause a deadlock.)
+
+curl_global_init(3) has an argument that tells what particular parts of
+the global constant environment to set up. In order to successfully use any
+value except *CURL_GLOBAL_ALL* (which says to set up the whole thing), you
+must have specific knowledge of internal workings of libcurl and all other
+parts of the program of which it is part.
+
+A special part of the global constant environment is the identity of the
+memory allocator. curl_global_init(3) selects the system default memory
+allocator, but you can use curl_global_init_mem(3) to supply one of your
+own. However, there is no way to use curl_global_init_mem(3) in a
+modular program -- all modules in the program that might use libcurl would
+have to agree on one allocator.
+
+There is a failsafe in libcurl that makes it usable in simple situations
+without you having to worry about the global constant environment at all:
+curl_easy_init(3) sets up the environment itself if it has not been done
+yet. The resources it acquires to do so get released by the operating system
+automatically when the program exits.
+
+This failsafe feature exists mainly for backward compatibility because there
+was a time when the global functions did not exist. Because it is sufficient
+only in the simplest of programs, it is not recommended for any program to
+rely on it.
diff --git a/docs/libcurl/mksymbolsmanpage.pl b/docs/libcurl/mksymbolsmanpage.pl
index a8cb10d82..d7b9a77e3 100755
--- a/docs/libcurl/mksymbolsmanpage.pl
+++ b/docs/libcurl/mksymbolsmanpage.pl
@@ -23,40 +23,32 @@
# *
# ***************************************************************************
-my $version="7.41.0";
-
use POSIX qw(strftime);
-my $date = strftime "%b %e, %Y", localtime;
-my $year = strftime "%Y", localtime;
+my @ts;
+if (defined($ENV{SOURCE_DATE_EPOCH})) {
+ @ts = localtime($ENV{SOURCE_DATE_EPOCH});
+} else {
+ @ts = localtime;
+}
+my $date = strftime "%b %e, %Y", @ts;
+my $year = strftime "%Y", @ts;
print <<HEADER
-.\\" **************************************************************************
-.\\" * _ _ ____ _
-.\\" * Project ___| | | | _ \\| |
-.\\" * / __| | | | |_) | |
-.\\" * | (__| |_| | _ <| |___
-.\\" * \\___|\\___/|_| \\_\\_____|
-.\\" *
-.\\" * Copyright (C) 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.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.
-.\\" *
-.\\" * SPDX-License-Identifier: curl
-.\\" *
-.\\" **************************************************************************
-.TH libcurl-symbols 3 "$date" "libcurl" "libcurl"
-.SH NAME
-libcurl-symbols \\- libcurl symbol version information
-.SH "libcurl symbols"
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: libcurl-symbols
+Section: 3
+Source: libcurl
+See-also:
+ - libcurl (3)
+ - libcurl-easy (3)
+ - libcurl-multi (3)
+ - libcurl-security (3)
+ - libcurl-thread (3)
+---
+# libcurl symbols
+
This man page details version information for public symbols provided in the
libcurl header files. This lists the first version in which the symbol was
introduced and for some symbols two additional information pieces:
@@ -72,6 +64,224 @@ This man page is automatically generated from the symbols-in-versions file.
HEADER
;
+sub nameref {
+ my ($n)=@_;
+ if($n =~ /^CURLOPT_/) {
+ if($n eq "CURLOPT_RTSPHEADER") {
+ $n = "CURLOPT_HTTPHEADER";
+ }
+ elsif($n eq "CURLOPT_WRITEHEADER") {
+ $n = "CURLOPT_HEADERDATA";
+ }
+ elsif($n eq "CURLOPT_WRITEINFO") {
+ ; # now obsolete
+ }
+ else {
+ return "$n(3)";
+ }
+ }
+ elsif($n =~ /^CURLMOPT_/) {
+ return "$n(3)";
+ }
+ elsif($n =~ /^CURLINFO_/) {
+ my %infotypes = (
+ 'CURLINFO_TEXT' => 1,
+ 'CURLINFO_HEADER_IN' => 1,
+ 'CURLINFO_HEADER_OUT' => 1,
+ 'CURLINFO_DATA_IN' => 1,
+ 'CURLINFO_DATA_OUT' => 1,
+ 'CURLINFO_SSL_DATA_IN' => 1,
+ 'CURLINFO_SSL_DATA_OUT' => 1,
+ );
+ if($infotypes{$n}) {
+ return "CURLOPT_DEBUGFUNCTION(3)";
+ }
+ }
+ elsif($n =~ /^CURLALTSVC_/) {
+ return "CURLOPT_ALTSVC_CTRL(3)";
+ }
+ elsif($n =~ /^CURLAUTH_/) {
+ return "CURLOPT_HTTPAUTH(3)";
+ }
+ elsif($n =~ /^CURLFORM_/) {
+ return "curl_formadd(3)";
+ }
+ elsif($n =~ /^CURLKH/) {
+ return "CURLOPT_SSH_KEYFUNCTION(3)";
+ }
+ elsif($n =~ /^CURLE_/) {
+ return "libcurl-errors(3)";
+ }
+ elsif($n =~ /^CURLM_/) {
+ return "libcurl-errors(3)";
+ }
+ elsif($n =~ /^CURLUE_/) {
+ return "libcurl-errors(3)";
+ }
+ elsif($n =~ /^CURLHE_/) {
+ return "libcurl-errors(3)";
+ }
+ elsif($n =~ /^CURLSHE_/) {
+ return "libcurl-errors(3)";
+ }
+ elsif($n =~ /^CURLPROTO_/) {
+ return "CURLINFO_PROTOCOL(3)";
+ }
+ elsif($n =~ /^CURLPX_/) {
+ return "CURLINFO_PROXY_ERROR(3)";
+ }
+ elsif($n =~ /^CURLPROXY_/) {
+ return "CURLOPT_PROXYTYPE(3)";
+ }
+ elsif($n =~ /^CURLSSLBACKEND_/) {
+ return "curl_global_sslset(3)";
+ }
+ elsif($n =~ /^CURLSSLOPT_/) {
+ return "CURLOPT_SSL_OPTIONS(3)";
+ }
+ elsif($n =~ /^CURLSSLSET_/) {
+ return "curl_global_sslset(3)";
+ }
+ elsif($n =~ /^CURLUPART_/) {
+ return "curl_url_get(3)";
+ }
+ elsif($n =~ /^CURLU_/) {
+ return "curl_url_get(3)";
+ }
+ elsif($n =~ /^CURLVERSION_/) {
+ return "curl_version_info(3)";
+ }
+ elsif($n =~ /^CURLSHOPT_/) {
+ if($n eq "CURLSHOPT_NONE") {
+ $n = "curl_share_setopt";
+ }
+ return "$n(3)";
+ }
+ elsif($n =~ /^CURLWS_/) {
+ return "curl_ws_send(3)";
+ }
+ elsif($n =~ /^CURL_FORMADD_/) {
+ return "curl_formadd(3)";
+ }
+ elsif($n =~ /^CURL_HTTPPOST_/) {
+ return "curl_formadd(3)";
+ }
+ elsif($n =~ /^CURL_GLOBAL_/) {
+ return "curl_global_init(3)";
+ }
+ elsif($n =~ /^CURL_HTTP_VERSION_/) {
+ return "CURLOPT_HTTP_VERSION(3)";
+ }
+ elsif($n =~ /^CURL_LOCK_/) {
+ return "CURLSHOPT_SHARE(3)";
+ }
+ elsif($n =~ /^CURL_SSLVERSION_/) {
+ return "CURLOPT_SSLVERSION(3)";
+ }
+ elsif($n =~ /^CURL_VERSION_/) {
+ return "curl_version_info(3)";
+ }
+ elsif($n =~ /^CURL_RTSPREQ_/) {
+ return "CURLOPT_RTSP_REQUEST(3)";
+ }
+ elsif($n =~ /^CURLH_/) {
+ return "curl_easy_header(3)";
+ }
+ elsif($n =~ /^CURL_TRAILERFUNC_/) {
+ return "CURLOPT_TRAILERFUNCTION(3)";
+ }
+ elsif($n =~ /^CURLOT_/) {
+ return "curl_easy_option_next(3)";
+ }
+ elsif($n =~ /^CURLFINFOFLAG_/) {
+ return "CURLOPT_CHUNK_BGN_FUNCTION(3)";
+ }
+ elsif($n =~ /^CURLFILETYPE_/) {
+ return "CURLOPT_CHUNK_BGN_FUNCTION(3)";
+ }
+ elsif($n =~ /^CURL_CHUNK_BGN_FUNC_/) {
+ return "CURLOPT_CHUNK_BGN_FUNCTION(3)";
+ }
+ elsif($n =~ /^CURL_CHUNK_END_FUNC_/) {
+ return "CURLOPT_CHUNK_END_FUNCTION(3)";
+ }
+ elsif($n =~ /^CURLSSH_AUTH_/) {
+ return "CURLOPT_SSH_AUTH_TYPES(3)";
+ }
+ elsif($n =~ /^CURL_POLL_/) {
+ return "CURLMOPT_SOCKETFUNCTION(3)";
+ }
+ elsif($n =~ /^CURLMSG_/) {
+ return "curl_multi_info_read(3)";
+ }
+ elsif($n =~ /^CURLFTPAUTH_/) {
+ return "CURLOPT_FTPSSLAUTH(3)";
+ }
+ elsif($n =~ /^CURLFTPMETHOD_/) {
+ return "CURLOPT_FTP_FILEMETHOD(3)";
+ }
+ elsif($n =~ /^CURLFTPSSL_/) {
+ return "CURLOPT_USE_SSL(3)";
+ }
+ elsif($n =~ /^CURLFTP_CREATE_/) {
+ return "CURLOPT_FTP_CREATE_MISSING_DIRS(3)";
+ }
+ elsif($n =~ /^CURLGSSAPI_DELEGATION_/) {
+ return "CURLOPT_GSSAPI_DELEGATION(3)";
+ }
+ elsif($n =~ /^CURLHEADER_/) {
+ return "CURLOPT_HEADEROPT(3)";
+ }
+ elsif($n =~ /^CURLHSTS_/) {
+ return "CURLOPT_HSTS_CTRL(3)";
+ }
+ elsif($n =~ /^CURLIOCMD_/) {
+ return "CURLOPT_IOCTLFUNCTION(3)";
+ }
+ elsif($n =~ /^CURLIOE_/) {
+ return "CURLOPT_IOCTLFUNCTION(3)";
+ }
+ elsif($n =~ /^CURLMIMEOPT_/) {
+ return "CURLOPT_MIME_OPTIONS(3)";
+ }
+ elsif($n =~ /^CURLPAUSE_/) {
+ return "curl_easy_pause(3)";
+ }
+ elsif($n =~ /^CURLPIPE_/) {
+ return "CURLMOPT_PIPELINING(3)";
+ }
+ elsif($n =~ /^CURLSOCKTYPE_/) {
+ return "CURLOPT_SOCKOPTFUNCTION(3)";
+ }
+ elsif($n =~ /^CURLSTS_/) {
+ return "CURLOPT_HSTSREADFUNCTION(3)";
+ }
+ elsif($n =~ /^CURLUSESSL_/) {
+ return "CURLOPT_USE_SSL(3)";
+ }
+ elsif($n =~ /^CURL_CSELECT_/) {
+ return "curl_multi_socket_action(3)";
+ }
+ elsif($n =~ /^CURL_FNMATCHFUNC_/) {
+ return "CURLOPT_FNMATCH_FUNCTION(3)";
+ }
+ elsif($n =~ /^CURL_HET_/) {
+ return "CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS(3)";
+ }
+ elsif($n =~ /^CURL_IPRESOLVE_/) {
+ return "CURLOPT_IPRESOLVE(3)";
+ }
+ elsif($n =~ /^CURL_SEEKFUNC_/) {
+ return "CURLOPT_SEEKFUNCTION(3)";
+ }
+ elsif($n =~ /^CURL_TIMECOND_/) {
+ return "CURLOPT_TIMECONDITION(3)";
+ }
+ elsif($n =~ /^CURL_REDIR_POST_/) {
+ return "CURLOPT_POSTREDIR(3)";
+ }
+}
+
while(<STDIN>) {
if($_ =~ /^(CURL[A-Z0-9_.]*) *(.*)/i) {
my ($symbol, $rest)=($1,$2);
@@ -82,16 +292,20 @@ while(<STDIN>) {
if($rest =~ s/^([0-9.]*) *//) {
$dep = $1;
}
- if($rest =~ s/^([0-9.]*) *//) {
+ if($rest =~ s/^- *([0-9.]*)//) {
$rem = $1;
}
- print ".IP $symbol\nIntroduced in $intro\n";
+ print "\n## $symbol\nIntroduced in $intro.";
if($dep) {
- print "Deprecated since $dep\n";
+ print " Deprecated since $dep.";
}
if($rem) {
- print "Last used in $rem\n";
+ print " Last used in $rem.";
}
+ my $see = $rem || $dep ? "" : nameref($symbol);
+ if($see) {
+ print " See $see.";
+ }
+ print "\n";
}
-
}
diff --git a/docs/libcurl/opts/CMakeLists.txt b/docs/libcurl/opts/CMakeLists.txt
index 152a08a35..82844a225 100644
--- a/docs/libcurl/opts/CMakeLists.txt
+++ b/docs/libcurl/opts/CMakeLists.txt
@@ -26,10 +26,9 @@ transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
add_manual_pages(man_MANS)
-
-string(REPLACE ".3" ".html" HTMLPAGES "${man_MANS}")
-string(REPLACE ".3" ".pdf" PDFPAGES "${man_MANS}")
-add_custom_target(opts-html DEPENDS ${HTMLPAGES})
-add_custom_target(opts-pdf DEPENDS ${PDFPAGES})
-add_dependencies(html opts-html)
-add_dependencies(pdf opts-pdf)
+add_custom_target(opts-man DEPENDS ${man_MANS})
+add_dependencies(man opts-man)
+if(NOT CURL_DISABLE_INSTALL)
+ install(FILES "$<LIST:TRANSFORM,${man_MANS},PREPEND,${CMAKE_CURRENT_BINARY_DIR}/>"
+ DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
+endif()
diff --git a/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3 b/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3
deleted file mode 100644
index 0ef47f443..000000000
--- a/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_ACTIVESOCKET 3 "12 Sep 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_ACTIVESOCKET \- get the active socket
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_ACTIVESOCKET,
- curl_socket_t *socket);
-.fi
-.SH DESCRIPTION
-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.
-
-\fICURLINFO_ACTIVESOCKET(3)\fP was added as a replacement for
-\fICURLINFO_LASTSOCKET(3)\fP since that one is not working on all platforms.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_socket_t sockfd;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Do not do the transfer - only connect to host */
- curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
- res = curl_easy_perform(curl);
-
- /* Extract the socket from the curl handle */
- res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
-
- if(res != CURLE_OK) {
- printf("Error: %s\\n", curl_easy_strerror(res));
- return 1;
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.45.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_LASTSOCKET (3),
-.BR CURLOPT_CONNECT_ONLY (3)
diff --git a/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md b/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md
new file mode 100644
index 000000000..7e106ed0b
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_ACTIVESOCKET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_LASTSOCKET (3)
+ - CURLOPT_CONNECT_ONLY (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_ACTIVESOCKET - get the active socket
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_ACTIVESOCKET,
+ curl_socket_t *socket);
+~~~
+
+# DESCRIPTION
+
+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, *CURL_SOCKET_BAD* is returned. When you are finished working
+with the socket, you must call curl_easy_cleanup(3) 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
+CURLOPT_CONNECT_ONLY(3), which skips the transfer phase.
+
+CURLINFO_ACTIVESOCKET(3) was added as a replacement for
+CURLINFO_LASTSOCKET(3) since that one is not working on all platforms.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_socket_t sockfd;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Do not do the transfer - only connect to host */
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
+ res = curl_easy_perform(curl);
+
+ /* Extract the socket from the curl handle */
+ res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
+
+ if(res != CURLE_OK) {
+ printf("Error: %s\n", curl_easy_strerror(res));
+ return 1;
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.45.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3 b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3
deleted file mode 100644
index 000ad8363..000000000
--- a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_APPCONNECT_TIME 3 "28 Aug 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_APPCONNECT_TIME \- get the time until the SSL/SSH handshake is completed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME,
- double *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the time, in seconds, it took from the
-start until the SSL/SSH connect/handshake to the remote host was completed.
-This time is most often close to the \fICURLINFO_PRETRANSFER_TIME(3)\fP time,
-except for cases such as HTTP pipelining where the pretransfer time can be
-delayed due to waits in line for the pipeline and more.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- double connect;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &connect);
- if(CURLE_OK == res) {
- printf("Time: %.1f", connect);
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_APPCONNECT_TIME_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md
new file mode 100644
index 000000000..17fb46580
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_APPCONNECT_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_APPCONNECT_TIME_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_APPCONNECT_TIME - get the time until the SSL/SSH handshake is completed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME,
+ double *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the time, in seconds, it took from the
+start until the SSL/SSH connect/handshake to the remote host was completed.
+This time is most often close to the CURLINFO_PRETRANSFER_TIME(3) time,
+except for cases such as HTTP pipelining where the pretransfer time can be
+delayed due to waits in line for the pipeline and more.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ double connect;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &connect);
+ if(CURLE_OK == res) {
+ printf("Time: %.1f", connect);
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3 b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3
deleted file mode 100644
index 2a23557fb..000000000
--- a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_APPCONNECT_TIME_T 3 "28 Apr 2018" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_APPCONNECT_TIME_T \- time until the SSL/SSH handshake completed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the time, in microseconds, it took
-from the start until the SSL/SSH connect/handshake to the remote host was
-completed. This time is most often close to the
-\fICURLINFO_PRETRANSFER_TIME_T(3)\fP time, except for cases such as HTTP
-pipelining where the pretransfer time can be delayed due to waits in line for
-the pipeline and more.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_off_t connect;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME_T, &connect);
- if(CURLE_OK == res) {
- printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000,
- (long)(connect % 1000000));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_APPCONNECT_TIME (3)
diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md
new file mode 100644
index 000000000..cc4f2b858
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_APPCONNECT_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_APPCONNECT_TIME (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_APPCONNECT_TIME_T - time until the SSL/SSH handshake completed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_APPCONNECT_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the time, in microseconds, it took
+from the start until the SSL/SSH connect/handshake to the remote host was
+completed. This time is most often close to the
+CURLINFO_PRETRANSFER_TIME_T(3) time, except for cases such as HTTP
+pipelining where the pretransfer time can be delayed due to waits in line for
+the pipeline and more.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t connect;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME_T, &connect);
+ if(CURLE_OK == res) {
+ printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000,
+ (long)(connect % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CAINFO.3 b/docs/libcurl/opts/CURLINFO_CAINFO.3
deleted file mode 100644
index 1ab5113e8..000000000
--- a/docs/libcurl/opts/CURLINFO_CAINFO.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CAINFO 3 "20 May 2022" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CAINFO \- get the default built-in CA certificate path
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CAINFO, char **path);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the pointer to a null-terminated
-string holding the default built-in path used for the \fICURLOPT_CAINFO(3)\fP
-option unless set by the user.
-
-Note that in a situation where libcurl has been built to support multiple TLS
-libraries, this option might return a string even if the specific TLS library
-currently set to be used does not support \fICURLOPT_CAINFO(3)\fP.
-
-This is a path identifying a single file containing CA certificates.
-
-The \fBpath\fP pointer is set to NULL if there is no default path.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- char *cainfo = NULL;
- curl_easy_getinfo(curl, CURLINFO_CAINFO, &cainfo);
- if(cainfo)
- printf("default ca info path: %s\\n", cainfo);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.84.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CAPATH (3)
diff --git a/docs/libcurl/opts/CURLINFO_CAINFO.md b/docs/libcurl/opts/CURLINFO_CAINFO.md
new file mode 100644
index 000000000..44b253967
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CAINFO.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CAINFO
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CAPATH (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CAINFO - get the default built-in CA certificate path
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CAINFO, char **path);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a char pointer to receive the pointer to a null-terminated
+string holding the default built-in path used for the CURLOPT_CAINFO(3)
+option unless set by the user.
+
+Note that in a situation where libcurl has been built to support multiple TLS
+libraries, this option might return a string even if the specific TLS library
+currently set to be used does not support CURLOPT_CAINFO(3).
+
+This is a path identifying a single file containing CA certificates.
+
+The **path** pointer is set to NULL if there is no default path.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ char *cainfo = NULL;
+ curl_easy_getinfo(curl, CURLINFO_CAINFO, &cainfo);
+ if(cainfo) {
+ printf("default ca info path: %s\n", cainfo);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.84.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CAPATH.3 b/docs/libcurl/opts/CURLINFO_CAPATH.3
deleted file mode 100644
index d93e9fb11..000000000
--- a/docs/libcurl/opts/CURLINFO_CAPATH.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CAPATH 3 "20 May 2022" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CAPATH \- get the default built-in CA path string
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CAPATH, char **path);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the pointer to a null-terminated
-string holding the default built-in path used for the \fICURLOPT_CAPATH(3)\fP
-option unless set by the user.
-
-Note that in a situation where libcurl has been built to support multiple TLS
-libraries, this option might return a string even if the specific TLS library
-currently set to be used does not support \fICURLOPT_CAPATH(3)\fP.
-
-This is a path identifying a directory.
-
-The \fBpath\fP pointer is set to NULL if there is no default path.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- char *capath = NULL;
- curl_easy_getinfo(curl, CURLINFO_CAPATH, &capath);
- if(capath)
- printf("default ca path: %s\\n", capath);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.84.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CAINFO (3)
diff --git a/docs/libcurl/opts/CURLINFO_CAPATH.md b/docs/libcurl/opts/CURLINFO_CAPATH.md
new file mode 100644
index 000000000..46499e7f6
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CAPATH.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CAPATH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CAINFO (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CAPATH - get the default built-in CA path string
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CAPATH, char **path);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a char pointer to receive the pointer to a null-terminated
+string holding the default built-in path used for the CURLOPT_CAPATH(3)
+option unless set by the user.
+
+Note that in a situation where libcurl has been built to support multiple TLS
+libraries, this option might return a string even if the specific TLS library
+currently set to be used does not support CURLOPT_CAPATH(3).
+
+This is a path identifying a directory.
+
+The **path** pointer is set to NULL if there is no default path.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ char *capath = NULL;
+ curl_easy_getinfo(curl, CURLINFO_CAPATH, &capath);
+ if(capath) {
+ printf("default ca path: %s\n", capath);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.84.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CERTINFO.3 b/docs/libcurl/opts/CURLINFO_CERTINFO.3
deleted file mode 100644
index 277b6033f..000000000
--- a/docs/libcurl/opts/CURLINFO_CERTINFO.3
+++ /dev/null
@@ -1,100 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CERTINFO 3 "12 Sep 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CERTINFO \- get the TLS certificate chain
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CERTINFO,
- struct curl_certinfo **chainp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIstruct curl_certinfo *\fP and it is set to point to a
-struct that holds info about the server's certificate chain, assuming you had
-\fICURLOPT_CERTINFO(3)\fP enabled when the request was made.
-
-.nf
-struct curl_certinfo {
- int num_of_certs;
- struct curl_slist **certinfo;
-};
-.fi
-
-The \fIcertinfo\fP struct member is an array of linked lists of certificate
-information. The \fInum_of_certs\fP struct member is the number of
-certificates which is the number of elements in the array. Each certificate's
-list has items with textual information in the format "name:content" such as
-\&"Subject:Foo", "Issuer:Bar", etc. The items in each list varies depending on
-the SSL backend and the certificate.
-.SH PROTOCOLS
-All TLS-based
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
-
- /* connect to any HTTPS site, trusted or not */
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
-
- curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
-
- res = curl_easy_perform(curl);
-
- if (!res) {
- struct curl_certinfo *ci;
- res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci);
-
- if (!res) {
- printf("%d certs!\\n", ci->num_of_certs);
-
- for(i = 0; i < ci->num_of_certs; i++) {
- struct curl_slist *slist;
-
- for(slist = ci->certinfo[i]; slist; slist = slist->next)
- printf("%s\\n", slist->data);
- }
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-
-See also the \fIcertinfo.c\fP example.
-.SH AVAILABILITY
-This option is only working in libcurl built with OpenSSL, GnuTLS, Schannel or
-Secure Transport. GnuTLS support added in 7.42.0. Schannel support added in
-7.50.0. Secure Transport support added in 7.79.0.
-
-Added in 7.19.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CAPATH (3)
diff --git a/docs/libcurl/opts/CURLINFO_CERTINFO.md b/docs/libcurl/opts/CURLINFO_CERTINFO.md
new file mode 100644
index 000000000..d9cbc9306
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CERTINFO.md
@@ -0,0 +1,101 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CERTINFO
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CAPATH (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CERTINFO - get the TLS certificate chain
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CERTINFO,
+ struct curl_certinfo **chainp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *struct curl_certinfo ** and it is set to point to a
+struct that holds info about the server's certificate chain, assuming you had
+CURLOPT_CERTINFO(3) enabled when the request was made.
+
+~~~c
+struct curl_certinfo {
+ int num_of_certs;
+ struct curl_slist **certinfo;
+};
+~~~
+
+The *certinfo* struct member is an array of linked lists of certificate
+information. The *num_of_certs* struct member is the number of certificates
+which is the number of elements in the array. Each certificate's list has
+items with textual information in the format "name:content" such as
+"Subject:Foo", "Issuer:Bar", etc. The items in each list varies depending on
+the SSL backend and the certificate.
+
+# PROTOCOLS
+
+All TLS-based
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
+
+ /* connect to any HTTPS site, trusted or not */
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+
+ curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ int i;
+ struct curl_certinfo *ci;
+ res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci);
+
+ if(!res) {
+ printf("%d certs!\n", ci->num_of_certs);
+
+ for(i = 0; i < ci->num_of_certs; i++) {
+ struct curl_slist *slist;
+
+ for(slist = ci->certinfo[i]; slist; slist = slist->next)
+ printf("%s\n", slist->data);
+ }
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+See also the *certinfo.c* example.
+
+# AVAILABILITY
+
+This option is only working in libcurl built with OpenSSL, GnuTLS, Schannel or
+Secure Transport. GnuTLS support added in 7.42.0. Schannel support added in
+7.50.0. Secure Transport support added in 7.79.0.
+
+Added in 7.19.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3 b/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3
deleted file mode 100644
index 1d1627b3c..000000000
--- a/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONDITION_UNMET 3 "1 Sep 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONDITION_UNMET \- get info on unmet time conditional or 304 HTTP response.
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONDITION_UNMET,
- long *unmet);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the number 1 if the condition provided in
-the previous request did not match (see \fICURLOPT_TIMECONDITION(3)\fP). Alas,
-if this returns a 1 you know that the reason you did not get data in return is
-because it did not fulfill the condition. The long this argument points to
-gets a zero stored if the condition instead was met. This can also return 1 if
-the server responded with a 304 HTTP status code, for example after sending a
-custom "If-Match-*" header.
-.SH PROTOCOLS
-HTTP and some
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* January 1, 2020 is 1577833200 */
- curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
-
- /* If-Modified-Since the above time stamp */
- curl_easy_setopt(curl, CURLOPT_TIMECONDITION,
- (long)CURL_TIMECOND_IFMODSINCE);
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* check the time condition */
- long unmet;
- res = curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &unmet);
- if(!res) {
- printf("The time condition was %sfulfilled\\n", unmet?"NOT":"");
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_TIMECONDITION (3),
-.BR CURLOPT_TIMEVALUE (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md b/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md
new file mode 100644
index 000000000..aca04f1c9
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONDITION_UNMET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TIMECONDITION (3)
+ - CURLOPT_TIMEVALUE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONDITION_UNMET - get info on unmet time conditional or 304 HTTP response.
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONDITION_UNMET,
+ long *unmet);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the number 1 if the condition provided in
+the previous request did not match (see CURLOPT_TIMECONDITION(3)). Alas,
+if this returns a 1 you know that the reason you did not get data in return is
+because it did not fulfill the condition. The long this argument points to
+gets a zero stored if the condition instead was met. This can also return 1 if
+the server responded with a 304 HTTP status code, for example after sending a
+custom "If-Match-*" header.
+
+# PROTOCOLS
+
+HTTP and some
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* January 1, 2020 is 1577833200 */
+ curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
+
+ /* If-Modified-Since the above time stamp */
+ curl_easy_setopt(curl, CURLOPT_TIMECONDITION,
+ (long)CURL_TIMECOND_IFMODSINCE);
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* check the time condition */
+ long unmet;
+ res = curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &unmet);
+ if(!res) {
+ printf("The time condition was %sfulfilled\n", unmet?"NOT":"");
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3 b/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3
deleted file mode 100644
index cf0ce8a85..000000000
--- a/docs/libcurl/opts/CURLINFO_CONNECT_TIME.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONNECT_TIME 3 "28 Aug 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONNECT_TIME \- get the time until connect
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME, double *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the total time in seconds from the start
-until the connection to the remote host (or proxy) was completed.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- double connect;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &connect);
- if(CURLE_OK == res) {
- printf("Time: %.1f", connect);
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONNECT_TIME_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME.md b/docs/libcurl/opts/CURLINFO_CONNECT_TIME.md
new file mode 100644
index 000000000..1fde76699
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONNECT_TIME.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONNECT_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONNECT_TIME_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONNECT_TIME - get the time until connect
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME, double *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the total time in seconds from the start
+until the connection to the remote host (or proxy) was completed.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ double connect;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &connect);
+ if(CURLE_OK == res) {
+ printf("Time: %.1f", connect);
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3 b/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3
deleted file mode 100644
index 8641de0ac..000000000
--- a/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONNECT_TIME_T 3 "28 Apr 2018" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONNECT_TIME_T \- get the time until connect
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the total time in microseconds from
-the start until the connection to the remote host (or proxy) was completed.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_off_t connect;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME_T, &connect);
- if(CURLE_OK == res) {
- printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000,
- (long)(connect % 1000000));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONNECT_TIME (3),
-.BR CURLOPT_CONNECTTIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md b/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md
new file mode 100644
index 000000000..cd72cdd07
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONNECT_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONNECT_TIME (3)
+ - CURLOPT_CONNECTTIMEOUT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONNECT_TIME_T - get the time until connect
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONNECT_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the total time in microseconds from
+the start until the connection to the remote host (or proxy) was completed.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t connect;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME_T, &connect);
+ if(CURLE_OK == res) {
+ printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000,
+ (long)(connect % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONN_ID.3 b/docs/libcurl/opts/CURLINFO_CONN_ID.3
deleted file mode 100644
index 3a63520e0..000000000
--- a/docs/libcurl/opts/CURLINFO_CONN_ID.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONN_ID 3 "07 June 2023" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONN_ID \- get the ID of the last connection used by the handle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONN_ID,
- curl_off_t *conn_id);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the connection identifier last
-used by the handle. Stores -1 if there was no connection used.
-
-The connection id is unique among all connections using the same
-connection cache. This is implicitly the case for all connections in the
-same multi handle.
-
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- curl_off_t conn_id;
- res = curl_easy_getinfo(curl, CURLINFO_CONN_ID, &conn_id);
- if(!res) {
- printf("Connection used: %" CURL_FORMAT_CURL_OFF_T "\\n", conn_id);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 8.2.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_XFER_ID (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONN_ID.md b/docs/libcurl/opts/CURLINFO_CONN_ID.md
new file mode 100644
index 000000000..d4791b42c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONN_ID.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONN_ID
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_XFER_ID (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONN_ID - get the ID of the last connection used by the handle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONN_ID,
+ curl_off_t *conn_id);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the connection identifier last
+used by the handle. Stores -1 if there was no connection used.
+
+The connection id is unique among all connections using the same
+connection cache. This is implicitly the case for all connections in the
+same multi handle.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ curl_off_t conn_id;
+ res = curl_easy_getinfo(curl, CURLINFO_CONN_ID, &conn_id);
+ if(!res) {
+ printf("Connection used: %" CURL_FORMAT_CURL_OFF_T "\n", conn_id);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 8.2.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3
deleted file mode 100644
index 474c21af0..000000000
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD 3 "1 Sep 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONTENT_LENGTH_DOWNLOAD \- get content-length of download
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
- double *content_length);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the content-length of the download. This
-is the value read from the Content-Length: field. Since 7.19.4, this returns
--1 if the size is not known.
-
-\fICURLINFO_CONTENT_LENGTH_DOWNLOAD_T(3)\fP is a newer replacement that returns a more
-sensible variable type.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* check the size */
- double cl;
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl);
- if(!res) {
- printf("Size: %.0f\\n", cl);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.6.1. Deprecated since 7.55.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONTENT_LENGTH_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md
new file mode 100644
index 000000000..1e01419bd
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONTENT_LENGTH_DOWNLOAD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONTENT_LENGTH_UPLOAD (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONTENT_LENGTH_DOWNLOAD - get content-length of download
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ double *content_length);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the content-length of the download. This
+is the value read from the Content-Length: field. Since 7.19.4, this returns
+-1 if the size is not known.
+
+CURLINFO_CONTENT_LENGTH_DOWNLOAD_T(3) is a newer replacement that returns a more
+sensible variable type.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* check the size */
+ double cl;
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl);
+ if(!res) {
+ printf("Size: %.0f\n", cl);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.6.1. Deprecated since 7.55.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
deleted file mode 100644
index cea6ad0f6..000000000
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 3 "25 May 2017" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONTENT_LENGTH_DOWNLOAD_T \- get content-length of download
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
- curl_off_t *content_length);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the content-length of the
-download. This is the value read from the Content-Length: field. Stores -1 if
-the size is not known.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* check the size */
- curl_off_t cl;
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl);
- if(!res) {
- printf("Download size: %" CURL_FORMAT_CURL_OFF_T "\\n", cl);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONTENT_LENGTH_UPLOAD_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md
new file mode 100644
index 000000000..15016c84c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONTENT_LENGTH_DOWNLOAD_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONTENT_LENGTH_UPLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONTENT_LENGTH_DOWNLOAD_T - get content-length of download
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
+ curl_off_t *content_length);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the content-length of the
+download. This is the value read from the Content-Length: field. Stores -1 if
+the size is not known.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* check the size */
+ curl_off_t cl;
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl);
+ if(!res) {
+ printf("Download size: %" CURL_FORMAT_CURL_OFF_T "\n", cl);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3
deleted file mode 100644
index b2da1af25..000000000
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONTENT_LENGTH_UPLOAD 3 "1 Sep 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONTENT_LENGTH_UPLOAD \- get the specified size of the upload
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD,
- double *content_length);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the specified size of the upload. Since
-7.19.4, this returns -1 if the size is not known.
-
-\fICURLINFO_CONTENT_LENGTH_UPLOAD_T(3)\fP is a newer replacement that returns a
-more sensible variable type.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the upload */
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* check the size */
- double cl;
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &cl);
- if(!res) {
- printf("Size: %.0f\\n", cl);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.6.1. Deprecated since 7.55.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONTENT_LENGTH_DOWNLOAD_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md
new file mode 100644
index 000000000..c90e19e72
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONTENT_LENGTH_UPLOAD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONTENT_LENGTH_DOWNLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONTENT_LENGTH_UPLOAD - get the specified size of the upload
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD,
+ double *content_length);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the specified size of the upload. Since
+7.19.4, this returns -1 if the size is not known.
+
+CURLINFO_CONTENT_LENGTH_UPLOAD_T(3) is a newer replacement that returns a
+more sensible variable type.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the upload */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* check the size */
+ double cl;
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &cl);
+ if(!res) {
+ printf("Size: %.0f\n", cl);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.6.1. Deprecated since 7.55.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3 b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3
deleted file mode 100644
index 61a1fde5f..000000000
--- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONTENT_LENGTH_UPLOAD_T 3 "25 May 2017" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONTENT_LENGTH_UPLOAD_T \- get the specified size of the upload
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD_T,
- curl_off_t *content_length);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the specified size of the
-upload. Stores -1 if the size is not known.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the upload */
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* check the size */
- curl_off_t cl;
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD_T, &cl);
- if(!res) {
- printf("Upload size: %" CURL_FORMAT_CURL_OFF_T "\\n", cl);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONTENT_LENGTH_DOWNLOAD_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md
new file mode 100644
index 000000000..319a3345e
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONTENT_LENGTH_UPLOAD_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONTENT_LENGTH_DOWNLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONTENT_LENGTH_UPLOAD_T - get the specified size of the upload
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD_T,
+ curl_off_t *content_length);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the specified size of the
+upload. Stores -1 if the size is not known.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the upload */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* check the size */
+ curl_off_t cl;
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD_T, &cl);
+ if(!res) {
+ printf("Upload size: %" CURL_FORMAT_CURL_OFF_T "\n", cl);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3 b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3
deleted file mode 100644
index 56caea7df..000000000
--- a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_CONTENT_TYPE 3 "1 Sep 2015" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_CONTENT_TYPE \- get Content-Type
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_TYPE, char **ct);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the content-type of the downloaded
-object. This is the value read from the Content-Type: field. If you get NULL,
-it means that the server did not send a valid Content-Type header or that the
-protocol used does not support this.
-
-The \fBct\fP pointer is set to NULL or pointing to private memory. You MUST
-NOT free it - it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the
-corresponding CURL handle.
-
-The modern way to get this header from a response is to instead use the
-\fIcurl_easy_header(3)\fP function.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* extract the content-type */
- char *ct = NULL;
- res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
- if(!res && ct) {
- printf("Content-Type: %s\\n", ct);
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.9.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_header (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_HEADERFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md
new file mode 100644
index 000000000..b87457251
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_CONTENT_TYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERFUNCTION (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_header (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_CONTENT_TYPE - get Content-Type
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_TYPE, char **ct);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a char pointer to receive the content-type of the downloaded
+object. This is the value read from the Content-Type: field. If you get NULL,
+it means that the server did not send a valid Content-Type header or that the
+protocol used does not support this.
+
+The **ct** pointer is set to NULL or pointing to private memory. You MUST
+NOT free it - it gets freed when you call curl_easy_cleanup(3) on the
+corresponding CURL handle.
+
+The modern way to get this header from a response is to instead use the
+curl_easy_header(3) function.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* extract the content-type */
+ char *ct = NULL;
+ res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
+ if(!res && ct) {
+ printf("Content-Type: %s\n", ct);
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_COOKIELIST.3 b/docs/libcurl/opts/CURLINFO_COOKIELIST.3
deleted file mode 100644
index 29c8983ce..000000000
--- a/docs/libcurl/opts/CURLINFO_COOKIELIST.3
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_COOKIELIST 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_COOKIELIST \- get all known cookies
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_COOKIELIST,
- struct curl_slist **cookies);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a 'struct curl_slist *' to receive a linked-list of all
-cookies curl knows (expired ones, too). do not forget to call
-\fIcurl_slist_free_all(3)\fP on the list after it has been used. If there are
-no cookies (cookies for the handle have not been enabled or simply none have
-been received) the 'struct curl_slist *' is made a NULL pointer.
-
-Since 7.43.0 cookies that were imported in the Set-Cookie format without a
-domain name are not exported by this option.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* enable the cookie engine */
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
-
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* extract all known cookies */
- struct curl_slist *cookies = NULL;
- res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
- if(!res && cookies) {
- /* a linked list of cookies in cookie file format */
- struct curl_slist *each = cookies;
- while(each) {
- printf("%s\\n", each->data);
- each = each->next;
- }
- /* we must free these cookies when we are done */
- curl_slist_free_all(cookies);
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.14.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_COOKIELIST (3)
diff --git a/docs/libcurl/opts/CURLINFO_COOKIELIST.md b/docs/libcurl/opts/CURLINFO_COOKIELIST.md
new file mode 100644
index 000000000..60ac0f036
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_COOKIELIST.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_COOKIELIST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_COOKIELIST (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_COOKIELIST - get all known cookies
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_COOKIELIST,
+ struct curl_slist **cookies);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a 'struct curl_slist *' to receive a linked-list of all
+cookies curl knows (expired ones, too). Do not forget to call
+curl_slist_free_all(3) on the list after it has been used. If there are no
+cookies (cookies for the handle have not been enabled or simply none have been
+received) the 'struct curl_slist *' is made a NULL pointer.
+
+Since 7.43.0 cookies that were imported in the Set-Cookie format without a
+domain name are not exported by this option.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* enable the cookie engine */
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* extract all known cookies */
+ struct curl_slist *cookies = NULL;
+ res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);
+ if(!res && cookies) {
+ /* a linked list of cookies in cookie file format */
+ struct curl_slist *each = cookies;
+ while(each) {
+ printf("%s\n", each->data);
+ each = each->next;
+ }
+ /* we must free these cookies when we are done */
+ curl_slist_free_all(cookies);
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.14.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3 b/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3
deleted file mode 100644
index 4129a63fa..000000000
--- a/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_EFFECTIVE_METHOD 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_EFFECTIVE_METHOD \- get the last used HTTP method
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_METHOD,
- char **methodp);
-.fi
-.SH DESCRIPTION
-Pass in a pointer to a char pointer and get the last used effective HTTP
-method.
-
-In cases when you have asked libcurl to follow redirects, the method may not be
-the same method the first request would use.
-
-The \fBmethodp\fP pointer is NULL or points to private memory. You MUST NOT
-free - it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the
-corresponding CURL handle.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "data");
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- char *method = NULL;
- curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_METHOD, &method);
- if(method)
- printf("Redirected to method: %s\\n", method);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.72.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_CUSTOMREQUEST (3),
-.BR CURLOPT_FOLLOWLOCATION (3)
diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md b/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md
new file mode 100644
index 000000000..da2e2a016
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_EFFECTIVE_METHOD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CUSTOMREQUEST (3)
+ - CURLOPT_FOLLOWLOCATION (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_EFFECTIVE_METHOD - get the last used HTTP method
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_METHOD,
+ char **methodp);
+~~~
+
+# DESCRIPTION
+
+Pass in a pointer to a char pointer and get the last used effective HTTP
+method.
+
+In cases when you have asked libcurl to follow redirects, the method may not be
+the same method the first request would use.
+
+The **methodp** pointer is NULL or points to private memory. You MUST NOT
+free - it gets freed when you call curl_easy_cleanup(3) on the
+corresponding CURL handle.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "data");
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ char *method = NULL;
+ curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_METHOD, &method);
+ if(method)
+ printf("Redirected to method: %s\n", method);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.72.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3 b/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3
deleted file mode 100644
index 987a179d4..000000000
--- a/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_EFFECTIVE_URL 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_EFFECTIVE_URL \- get the last used URL
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_URL, char **urlp);
-.fi
-.SH DESCRIPTION
-Pass in a pointer to a char pointer and get the last used effective URL.
-
-In cases when you have asked libcurl to follow redirects, it may not be the same
-value you set with \fICURLOPT_URL(3)\fP.
-
-The \fBurlp\fP pointer is NULL or points to private memory. You MUST NOT free
-- it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding
-CURL handle.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- char *url = NULL;
- curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
- if(url)
- printf("Redirect to: %s\\n", url);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_FOLLOWLOCATION (3)
diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md b/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md
new file mode 100644
index 000000000..268ff2c67
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_EFFECTIVE_URL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FOLLOWLOCATION (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_EFFECTIVE_URL - get the last used URL
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_EFFECTIVE_URL, char **urlp);
+~~~
+
+# DESCRIPTION
+
+Pass in a pointer to a char pointer and get the last used effective URL.
+
+In cases when you have asked libcurl to follow redirects, it may not be the same
+value you set with CURLOPT_URL(3).
+
+The **urlp** pointer is NULL or points to private memory. You MUST NOT free
+- it gets freed when you call curl_easy_cleanup(3) on the corresponding
+CURL handle.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ char *url = NULL;
+ curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
+ if(url)
+ printf("Redirect to: %s\n", url);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_FILETIME.3 b/docs/libcurl/opts/CURLINFO_FILETIME.3
deleted file mode 100644
index e8da80cf3..000000000
--- a/docs/libcurl/opts/CURLINFO_FILETIME.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_FILETIME 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_FILETIME \- get the remote time of the retrieved document
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME, long *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the remote time of the retrieved document
-in number of seconds since January 1 1970 in the GMT/UTC time zone. If you get
--1, it can be because of many reasons (it might be unknown, the server might
-hide it or the server does not support the command that tells document time
-etc) and the time of the document is unknown.
-
-You must tell libcurl to collect this information before the transfer is made,
-by using the \fICURLOPT_FILETIME(3)\fP option to \fIcurl_easy_setopt(3)\fP or
-you this unconditionally gets a -1 back.
-
-Consider using \fICURLINFO_FILETIME_T(3)\fP to be able to extract dates beyond
-the year 2038 on systems using 32 bit longs (Windows).
-.SH PROTOCOLS
-HTTP(S), FTP(S), SFTP
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, url);
- /* Ask for filetime */
- curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
- if((CURLE_OK == res) && (filetime >= 0)) {
- time_t file_time = (time_t)filetime;
- printf("filetime %s: %s", filename, ctime(&file_time));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.5
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_FILETIME (3)
diff --git a/docs/libcurl/opts/CURLINFO_FILETIME.md b/docs/libcurl/opts/CURLINFO_FILETIME.md
new file mode 100644
index 000000000..77ef534b4
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_FILETIME.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_FILETIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FILETIME (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_FILETIME - get the remote time of the retrieved document
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME, long *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the remote time of the retrieved document
+in number of seconds since January 1 1970 in the GMT/UTC time zone. If you get
+-1, it can be because of many reasons (it might be unknown, the server might
+hide it or the server does not support the command that tells document time
+etc) and the time of the document is unknown.
+
+You must tell libcurl to collect this information before the transfer is made,
+by using the CURLOPT_FILETIME(3) option to curl_easy_setopt(3) or
+you this unconditionally gets a -1 back.
+
+Consider using CURLINFO_FILETIME_T(3) to be able to extract dates beyond
+the year 2038 on systems using 32 bit longs (Windows).
+
+# PROTOCOLS
+
+HTTP(S), FTP(S), SFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ /* Ask for filetime */
+ curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ long filetime = 0;
+ res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
+ if((CURLE_OK == res) && (filetime >= 0)) {
+ time_t file_time = (time_t)filetime;
+ printf("filetime: %s", ctime(&file_time));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.5
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_FILETIME_T.3 b/docs/libcurl/opts/CURLINFO_FILETIME_T.3
deleted file mode 100644
index ffed16677..000000000
--- a/docs/libcurl/opts/CURLINFO_FILETIME_T.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_FILETIME 3 "25 Jan 2018" libcurl libcurl
-.SH NAME
-CURLINFO_FILETIME_T \- get the remote time of the retrieved document
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the remote time of the retrieved
-document in number of seconds since January 1 1970 in the GMT/UTC time
-zone. If you get -1, it can be because of many reasons (it might be unknown,
-the server might hide it or the server does not support the command that tells
-document time etc) and the time of the document is unknown.
-
-You must ask libcurl to collect this information before the transfer is made,
-by using the \fICURLOPT_FILETIME(3)\fP option to \fIcurl_easy_setopt(3)\fP or
-you unconditionally get a -1 back.
-
-This option is an alternative to \fICURLINFO_FILETIME(3)\fP to allow systems
-with 32 bit long variables to extract dates outside of the 32bit timestamp
-range.
-.SH PROTOCOLS
-HTTP(S), FTP(S), SFTP
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, url);
- /* Ask for filetime */
- curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- curl_off_t filetime;
- res = curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime);
- if((CURLE_OK == res) && (filetime >= 0)) {
- time_t file_time = (time_t)filetime;
- printf("filetime %s: %s", filename, ctime(&file_time));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.59.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_FILETIME (3)
diff --git a/docs/libcurl/opts/CURLINFO_FILETIME_T.md b/docs/libcurl/opts/CURLINFO_FILETIME_T.md
new file mode 100644
index 000000000..62c5f3cb0
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_FILETIME_T.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_FILETIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FILETIME (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_FILETIME_T - get the remote time of the retrieved document
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FILETIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the remote time of the retrieved
+document in number of seconds since January 1 1970 in the GMT/UTC time
+zone. If you get -1, it can be because of many reasons (it might be unknown,
+the server might hide it or the server does not support the command that tells
+document time etc) and the time of the document is unknown.
+
+You must ask libcurl to collect this information before the transfer is made,
+by using the CURLOPT_FILETIME(3) option to curl_easy_setopt(3) or
+you unconditionally get a -1 back.
+
+This option is an alternative to CURLINFO_FILETIME(3) to allow systems
+with 32 bit long variables to extract dates outside of the 32bit timestamp
+range.
+
+# PROTOCOLS
+
+HTTP(S), FTP(S), SFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* Ask for filetime */
+ curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ curl_off_t filetime;
+ res = curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime);
+ if((CURLE_OK == res) && (filetime >= 0)) {
+ time_t file_time = (time_t)filetime;
+ printf("filetime: %s", ctime(&file_time));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.59.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3 b/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3
deleted file mode 100644
index 8ca9a0571..000000000
--- a/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_FTP_ENTRY_PATH 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_FTP_ENTRY_PATH \- get entry path in FTP server
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FTP_ENTRY_PATH, char **path);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a char pointer to receive a pointer to a string holding the
-path of the entry path. That is the initial path libcurl ended up in when
-logging on to the remote FTP server. This stores a NULL as pointer if
-something is wrong.
-
-The \fBpath\fP pointer is NULL or points to private memory. You MUST NOT free
-- it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding
-CURL handle.
-.SH PROTOCOLS
-FTP(S) and SFTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com");
-
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* extract the entry path */
- char *ep = NULL;
- res = curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &ep);
- if(!res && ep) {
- printf("Entry path was: %s\\n", ep);
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.4. Works for SFTP since 7.21.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md b/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md
new file mode 100644
index 000000000..344e1f174
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_FTP_ENTRY_PATH
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_FTP_ENTRY_PATH - get entry path in FTP server
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_FTP_ENTRY_PATH, char **path);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a char pointer to receive a pointer to a string holding the
+path of the entry path. That is the initial path libcurl ended up in when
+logging on to the remote FTP server. This stores a NULL as pointer if
+something is wrong.
+
+The **path** pointer is NULL or points to private memory. You MUST NOT free
+- it gets freed when you call curl_easy_cleanup(3) on the corresponding
+CURL handle.
+
+# PROTOCOLS
+
+FTP(S) and SFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com");
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* extract the entry path */
+ char *ep = NULL;
+ res = curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &ep);
+ if(!res && ep) {
+ printf("Entry path was: %s\n", ep);
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.4. Works for SFTP since 7.21.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3 b/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3
deleted file mode 100644
index bce4b8a3c..000000000
--- a/docs/libcurl/opts/CURLINFO_HEADER_SIZE.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_HEADER_SIZE 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_HEADER_SIZE \- get size of retrieved headers
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HEADER_SIZE, long *sizep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the total size of all the headers
-received. Measured in number of bytes.
-
-The total includes the size of any received headers suppressed by
-\fICURLOPT_SUPPRESS_CONNECT_HEADERS(3)\fP.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long size;
- res = curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size);
- if(!res)
- printf("Header size: %ld bytes\\n", size);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_REQUEST_SIZE (3),
-.BR CURLINFO_SIZE_DOWNLOAD (3)
diff --git a/docs/libcurl/opts/CURLINFO_HEADER_SIZE.md b/docs/libcurl/opts/CURLINFO_HEADER_SIZE.md
new file mode 100644
index 000000000..67ccfc232
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_HEADER_SIZE.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_HEADER_SIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REQUEST_SIZE (3)
+ - CURLINFO_SIZE_DOWNLOAD (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_HEADER_SIZE - get size of retrieved headers
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HEADER_SIZE, long *sizep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the total size of all the headers
+received. Measured in number of bytes.
+
+The total includes the size of any received headers suppressed by
+CURLOPT_SUPPRESS_CONNECT_HEADERS(3).
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long size;
+ res = curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size);
+ if(!res)
+ printf("Header size: %ld bytes\n", size);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3 b/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3
deleted file mode 100644
index 07c967547..000000000
--- a/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_HTTPAUTH_AVAIL 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_HTTPAUTH_AVAIL \- get available HTTP authentication methods
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTPAUTH_AVAIL, long *authp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive a bitmask indicating the authentication
-method(s) available according to the previous response. The meaning of the
-bits is explained in the \fICURLOPT_HTTPAUTH(3)\fP option for
-\fIcurl_easy_setopt(3)\fP.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* extract the available authentication types */
- long auth;
- res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_AVAIL, &auth);
- if(!res) {
- if(!auth)
- printf("No auth available, perhaps no 401?\\n");
- else {
- printf("%s%s%s%s\\n",
- auth & CURLAUTH_BASIC ? "Basic ":"",
- auth & CURLAUTH_DIGEST ? "Digest ":"",
- auth & CURLAUTH_NEGOTIATE ? "Negotiate ":"",
- auth % CURLAUTH_NTLM ? "NTLM ":"");
- }
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added RFC 2617 in 7.10.8
-Added RFC 7616 in 7.57.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_PROXYAUTH_AVAIL (3),
-.BR CURLOPT_HTTPAUTH (3)
diff --git a/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md b/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md
new file mode 100644
index 000000000..574e0a52b
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_HTTPAUTH_AVAIL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PROXYAUTH_AVAIL (3)
+ - CURLOPT_HTTPAUTH (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_HTTPAUTH_AVAIL - get available HTTP authentication methods
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTPAUTH_AVAIL, long *authp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive a bitmask indicating the authentication
+method(s) available according to the previous response. The meaning of the
+bits is explained in the CURLOPT_HTTPAUTH(3) option for
+curl_easy_setopt(3).
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* extract the available authentication types */
+ long auth;
+ res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_AVAIL, &auth);
+ if(!res) {
+ if(!auth)
+ printf("No auth available, perhaps no 401?\n");
+ else {
+ printf("%s%s%s%s\n",
+ auth & CURLAUTH_BASIC ? "Basic ":"",
+ auth & CURLAUTH_DIGEST ? "Digest ":"",
+ auth & CURLAUTH_NEGOTIATE ? "Negotiate ":"",
+ auth % CURLAUTH_NTLM ? "NTLM ":"");
+ }
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added RFC 2617 in 7.10.8
+Added RFC 7616 in 7.57.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3 b/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3
deleted file mode 100644
index 3262aa686..000000000
--- a/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_HTTP_CONNECTCODE 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_HTTP_CONNECTCODE \- get the CONNECT response code
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_CONNECTCODE, long *p);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the last received HTTP proxy response code
-to a CONNECT request. The returned value is zero if no such response code was
-available.
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* typically CONNECT is used to do HTTPS over HTTP proxies */
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long code;
- res = curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, &code);
- if(!res && code)
- printf("The CONNECT response code: %03ld\\n", code);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.7
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RESPONSE_CODE (3)
diff --git a/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md b/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md
new file mode 100644
index 000000000..ee3f0f65c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_HTTP_CONNECTCODE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RESPONSE_CODE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_HTTP_CONNECTCODE - get the CONNECT response code
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_CONNECTCODE, long *p);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the last received HTTP proxy response code
+to a CONNECT request. The returned value is zero if no such response code was
+available.
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* typically CONNECT is used to do HTTPS over HTTP proxies */
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long code;
+ res = curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, &code);
+ if(!res && code)
+ printf("The CONNECT response code: %03ld\n", code);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.7
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3 b/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3
deleted file mode 100644
index 8058c47b6..000000000
--- a/docs/libcurl/opts/CURLINFO_HTTP_VERSION.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_HTTP_VERSION 3 "11 May 2016" libcurl libcurl
-.SH NAME
-CURLINFO_HTTP_VERSION \- get the http version used in the connection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_VERSION, long *p);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the version used in the last http
-connection done using this handle. The returned value is
-CURL_HTTP_VERSION_1_0, CURL_HTTP_VERSION_1_1, CURL_HTTP_VERSION_2_0,
-CURL_HTTP_VERSION_3 or 0 if the version cannot be determined.
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long http_version;
- curl_easy_getinfo(curl, CURLINFO_HTTP_VERSION, &http_version);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.50.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RESPONSE_CODE (3)
diff --git a/docs/libcurl/opts/CURLINFO_HTTP_VERSION.md b/docs/libcurl/opts/CURLINFO_HTTP_VERSION.md
new file mode 100644
index 000000000..994d7712c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_HTTP_VERSION.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_HTTP_VERSION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RESPONSE_CODE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_HTTP_VERSION - get the http version used in the connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_HTTP_VERSION, long *p);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the version used in the last http
+connection done using this handle. The returned value is
+CURL_HTTP_VERSION_1_0, CURL_HTTP_VERSION_1_1, CURL_HTTP_VERSION_2_0,
+CURL_HTTP_VERSION_3 or 0 if the version cannot be determined.
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long http_version;
+ curl_easy_getinfo(curl, CURLINFO_HTTP_VERSION, &http_version);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.50.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_LASTSOCKET.3 b/docs/libcurl/opts/CURLINFO_LASTSOCKET.3
deleted file mode 100644
index efc137946..000000000
--- a/docs/libcurl/opts/CURLINFO_LASTSOCKET.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_LASTSOCKET 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_LASTSOCKET \- get the last socket used
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LASTSOCKET, long *socket);
-.fi
-.SH DESCRIPTION
-Deprecated since 7.45.0. Use \fICURLINFO_ACTIVESOCKET(3)\fP instead.
-
-Pass a pointer to a long to receive the last socket used by this curl
-session. If the socket is no longer valid, -1 is returned. When you finish
-working with the socket, you must call \fIcurl_easy_cleanup(3)\fP as usual 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.
-
-NOTE: this API is deprecated since it is not working on win64 where the SOCKET
-type is 64 bits large while its 'long' is 32 bits. Use the
-\fICURLINFO_ACTIVESOCKET(3)\fP instead, if possible.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- long sockfd; /* does not work on win64! */
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Do not do the transfer - only connect to host */
- curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
- res = curl_easy_perform(curl);
-
- /* Extract the socket from the curl handle */
- res = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockfd);
-
- if(res != CURLE_OK) {
- printf("Error: %s\\n", curl_easy_strerror(res));
- return 1;
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_ACTIVESOCKET (3),
-.BR CURLOPT_CONNECT_ONLY (3)
diff --git a/docs/libcurl/opts/CURLINFO_LASTSOCKET.md b/docs/libcurl/opts/CURLINFO_LASTSOCKET.md
new file mode 100644
index 000000000..b1619ebdb
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_LASTSOCKET.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_LASTSOCKET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_ACTIVESOCKET (3)
+ - CURLOPT_CONNECT_ONLY (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_LASTSOCKET - get the last socket used
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LASTSOCKET, long *socket);
+~~~
+
+# DESCRIPTION
+
+Deprecated since 7.45.0. Use CURLINFO_ACTIVESOCKET(3) instead.
+
+Pass a pointer to a long to receive the last socket used by this curl
+session. If the socket is no longer valid, -1 is returned. When you finish
+working with the socket, you must call curl_easy_cleanup(3) as usual and
+let libcurl close the socket and cleanup other resources associated with the
+handle. This is typically used in combination with
+CURLOPT_CONNECT_ONLY(3).
+
+NOTE: this API is deprecated since it is not working on win64 where the SOCKET
+type is 64 bits large while its 'long' is 32 bits. Use the
+CURLINFO_ACTIVESOCKET(3) instead, if possible.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ long sockfd; /* does not work on win64! */
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Do not do the transfer - only connect to host */
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
+ res = curl_easy_perform(curl);
+
+ /* Extract the socket from the curl handle */
+ res = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockfd);
+
+ if(res != CURLE_OK) {
+ printf("Error: %s\n", curl_easy_strerror(res));
+ return 1;
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_IP.3 b/docs/libcurl/opts/CURLINFO_LOCAL_IP.3
deleted file mode 100644
index 151340301..000000000
--- a/docs/libcurl/opts/CURLINFO_LOCAL_IP.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_LOCAL_IP 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_LOCAL_IP \- get local IP address of last connection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_IP, char **ip);
-.fi
-.SH DESCRIPTION
-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 is reused at next
-request so you need to copy the string if you want to keep the information.
-
-The \fBip\fP pointer is NULL or points to private memory. You MUST NOT free -
-it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding
-CURL handle.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-{
- char *ip;
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the transfer */
- res = curl_easy_perform(curl);
- /* Check for errors */
- if((res == CURLE_OK) &&
- !curl_easy_getinfo(curl, CURLINFO_LOCAL_IP, &ip) && ip) {
- printf("Local IP: %s\\n", ip);
- }
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_PRIMARY_IP (3),
-.BR CURLINFO_LOCAL_PORT (3)
diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_IP.md b/docs/libcurl/opts/CURLINFO_LOCAL_IP.md
new file mode 100644
index 000000000..e70d0cf04
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_LOCAL_IP.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_LOCAL_IP
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_LOCAL_PORT (3)
+ - CURLINFO_PRIMARY_IP (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_LOCAL_IP - get local IP address of last connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_IP, char **ip);
+~~~
+
+# DESCRIPTION
+
+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 **curl** handle. This string may be IPv6 when that is
+enabled. Note that you get a pointer to a memory area that is reused at next
+request so you need to copy the string if you want to keep the information.
+
+The **ip** pointer is NULL or points to private memory. You MUST NOT free -
+it gets freed when you call curl_easy_cleanup(3) on the corresponding
+CURL handle.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ char *ip;
+ CURLcode res;
+ CURL *curl = curl_easy_init();
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the transfer */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if((res == CURLE_OK) &&
+ !curl_easy_getinfo(curl, CURLINFO_LOCAL_IP, &ip) && ip) {
+ printf("Local IP: %s\n", ip);
+ }
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3 b/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3
deleted file mode 100644
index 9a5d16a0d..000000000
--- a/docs/libcurl/opts/CURLINFO_LOCAL_PORT.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_LOCAL_PORT 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_LOCAL_PORT \- get the latest local port number
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_PORT, long *portp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the local port number of the most recent
-connection done with this \fBcurl\fP handle.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-{
- CURL *curl;
- CURLcode res;
-
- curl = curl_easy_init();
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- res = curl_easy_perform(curl);
-
- if(CURLE_OK == res) {
- long port;
- res = curl_easy_getinfo(curl, CURLINFO_LOCAL_PORT, &port);
-
- if(CURLE_OK == res) {
- printf("We used local port: %ld\\n", port);
- }
- }
- curl_easy_cleanup(curl);
- }
- return 0;
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_LOCAL_IP (3),
-.BR CURLINFO_PRIMARY_PORT (3)
diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_PORT.md b/docs/libcurl/opts/CURLINFO_LOCAL_PORT.md
new file mode 100644
index 000000000..055fc2ee0
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_LOCAL_PORT.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_LOCAL_PORT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_LOCAL_IP (3)
+ - CURLINFO_PRIMARY_PORT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_LOCAL_PORT - get the latest local port number
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_PORT, long *portp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the local port number of the most recent
+connection done with this **curl** handle.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+
+ if(CURLE_OK == res) {
+ long port;
+ res = curl_easy_getinfo(curl, CURLINFO_LOCAL_PORT, &port);
+
+ if(CURLE_OK == res) {
+ printf("We used local port: %ld\n", port);
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3 b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3
deleted file mode 100644
index 473342fac..000000000
--- a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_NAMELOOKUP_TIME 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_NAMELOOKUP_TIME \- get the name lookup time
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME,
- double *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the total time in seconds from the start
-until the name resolving was completed.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- double namelookup;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &namelookup);
- if(CURLE_OK == res) {
- printf("Time: %.1f", namelookup);
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_NAMELOOKUP_TIME_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md
new file mode 100644
index 000000000..8cf425e0f
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_NAMELOOKUP_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_NAMELOOKUP_TIME_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_NAMELOOKUP_TIME - get the name lookup time
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME,
+ double *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the total time in seconds from the start
+until the name resolving was completed.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ double namelookup;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &namelookup);
+ if(CURLE_OK == res) {
+ printf("Time: %.1f", namelookup);
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3 b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3
deleted file mode 100644
index 0cedd39fc..000000000
--- a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_NAMELOOKUP_TIME_T 3 "28 Apr 2018" libcurl libcurl
-.SH NAME
-CURLINFO_NAMELOOKUP_TIME_T \- get the name lookup time in microseconds
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the total time in microseconds
-from the start until the name resolving was completed.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_off_t namelookup;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T, &namelookup);
- if(CURLE_OK == res) {
- printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", namelookup / 1000000,
- (long)(namelookup % 1000000));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_NAMELOOKUP_TIME (3)
diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md
new file mode 100644
index 000000000..a3fd4dd84
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_NAMELOOKUP_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_NAMELOOKUP_TIME (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_NAMELOOKUP_TIME_T - get the name lookup time in microseconds
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NAMELOOKUP_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the total time in microseconds
+from the start until the name resolving was completed.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t namelookup;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T, &namelookup);
+ if(CURLE_OK == res) {
+ printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", namelookup / 1000000,
+ (long)(namelookup % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3 b/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3
deleted file mode 100644
index aec2d709c..000000000
--- a/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_NUM_CONNECTS 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_NUM_CONNECTS \- get number of created connections
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NUM_CONNECTS, long *nump);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive how many new connections libcurl had to
-create to achieve the previous transfer (only the successful connects are
-counted). Combined with \fICURLINFO_REDIRECT_COUNT(3)\fP you are able to know
-how many times libcurl successfully reused existing connection(s) or not. See
-the connection options of \fIcurl_easy_setopt(3)\fP to see how libcurl tries
-to make persistent connections to save time.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long connects;
- res = curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &connects);
- if(res)
- printf("It needed %d connects\\n", connects);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.12.3
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md b/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md
new file mode 100644
index 000000000..5127a0a32
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_NUM_CONNECTS
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_NUM_CONNECTS - get number of created connections
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_NUM_CONNECTS, long *nump);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive how many new connections libcurl had to
+create to achieve the previous transfer (only the successful connects are
+counted). Combined with CURLINFO_REDIRECT_COUNT(3) you are able to know how
+many times libcurl successfully reused existing connection(s) or not. See the
+connection options of curl_easy_setopt(3) to see how libcurl tries to make
+persistent connections to save time.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long connects;
+ res = curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &connects);
+ if(res)
+ printf("It needed %ld connects\n", connects);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.12.3
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_OS_ERRNO.3 b/docs/libcurl/opts/CURLINFO_OS_ERRNO.3
deleted file mode 100644
index 96b3b9dfa..000000000
--- a/docs/libcurl/opts/CURLINFO_OS_ERRNO.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_OS_ERRNO 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_OS_ERRNO \- get errno number from last connect failure
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_OS_ERRNO, long *errnop);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the errno variable from a connect failure.
-Note that the value is only set on failure, it is not reset upon a successful
-operation. The number is OS and system specific.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res != CURLE_OK) {
- long error;
- res = curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &error);
- if(res && error) {
- printf("Errno: %ld\\n", error);
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.12.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3)
diff --git a/docs/libcurl/opts/CURLINFO_OS_ERRNO.md b/docs/libcurl/opts/CURLINFO_OS_ERRNO.md
new file mode 100644
index 000000000..3fb69b43c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_OS_ERRNO.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_OS_ERRNO
+Section: 3
+Source: libcurl
+See-also:
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_OS_ERRNO - get errno number from last connect failure
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_OS_ERRNO, long *errnop);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the errno variable from a connect failure.
+Note that the value is only set on failure, it is not reset upon a successful
+operation. The number is OS and system specific.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res != CURLE_OK) {
+ long error;
+ res = curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &error);
+ if(res && error) {
+ printf("Errno: %ld\n", error);
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.12.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3 b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3
deleted file mode 100644
index 05cab3be3..000000000
--- a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PRETRANSFER_TIME 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_PRETRANSFER_TIME \- get the time until the file transfer start
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME,
- double *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the time, in seconds, it took from the
-start until the file transfer is just about to begin.
-
-This time-stamp includes all pre-transfer commands and negotiations that are
-specific to the particular protocol(s) involved. It includes the sending of
-the protocol- specific protocol instructions that triggers a transfer.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- double pretransfer;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &pretransfer);
- if(CURLE_OK == res) {
- printf("Time: %.1f", pretransfer);
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONNECT_TIME_T (3),
-.BR CURLINFO_PRETRANSFER_TIME_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md
new file mode 100644
index 000000000..8eda23a3c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PRETRANSFER_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONNECT_TIME_T (3)
+ - CURLINFO_PRETRANSFER_TIME_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PRETRANSFER_TIME - get the time until the file transfer start
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME,
+ double *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the time, in seconds, it took from the
+start until the file transfer is just about to begin.
+
+This time-stamp includes all pre-transfer commands and negotiations that are
+specific to the particular protocol(s) involved. It includes the sending of
+the protocol-specific instructions that trigger a transfer.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ double pretransfer;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &pretransfer);
+ if(CURLE_OK == res) {
+ printf("Time: %.1f", pretransfer);
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3 b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3
deleted file mode 100644
index eb1434a54..000000000
--- a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PRETRANSFER_TIME_T 3 "28 Apr 2018" libcurl libcurl
-.SH NAME
-CURLINFO_PRETRANSFER_TIME_T \- get the time until the file transfer start
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the time, in microseconds,
-it took from the
-start until the file transfer is just about to begin. This includes all
-pre-transfer commands and negotiations that are specific to the particular
-protocol(s) involved. It does \fInot\fP involve the sending of the protocol-
-specific request that triggers a transfer.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_off_t pretransfer;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME_T, &pretransfer);
- if(CURLE_OK == res) {
- printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", pretransfer / 1000000,
- (long)(pretransfer % 1000000));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONNECT_TIME (3),
-.BR CURLINFO_PRETRANSFER_TIME_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md
new file mode 100644
index 000000000..50c515f3a
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PRETRANSFER_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONNECT_TIME (3)
+ - CURLINFO_PRETRANSFER_TIME_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PRETRANSFER_TIME_T - get the time until the file transfer start
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRETRANSFER_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the time, in microseconds, it took
+from the start until the file transfer is just about to begin.
+
+This time-stamp includes all pre-transfer commands and negotiations that are
+specific to the particular protocol(s) involved. It includes the sending of
+the protocol-specific instructions that trigger a transfer.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t pretransfer;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME_T, &pretransfer);
+ if(CURLE_OK == res) {
+ printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld\n",
+ pretransfer / 1000000,
+ (long)(pretransfer % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3 b/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3
deleted file mode 100644
index 6431e36eb..000000000
--- a/docs/libcurl/opts/CURLINFO_PRIMARY_IP.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PRIMARY_IP 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_PRIMARY_IP \- get IP address of last connection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_IP, char **ip);
-.fi
-.SH DESCRIPTION
-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 is reused at next request so you need to
-copy the string if you want to keep the information.
-
-The \fBip\fP pointer is NULL or points to private memory. You MUST NOT free -
-it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding
-CURL handle.
-.SH PROTOCOLS
-All network based ones
-.SH EXAMPLE
-.nf
-{
- char *ip;
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the transfer */
- res = curl_easy_perform(curl);
- /* Check for errors */
- if((res == CURLE_OK) &&
- !curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip) && ip) {
- printf("IP: %s\\n", ip);
- }
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_LOCAL_IP (3),
-.BR CURLINFO_LOCAL_PORT (3),
-.BR CURLINFO_PRIMARY_PORT (3)
diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_IP.md b/docs/libcurl/opts/CURLINFO_PRIMARY_IP.md
new file mode 100644
index 000000000..115113f3f
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PRIMARY_IP.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PRIMARY_IP
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_LOCAL_IP (3)
+ - CURLINFO_LOCAL_PORT (3)
+ - CURLINFO_PRIMARY_PORT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PRIMARY_IP - get IP address of last connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_IP, char **ip);
+~~~
+
+# DESCRIPTION
+
+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
+**curl** handle. This string may be IPv6 when that is enabled. Note that you
+get a pointer to a memory area that is reused at next request so you need to
+copy the string if you want to keep the information.
+
+The **ip** pointer is NULL or points to private memory. You MUST NOT free -
+it gets freed when you call curl_easy_cleanup(3) on the corresponding
+CURL handle.
+
+# PROTOCOLS
+
+All network based ones
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ char *ip;
+ CURLcode res;
+ CURL *curl = curl_easy_init();
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the transfer */
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if((res == CURLE_OK) &&
+ !curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip) && ip) {
+ printf("IP: %s\n", ip);
+ }
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3 b/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3
deleted file mode 100644
index 857999595..000000000
--- a/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PRIMARY_PORT 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_PRIMARY_PORT \- get the latest destination port number
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_PORT, long *portp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the destination port of the most recent
-connection done with this \fBcurl\fP handle.
-
-This is the destination port of the actual TCP or UDP connection libcurl used.
-If a proxy was used for the most recent transfer, this is the port number of
-the proxy, if no proxy was used it is the port number of the most recently
-accessed URL.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long port;
- res = curl_easy_getinfo(curl, CURLINFO_PRIMARY_PORT, &port);
- if(!res)
- printf("Connected to remote port: %ld\\n", port);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_LOCAL_PORT (3),
-.BR CURLINFO_PRIMARY_IP (3)
diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md b/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md
new file mode 100644
index 000000000..3d90b64ed
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PRIMARY_PORT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_LOCAL_PORT (3)
+ - CURLINFO_PRIMARY_IP (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PRIMARY_PORT - get the latest destination port number
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_PORT, long *portp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the destination port of the most recent
+connection done with this **curl** handle.
+
+This is the destination port of the actual TCP or UDP connection libcurl used.
+If a proxy was used for the most recent transfer, this is the port number of
+the proxy, if no proxy was used it is the port number of the most recently
+accessed URL.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long port;
+ res = curl_easy_getinfo(curl, CURLINFO_PRIMARY_PORT, &port);
+ if(!res)
+ printf("Connected to remote port: %ld\n", port);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PRIVATE.3 b/docs/libcurl/opts/CURLINFO_PRIVATE.3
deleted file mode 100644
index 58459752f..000000000
--- a/docs/libcurl/opts/CURLINFO_PRIVATE.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PRIVATE 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_PRIVATE \- get the private pointer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIVATE, char **private);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the pointer to the private data
-associated with the curl handle (set with the \fICURLOPT_PRIVATE(3)\fP).
-Please note that for internal reasons, the value is returned as a char
-pointer, although effectively being a 'void *'.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- void *pointer = 0x2345454;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* set the private pointer */
- curl_easy_setopt(curl, CURLOPT_PRIVATE, pointer);
- ret = curl_easy_perform(curl);
-
- /* extract the private pointer again */
- ret = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &pointer);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.3
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_PRIVATE (3)
diff --git a/docs/libcurl/opts/CURLINFO_PRIVATE.md b/docs/libcurl/opts/CURLINFO_PRIVATE.md
new file mode 100644
index 000000000..127049f7e
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PRIVATE.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PRIVATE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PRIVATE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PRIVATE - get the private pointer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIVATE, char **private);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a char pointer to receive the pointer to the private data
+associated with the curl handle (set with the CURLOPT_PRIVATE(3)).
+Please note that for internal reasons, the value is returned as a char
+pointer, although effectively being a 'void *'.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ void *pointer = (void *)0x2345454;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* set the private pointer */
+ curl_easy_setopt(curl, CURLOPT_PRIVATE, pointer);
+ res = curl_easy_perform(curl);
+
+ /* extract the private pointer again */
+ res = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &pointer);
+
+ if(res)
+ printf("error: %s\n", curl_easy_strerror(res));
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.3
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PROTOCOL.3 b/docs/libcurl/opts/CURLINFO_PROTOCOL.3
deleted file mode 100644
index 94b2dacf8..000000000
--- a/docs/libcurl/opts/CURLINFO_PROTOCOL.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PROTOCOL 3 "23 November 2016" libcurl libcurl
-.SH NAME
-CURLINFO_PROTOCOL \- get the protocol used in the connection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
-.fi
-.SH DESCRIPTION
-This option is deprecated. We strongly recommend using
-\fICURLINFO_SCHEME(3)\fP instead, because this option cannot return all
-possible protocols!
-
-Pass a pointer to a long to receive the version used in the last http
-connection. The returned value is set to one of the CURLPROTO_* values:
-
-.nf
-CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_FTP, CURLPROTO_FTPS,
-CURLPROTO_GOPHER, CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_IMAP,
-CURLPROTO_IMAPS, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_POP3,
-CURLPROTO_POP3S, CURLPROTO_RTMP, CURLPROTO_RTMPE, CURLPROTO_RTMPS,
-CURLPROTO_RTMPT, CURLPROTO_RTMPTE, CURLPROTO_RTMPTS, CURLPROTO_RTSP,
-CURLPROTO_SCP, CURLPROTO_SFTP, CURLPROTO_SMB, CURLPROTO_SMBS, CURLPROTO_SMTP,
-CURLPROTO_SMTPS, CURLPROTO_TELNET, CURLPROTO_TFTP, CURLPROTO_MQTT
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long protocol;
- curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0. Deprecated since 7.85.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RESPONSE_CODE (3)
diff --git a/docs/libcurl/opts/CURLINFO_PROTOCOL.md b/docs/libcurl/opts/CURLINFO_PROTOCOL.md
new file mode 100644
index 000000000..9dfb2970f
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PROTOCOL.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PROTOCOL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RESPONSE_CODE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PROTOCOL - get the protocol used in the connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
+~~~
+
+# DESCRIPTION
+
+This option is deprecated. We strongly recommend using
+CURLINFO_SCHEME(3) instead, because this option cannot return all
+possible protocols!
+
+Pass a pointer to a long to receive the version used in the last http
+connection. The returned value is set to one of the CURLPROTO_* values:
+
+~~~c
+CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_FTP, CURLPROTO_FTPS,
+CURLPROTO_GOPHER, CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_IMAP,
+CURLPROTO_IMAPS, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_POP3,
+CURLPROTO_POP3S, CURLPROTO_RTMP, CURLPROTO_RTMPE, CURLPROTO_RTMPS,
+CURLPROTO_RTMPT, CURLPROTO_RTMPTE, CURLPROTO_RTMPTS, CURLPROTO_RTSP,
+CURLPROTO_SCP, CURLPROTO_SFTP, CURLPROTO_SMB, CURLPROTO_SMBS, CURLPROTO_SMTP,
+CURLPROTO_SMTPS, CURLPROTO_TELNET, CURLPROTO_TFTP, CURLPROTO_MQTT
+~~~
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long protocol;
+ curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0. Deprecated since 7.85.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3 b/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3
deleted file mode 100644
index 4d0789bf6..000000000
--- a/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PROXYAUTH_AVAIL 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_PROXYAUTH_AVAIL \- get available HTTP proxy authentication methods
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXYAUTH_AVAIL,
- long *authp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive a bitmask indicating the authentication
-method(s) available according to the previous response. The meaning of the
-bits is explained in the \fICURLOPT_PROXYAUTH(3)\fP option for
-\fIcurl_easy_setopt(3)\fP.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1:80");
-
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* extract the available proxy authentication types */
- long auth;
- res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_AVAIL, &auth);
- if(!res) {
- if(!auth)
- printf("No proxy auth available, perhaps no 407?\\n");
- else {
- printf("%s%s%s%s\\n",
- auth & CURLAUTH_BASIC ? "Basic ":"",
- auth & CURLAUTH_DIGEST ? "Digest ":"",
- auth & CURLAUTH_NEGOTIATE ? "Negotiate ":"",
- auth % CURLAUTH_NTLM ? "NTLM ":"");
- }
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added RFC 2617 in 7.10.8
-Added RFC 7616 in 7.57.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_HTTPAUTH_AVAIL (3)
diff --git a/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md b/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md
new file mode 100644
index 000000000..0e9dbdcb5
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PROXYAUTH_AVAIL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_HTTPAUTH_AVAIL (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PROXYAUTH_AVAIL - get available HTTP proxy authentication methods
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXYAUTH_AVAIL,
+ long *authp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive a bitmask indicating the authentication
+method(s) available according to the previous response. The meaning of the
+bits is explained in the CURLOPT_PROXYAUTH(3) option for
+curl_easy_setopt(3).
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1:80");
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* extract the available proxy authentication types */
+ long auth;
+ res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_AVAIL, &auth);
+ if(!res) {
+ if(!auth)
+ printf("No proxy auth available, perhaps no 407?\n");
+ else {
+ printf("%s%s%s%s\n",
+ auth & CURLAUTH_BASIC ? "Basic ":"",
+ auth & CURLAUTH_DIGEST ? "Digest ":"",
+ auth & CURLAUTH_NEGOTIATE ? "Negotiate ":"",
+ auth % CURLAUTH_NTLM ? "NTLM ":"");
+ }
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added RFC 2617 in 7.10.8
+Added RFC 7616 in 7.57.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3 b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
deleted file mode 100644
index 17f6fcf7e..000000000
--- a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.3
+++ /dev/null
@@ -1,106 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PROXY_ERROR 3 "3 Aug 2020" libcurl libcurl
-.SH NAME
-CURLINFO_PROXY_ERROR \- get the detailed (SOCKS) proxy error
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef enum {
- CURLPX_OK,
- CURLPX_BAD_ADDRESS_TYPE,
- CURLPX_BAD_VERSION,
- CURLPX_CLOSED,
- CURLPX_GSSAPI,
- CURLPX_GSSAPI_PERMSG,
- CURLPX_GSSAPI_PROTECTION,
- CURLPX_IDENTD,
- CURLPX_IDENTD_DIFFER,
- CURLPX_LONG_HOSTNAME,
- CURLPX_LONG_PASSWD,
- CURLPX_LONG_USER,
- CURLPX_NO_AUTH,
- CURLPX_RECV_ADDRESS,
- CURLPX_RECV_AUTH,
- CURLPX_RECV_CONNECT,
- CURLPX_RECV_REQACK,
- CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
- CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
- CURLPX_REPLY_CONNECTION_REFUSED,
- CURLPX_REPLY_GENERAL_SERVER_FAILURE,
- CURLPX_REPLY_HOST_UNREACHABLE,
- CURLPX_REPLY_NETWORK_UNREACHABLE,
- CURLPX_REPLY_NOT_ALLOWED,
- CURLPX_REPLY_TTL_EXPIRED,
- CURLPX_REPLY_UNASSIGNED,
- CURLPX_REQUEST_FAILED,
- CURLPX_RESOLVE_HOST,
- CURLPX_SEND_AUTH,
- CURLPX_SEND_CONNECT,
- CURLPX_SEND_REQUEST,
- CURLPX_UNKNOWN_FAIL,
- CURLPX_UNKNOWN_MODE,
- CURLPX_USER_REJECTED,
- CURLPX_LAST /* never use */
-} CURLproxycode;
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_ERROR, long *detail);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive a detailed error code when the most recent
-transfer returned a \fBCURLE_PROXY\fP error. That error code matches the
-\fBCURLproxycode\fP set.
-
-The error code is zero (\fBCURLPX_OK\fP) if no response code was available.
-.SH PROTOCOLS
-All that can be done over SOCKS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://127.0.0.1");
- res = curl_easy_perform(curl);
- if(res == CURLE_PROXY) {
- long proxycode;
- res = curl_easy_getinfo(curl, CURLINFO_PROXY_ERROR, &proxycode);
- if(!res && proxycode)
- printf("The detailed proxy error: %ld\\n", proxycode);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.73.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RESPONSE_CODE (3),
-.BR libcurl-errors (3)
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.md b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.md
new file mode 100644
index 000000000..01113c740
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.md
@@ -0,0 +1,105 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PROXY_ERROR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RESPONSE_CODE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+ - libcurl-errors (3)
+---
+
+# NAME
+
+CURLINFO_PROXY_ERROR - get the detailed (SOCKS) proxy error
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+typedef enum {
+ CURLPX_OK,
+ CURLPX_BAD_ADDRESS_TYPE,
+ CURLPX_BAD_VERSION,
+ CURLPX_CLOSED,
+ CURLPX_GSSAPI,
+ CURLPX_GSSAPI_PERMSG,
+ CURLPX_GSSAPI_PROTECTION,
+ CURLPX_IDENTD,
+ CURLPX_IDENTD_DIFFER,
+ CURLPX_LONG_HOSTNAME,
+ CURLPX_LONG_PASSWD,
+ CURLPX_LONG_USER,
+ CURLPX_NO_AUTH,
+ CURLPX_RECV_ADDRESS,
+ CURLPX_RECV_AUTH,
+ CURLPX_RECV_CONNECT,
+ CURLPX_RECV_REQACK,
+ CURLPX_REPLY_ADDRESS_TYPE_NOT_SUPPORTED,
+ CURLPX_REPLY_COMMAND_NOT_SUPPORTED,
+ CURLPX_REPLY_CONNECTION_REFUSED,
+ CURLPX_REPLY_GENERAL_SERVER_FAILURE,
+ CURLPX_REPLY_HOST_UNREACHABLE,
+ CURLPX_REPLY_NETWORK_UNREACHABLE,
+ CURLPX_REPLY_NOT_ALLOWED,
+ CURLPX_REPLY_TTL_EXPIRED,
+ CURLPX_REPLY_UNASSIGNED,
+ CURLPX_REQUEST_FAILED,
+ CURLPX_RESOLVE_HOST,
+ CURLPX_SEND_AUTH,
+ CURLPX_SEND_CONNECT,
+ CURLPX_SEND_REQUEST,
+ CURLPX_UNKNOWN_FAIL,
+ CURLPX_UNKNOWN_MODE,
+ CURLPX_USER_REJECTED,
+ CURLPX_LAST /* never use */
+} CURLproxycode;
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_ERROR, long *detail);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive a detailed error code when the most recent
+transfer returned a **CURLE_PROXY** error. That error code matches the
+**CURLproxycode** set.
+
+The error code is zero (**CURLPX_OK**) if no response code was available.
+
+# PROTOCOLS
+
+All that can be done over SOCKS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://127.0.0.1");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_PROXY) {
+ long proxycode;
+ res = curl_easy_getinfo(curl, CURLINFO_PROXY_ERROR, &proxycode);
+ if(!res && proxycode)
+ printf("The detailed proxy error: %ld\n", proxycode);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.73.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3 b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3
deleted file mode 100644
index 3b266f75b..000000000
--- a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_PROXY_SSL_VERIFYRESULT 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certificate verification
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT,
- long *result);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the result of the certificate verification
-that was requested (using the \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP
-option. This is only used for HTTPS proxies.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- long verifyresult;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443");
- res = curl_easy_perform(curl);
- curl_easy_getinfo(curl, CURLINFO_PROXY_SSL_VERIFYRESULT, &verifyresult);
- printf("The peer verification said %s\\n", verifyresult?
- "fine":"BAAAD");
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SSL_VERIFYRESULT (3)
diff --git a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md
new file mode 100644
index 000000000..d97f5e78e
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_PROXY_SSL_VERIFYRESULT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SSL_VERIFYRESULT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_PROXY_SSL_VERIFYRESULT - get the result of the proxy certificate verification
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT,
+ long *result);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the result of the certificate verification
+that was requested (using the CURLOPT_PROXY_SSL_VERIFYPEER(3)
+option. This is only used for HTTPS proxies.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ long verifyresult;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443");
+ res = curl_easy_perform(curl);
+ if(res)
+ printf("error: %s\n", curl_easy_strerror(res));
+ curl_easy_getinfo(curl, CURLINFO_PROXY_SSL_VERIFYRESULT, &verifyresult);
+ printf("The peer verification said %s\n", verifyresult?
+ "fine" : "bad");
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md b/docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md
new file mode 100644
index 000000000..00454e752
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_QUEUE_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_STARTTRANSFER_TIME_T (3)
+ - CURLOPT_TIMEOUT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_QUEUE_TIME_T - time this transfer was queued
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_QUEUE_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the time, in microseconds, this
+transfer was held in a waiting queue before it started "for real". A transfer
+might be put in a queue if after getting started, it cannot create a new
+connection etc due to set conditions and limits imposed by the application.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t queue;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_QUEUE_TIME_T, &queue);
+ if(CURLE_OK == res) {
+ printf("Queued: %" CURL_FORMAT_CURL_OFF_T ".%06ld us", queue / 1000000,
+ (long)(queue % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 8.6.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3
deleted file mode 100644
index 034c00e2f..000000000
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_REDIRECT_COUNT 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_REDIRECT_COUNT \- get the number of redirects
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_COUNT,
- long *countp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the total number of redirections that were
-actually followed.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long redirects;
- curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redirects);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.9.7
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_REDIRECT_URL (3),
-.BR CURLOPT_FOLLOWLOCATION (3)
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md b/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md
new file mode 100644
index 000000000..aa75bdb22
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_REDIRECT_COUNT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_URL (3)
+ - CURLOPT_FOLLOWLOCATION (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_REDIRECT_COUNT - get the number of redirects
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_COUNT,
+ long *countp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the total number of redirections that were
+actually followed.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long redirects;
+ curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redirects);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.7
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3
deleted file mode 100644
index 7d3870acd..000000000
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_REDIRECT_TIME 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_REDIRECT_TIME \- get the time for all redirection steps
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME,
- double *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the total time, in seconds, it took for
-all redirection steps include name lookup, connect, pretransfer and transfer
-before final transaction was started. \fICURLINFO_REDIRECT_TIME(3)\fP contains
-the complete execution time for multiple redirections.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- double redirect;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &redirect);
- if(CURLE_OK == res) {
- printf("Time: %.1f", redirect);
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.9.7
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_REDIRECT_COUNT (3),
-.BR CURLINFO_REDIRECT_TIME_T (3),
-.BR CURLINFO_REDIRECT_URL (3)
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md
new file mode 100644
index 000000000..26d9af2a0
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_REDIRECT_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_COUNT (3)
+ - CURLINFO_REDIRECT_TIME_T (3)
+ - CURLINFO_REDIRECT_URL (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_REDIRECT_TIME - get the time for all redirection steps
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME,
+ double *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the total time, in seconds, it took for
+all redirection steps include name lookup, connect, pretransfer and transfer
+before final transaction was started. CURLINFO_REDIRECT_TIME(3) contains
+the complete execution time for multiple redirections.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ double redirect;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &redirect);
+ if(CURLE_OK == res) {
+ printf("Time: %.1f", redirect);
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.7
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3
deleted file mode 100644
index 444bbae77..000000000
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_REDIRECT_TIME_T 3 "28 Apr 2018" libcurl libcurl
-.SH NAME
-CURLINFO_REDIRECT_TIME_T \- get the time for all redirection steps
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the total time, in microseconds, it
-took for all redirection steps include name lookup, connect, pretransfer and
-transfer before final transaction was started.
-\fICURLINFO_REDIRECT_TIME_T(3)\fP holds the complete execution time for
-multiple redirections.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_off_t redirect;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME_T, &redirect);
- if(CURLE_OK == res) {
- printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", redirect / 1000000,
- (long)(redirect % 1000000));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_REDIRECT_COUNT (3),
-.BR CURLINFO_REDIRECT_TIME (3),
-.BR CURLINFO_REDIRECT_URL (3)
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md
new file mode 100644
index 000000000..f4ee71089
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_REDIRECT_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_COUNT (3)
+ - CURLINFO_REDIRECT_TIME (3)
+ - CURLINFO_REDIRECT_URL (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_REDIRECT_TIME_T - get the time for all redirection steps
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the total time, in microseconds, it
+took for all redirection steps include name lookup, connect, pretransfer and
+transfer before final transaction was started.
+CURLINFO_REDIRECT_TIME_T(3) holds the complete execution time for
+multiple redirections.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t redirect;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME_T, &redirect);
+ if(CURLE_OK == res) {
+ printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", redirect / 1000000,
+ (long)(redirect % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3 b/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3
deleted file mode 100644
index aa39803eb..000000000
--- a/docs/libcurl/opts/CURLINFO_REDIRECT_URL.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_REDIRECT_URL 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_REDIRECT_URL \- get the URL a redirect would go to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_URL, char **urlp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the URL a redirect \fIwould\fP
-take you to if you would enable \fICURLOPT_FOLLOWLOCATION(3)\fP. This can come
-handy if you think using the built-in libcurl redirect logic is not good enough
-for you but you would still prefer to avoid implementing all the magic of
-figuring out the new URL.
-
-This URL is also set if the \fICURLOPT_MAXREDIRS(3)\fP limit prevented a
-redirect to happen (since 7.54.1).
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- char *url = NULL;
- curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &url);
- if(url)
- printf("Redirect to: %s\\n", url);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.18.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_REDIRECT_COUNT (3),
-.BR CURLINFO_REDIRECT_TIME_T (3),
-.BR CURLOPT_FOLLOWLOCATION (3)
diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_URL.md b/docs/libcurl/opts/CURLINFO_REDIRECT_URL.md
new file mode 100644
index 000000000..8d7fc5c10
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_REDIRECT_URL.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_REDIRECT_URL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_COUNT (3)
+ - CURLINFO_REDIRECT_TIME_T (3)
+ - CURLOPT_FOLLOWLOCATION (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_REDIRECT_URL - get the URL a redirect would go to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REDIRECT_URL, char **urlp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a char pointer to receive the URL a redirect *would*
+take you to if you would enable CURLOPT_FOLLOWLOCATION(3). This can come
+handy if you think using the built-in libcurl redirect logic is not good enough
+for you but you would still prefer to avoid implementing all the magic of
+figuring out the new URL.
+
+This URL is also set if the CURLOPT_MAXREDIRS(3) limit prevented a
+redirect to happen (since 7.54.1).
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ char *url = NULL;
+ curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &url);
+ if(url)
+ printf("Redirect to: %s\n", url);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.18.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_REFERER.3 b/docs/libcurl/opts/CURLINFO_REFERER.3
deleted file mode 100644
index fe4afd0b7..000000000
--- a/docs/libcurl/opts/CURLINFO_REFERER.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_REFERER 3 "11 Feb 2021" libcurl libcurl
-.SH NAME
-CURLINFO_REFERER \- get the referrer header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REFERER, char **hdrp);
-.fi
-.SH DESCRIPTION
-Pass in a pointer to a char pointer and get the referrer header.
-
-The \fBhdrp\fP pointer is NULL or points to private memory you MUST NOT free -
-it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding
-CURL handle.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.org/referrer");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- char *hdr = NULL;
- curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr);
- if(hdr)
- printf("Referrer header: %s\\n", hdr);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.76.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_header (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_REFERER (3)
diff --git a/docs/libcurl/opts/CURLINFO_REFERER.md b/docs/libcurl/opts/CURLINFO_REFERER.md
new file mode 100644
index 000000000..fabc652a7
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_REFERER.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_REFERER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_REFERER (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_header (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_REFERER - get the used referrer request header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REFERER, char **hdrp);
+~~~
+
+# DESCRIPTION
+
+Pass in a pointer to a char pointer and get the referrer header used in the
+most recent request.
+
+The **hdrp** pointer is NULL or points to private memory you MUST NOT free -
+it gets freed when you call curl_easy_cleanup(3) on the corresponding
+CURL handle.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.org/referrer");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ char *hdr = NULL;
+ curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr);
+ if(hdr)
+ printf("Referrer header: %s\n", hdr);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.76.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3 b/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3
deleted file mode 100644
index fca67a9b8..000000000
--- a/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_REQUEST_SIZE 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_REQUEST_SIZE \- get size of sent request
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REQUEST_SIZE, long *sizep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the total size of the issued
-requests. This is so far only for HTTP requests. Note that this may be more
-than one request if \fICURLOPT_FOLLOWLOCATION(3)\fP is enabled.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long req;
- res = curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &req);
- if(!res)
- printf("Request size: %ld bytes\\n", req);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_HEADER_SIZE (3),
-.BR CURLINFO_SIZE_DOWNLOAD_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md b/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md
new file mode 100644
index 000000000..444f4ec23
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_REQUEST_SIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_HEADER_SIZE (3)
+ - CURLINFO_SIZE_DOWNLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_REQUEST_SIZE - get size of sent request
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_REQUEST_SIZE, long *sizep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the total size of the issued
+requests. This is so far only for HTTP requests. Note that this may be more
+than one request if CURLOPT_FOLLOWLOCATION(3) is enabled.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long req;
+ res = curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &req);
+ if(!res)
+ printf("Request size: %ld bytes\n", req);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3 b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3
deleted file mode 100644
index 9cda1030f..000000000
--- a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_RESPONSE_CODE 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_RESPONSE_CODE \- get the last response code
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RESPONSE_CODE, long *codep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the last received HTTP, FTP, SMTP or LDAP
-(OpenLDAP only) response code. This option was previously known as
-CURLINFO_HTTP_CODE in libcurl 7.10.7 and earlier. The stored value is zero if
-no server response code has been received.
-
-Note that a proxy's CONNECT response should be read with
-\fICURLINFO_HTTP_CONNECTCODE(3)\fP and not this.
-.SH PROTOCOLS
-HTTP, FTP, SMTP and LDAP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long response_code;
- curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.8. CURLINFO_HTTP_CODE was added in 7.4.1.
-Support for SMTP responses added in 7.25.0, for OpenLDAP in 7.81.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_HTTP_CONNECTCODE (3)
diff --git a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md
new file mode 100644
index 000000000..43cf8378d
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_RESPONSE_CODE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_HTTP_CONNECTCODE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_RESPONSE_CODE - get the last response code
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RESPONSE_CODE, long *codep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the last received HTTP, FTP, SMTP or LDAP
+(OpenLDAP only) response code. This option was previously known as
+CURLINFO_HTTP_CODE in libcurl 7.10.7 and earlier. The stored value is zero if
+no server response code has been received.
+
+Note that a proxy's CONNECT response should be read with
+CURLINFO_HTTP_CONNECTCODE(3) and not this.
+
+# PROTOCOLS
+
+HTTP, FTP, SMTP and LDAP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long response_code;
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.8. CURLINFO_HTTP_CODE was added in 7.4.1.
+Support for SMTP responses added in 7.25.0, for OpenLDAP in 7.81.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3 b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3
deleted file mode 100644
index 2c761d731..000000000
--- a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_RETRY_AFTER 3 "6 Aug 2019" libcurl libcurl
-.SH NAME
-CURLINFO_RETRY_AFTER \- returns the Retry-After retry delay
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RETRY_AFTER,
- curl_off_t *retry);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t variable to receive the number of seconds the
-HTTP server suggests the client should wait until the next request is
-issued. The information from the "Retry-After:" header.
-
-While the HTTP header might contain a fixed date string, the
-\fICURLINFO_RETRY_AFTER(3)\fP always returns the number of seconds to wait -
-or zero if there was no header or the header could not be parsed.
-.SH DEFAULT
-Returns zero delay if there was no header.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- curl_off_t wait = 0;
- curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &wait);
- if(wait)
- printf("Wait for %" CURL_FORMAT_CURL_OFF_T " seconds\\n", wait);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.66.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_header (3),
-.BR CURLOPT_HEADERFUNCTION (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md
new file mode 100644
index 000000000..adc120077
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_RETRY_AFTER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERFUNCTION (3)
+ - CURLOPT_STDERR (3)
+ - curl_easy_header (3)
+---
+
+# NAME
+
+CURLINFO_RETRY_AFTER - returns the Retry-After retry delay
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RETRY_AFTER,
+ curl_off_t *retry);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t variable to receive the number of seconds the
+HTTP server suggests the client should wait until the next request is
+issued. The information from the "Retry-After:" header.
+
+While the HTTP header might contain a fixed date string, the
+CURLINFO_RETRY_AFTER(3) always returns the number of seconds to wait -
+or zero if there was no header or the header could not be parsed.
+
+# DEFAULT
+
+Returns zero delay if there was no header.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ curl_off_t wait = 0;
+ curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &wait);
+ if(wait)
+ printf("Wait for %" CURL_FORMAT_CURL_OFF_T " seconds\n", wait);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.66.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3 b/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3
deleted file mode 100644
index caad1935e..000000000
--- a/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_RTSP_CLIENT_CSEQ 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_RTSP_CLIENT_CSEQ \- get the next RTSP client CSeq
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CLIENT_CSEQ,
- long *cseq);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the next CSeq that is expected to be used
-by the application.
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long cseq;
- curl_easy_getinfo(curl, CURLINFO_RTSP_CLIENT_CSEQ, &cseq);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RTSP_CSEQ_RECV (3),
-.BR CURLINFO_RTSP_SERVER_CSEQ (3)
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md b/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md
new file mode 100644
index 000000000..8b515b427
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_RTSP_CLIENT_CSEQ
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RTSP_CSEQ_RECV (3)
+ - CURLINFO_RTSP_SERVER_CSEQ (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_RTSP_CLIENT_CSEQ - get the next RTSP client CSeq
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CLIENT_CSEQ,
+ long *cseq);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the next CSeq that is expected to be used
+by the application.
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long cseq;
+ curl_easy_getinfo(curl, CURLINFO_RTSP_CLIENT_CSEQ, &cseq);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3 b/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3
deleted file mode 100644
index 5331de260..000000000
--- a/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_RTSP_CSEQ_RECV 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_RTSP_CSEQ_RECV \- get the recently received CSeq
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CSEQ_RECV, long *cseq);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the most recently received CSeq from the
-server. If your application encounters a \fICURLE_RTSP_CSEQ_ERROR\fP then you
-may wish to troubleshoot and/or fix the CSeq mismatch by peeking at this
-value.
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long cseq;
- curl_easy_getinfo(curl, CURLINFO_RTSP_CSEQ_RECV, &cseq);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RTSP_SERVER_CSEQ (3)
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md b/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md
new file mode 100644
index 000000000..9eb813aa4
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_RTSP_CSEQ_RECV
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RTSP_SERVER_CSEQ (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_RTSP_CSEQ_RECV - get the recently received CSeq
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_CSEQ_RECV, long *cseq);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the most recently received CSeq from the
+server. If your application encounters a *CURLE_RTSP_CSEQ_ERROR* then you
+may wish to troubleshoot and/or fix the CSeq mismatch by peeking at this
+value.
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long cseq;
+ curl_easy_getinfo(curl, CURLINFO_RTSP_CSEQ_RECV, &cseq);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3 b/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3
deleted file mode 100644
index 478b25836..000000000
--- a/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_RTSP_SERVER_CSEQ 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_RTSP_SERVER_CSEQ \- get the next RTSP server CSeq
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SERVER_CSEQ,
- long *cseq);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a long to receive the next CSeq that is expected to be used
-by the application.
-
-Listening for server initiated requests is not implemented!
-
-Applications wishing to resume an RTSP session on another connection should
-retrieve this info before closing the active connection.
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- long cseq;
- curl_easy_getinfo(curl, CURLINFO_RTSP_SERVER_CSEQ, &cseq);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RTSP_CSEQ_RECV (3)
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md b/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md
new file mode 100644
index 000000000..7826f8a3c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_RTSP_SERVER_CSEQ
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RTSP_CSEQ_RECV (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_RTSP_SERVER_CSEQ - get the next RTSP server CSeq
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SERVER_CSEQ,
+ long *cseq);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the next CSeq that is expected to be used
+by the application.
+
+Listening for server initiated requests is not implemented!
+
+Applications wishing to resume an RTSP session on another connection should
+retrieve this info before closing the active connection.
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ long cseq;
+ curl_easy_getinfo(curl, CURLINFO_RTSP_SERVER_CSEQ, &cseq);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3 b/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3
deleted file mode 100644
index 375879273..000000000
--- a/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_RTSP_SESSION_ID 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_RTSP_SESSION_ID \- get RTSP session ID
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SESSION_ID, char **id);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a char pointer to receive a pointer to a string holding the
-most recent RTSP Session ID.
-
-Applications wishing to resume an RTSP session on another connection should
-retrieve this info before closing the active connection.
-
-The \fBid\fP pointer is NULL or points to private memory. You MUST NOT free -
-it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the corresponding
-CURL handle.
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- char *id;
- curl_easy_getinfo(curl, CURLINFO_RTSP_SESSION_ID, &id);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_RTSP_CSEQ_RECV (3)
diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md b/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md
new file mode 100644
index 000000000..402a122f8
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_RTSP_SESSION_ID
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RTSP_CSEQ_RECV (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_RTSP_SESSION_ID - get RTSP session ID
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_RTSP_SESSION_ID, char **id);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a char pointer to receive a pointer to a string holding the
+most recent RTSP Session ID.
+
+Applications wishing to resume an RTSP session on another connection should
+retrieve this info before closing the active connection.
+
+The **id** pointer is NULL or points to private memory. You MUST NOT free -
+it gets freed when you call curl_easy_cleanup(3) on the corresponding
+CURL handle.
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ char *id;
+ curl_easy_getinfo(curl, CURLINFO_RTSP_SESSION_ID, &id);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SCHEME.3 b/docs/libcurl/opts/CURLINFO_SCHEME.3
deleted file mode 100644
index a736dd81c..000000000
--- a/docs/libcurl/opts/CURLINFO_SCHEME.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SCHEME 3 "23 November 2016" libcurl libcurl
-.SH NAME
-CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the connection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);
-.fi
-.SH DESCRIPTION
-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.
-
-The \fBscheme\fP pointer is NULL or points to private memory. You MUST NOT
-free - it gets freed when you call \fIcurl_easy_cleanup(3)\fP on the
-corresponding CURL handle.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- if(res == CURLE_OK) {
- char *scheme = NULL;
- curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
- if(scheme)
- printf("scheme: %s\\n", scheme); /* scheme: HTTP */
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_EFFECTIVE_URL (3),
-.BR CURLINFO_PROTOCOL (3),
-.BR CURLINFO_RESPONSE_CODE (3)
diff --git a/docs/libcurl/opts/CURLINFO_SCHEME.md b/docs/libcurl/opts/CURLINFO_SCHEME.md
new file mode 100644
index 000000000..db567fc98
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SCHEME.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SCHEME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_EFFECTIVE_URL (3)
+ - CURLINFO_PROTOCOL (3)
+ - CURLINFO_RESPONSE_CODE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SCHEME - get the URL scheme (sometimes called protocol) used in the connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);
+~~~
+
+# DESCRIPTION
+
+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 **handle**.
+
+The **scheme** pointer is NULL or points to private memory. You MUST NOT
+free - it gets freed when you call curl_easy_cleanup(3) on the
+corresponding CURL handle.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res == CURLE_OK) {
+ char *scheme = NULL;
+ curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme);
+ if(scheme)
+ printf("scheme: %s\n", scheme); /* scheme: HTTP */
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3 b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3
deleted file mode 100644
index c3a2f2641..000000000
--- a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SIZE_DOWNLOAD 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_SIZE_DOWNLOAD \- get the number of downloaded bytes
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD, double *dlp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the total amount of bytes that were
-downloaded. The amount is only for the latest transfer and gets reset again
-for each new transfer. This counts actual payload data, what's also commonly
-called body. All meta and header data is excluded and not included in this
-number.
-
-\fICURLINFO_SIZE_DOWNLOAD_T(3)\fP is a newer replacement that returns a more
-sensible variable type.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* check the size */
- double dl;
- res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dl);
- if(!res) {
- printf("Downloaded %.0f bytes\\n", cl);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1. Deprecated since 7.55.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SIZE_DOWNLOAD_T (3),
-.BR CURLINFO_SIZE_UPLOAD_T (3),
-.BR CURLOPT_MAXFILESIZE (3)
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md
new file mode 100644
index 000000000..ff19908cf
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SIZE_DOWNLOAD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SIZE_DOWNLOAD_T (3)
+ - CURLINFO_SIZE_UPLOAD_T (3)
+ - CURLOPT_MAXFILESIZE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SIZE_DOWNLOAD - get the number of downloaded bytes
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD, double *dlp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the total amount of bytes that were
+downloaded. The amount is only for the latest transfer and gets reset again
+for each new transfer. This counts actual payload data, what's also commonly
+called body. All meta and header data is excluded and not included in this
+number.
+
+CURLINFO_SIZE_DOWNLOAD_T(3) is a newer replacement that returns a more
+sensible variable type.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* check the size */
+ double dl;
+ res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dl);
+ if(!res) {
+ printf("Downloaded %.0f bytes\n", dl);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1. Deprecated since 7.55.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3
deleted file mode 100644
index c3bb7f195..000000000
--- a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SIZE_DOWNLOAD_T 3 "25 May 2017" libcurl libcurl
-.SH NAME
-CURLINFO_SIZE_DOWNLOAD_T \- get the number of downloaded bytes
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD_T,
- curl_off_t *dlp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the total amount of bytes that
-were downloaded. The amount is only for the latest transfer and gets reset
-again for each new transfer. This counts actual payload data, what's also
-commonly called body. All meta and header data is excluded from this amount.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- /* check the size */
- curl_off_t dl;
- res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &dl);
- if(!res) {
- printf("Downloaded %" CURL_FORMAT_CURL_OFF_T " bytes\\n", dl);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SIZE_DOWNLOAD (3),
-.BR CURLINFO_SIZE_UPLOAD_T (3),
-.BR CURLOPT_MAXFILESIZE (3)
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md
new file mode 100644
index 000000000..f5468db9d
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SIZE_DOWNLOAD_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SIZE_DOWNLOAD (3)
+ - CURLINFO_SIZE_UPLOAD_T (3)
+ - CURLOPT_MAXFILESIZE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SIZE_DOWNLOAD_T - get the number of downloaded bytes
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD_T,
+ curl_off_t *dlp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the total amount of bytes that
+were downloaded. The amount is only for the latest transfer and gets reset
+again for each new transfer. This counts actual payload data, what's also
+commonly called body. All meta and header data is excluded from this amount.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ /* check the size */
+ curl_off_t dl;
+ res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &dl);
+ if(!res) {
+ printf("Downloaded %" CURL_FORMAT_CURL_OFF_T " bytes\n", dl);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3 b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3
deleted file mode 100644
index 89228b011..000000000
--- a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SIZE_UPLOAD 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_SIZE_UPLOAD \- get the number of uploaded bytes
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD,
- double *uploadp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the total amount of bytes that were
-uploaded.
-
-\fICURLINFO_SIZE_UPLOAD_T(3)\fP is a newer replacement that returns a more
-sensible variable type.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- double ul;
- res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &ul);
- if(!res) {
- printf("Uploaded %.0f bytes\\n", ul);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1. Deprecated since 7.55.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SIZE_DOWNLOAD_T (3),
-.BR CURLINFO_SIZE_UPLOAD_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md
new file mode 100644
index 000000000..175fe718d
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SIZE_UPLOAD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SIZE_DOWNLOAD_T (3)
+ - CURLINFO_SIZE_UPLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SIZE_UPLOAD - get the number of uploaded bytes
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD,
+ double *uploadp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the total amount of bytes that were
+uploaded.
+
+CURLINFO_SIZE_UPLOAD_T(3) is a newer replacement that returns a more
+sensible variable type.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ double ul;
+ res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &ul);
+ if(!res) {
+ printf("Uploaded %.0f bytes\n", ul);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1. Deprecated since 7.55.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3
deleted file mode 100644
index ea77bd7cc..000000000
--- a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SIZE_UPLOAD_T 3 "25 May 2017" libcurl libcurl
-.SH NAME
-CURLINFO_SIZE_UPLOAD_T \- get the number of uploaded bytes
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD_T,
- curl_off_t *uploadp);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the total amount of bytes that
-were uploaded.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- curl_off_t ul;
- res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &ul);
- if(!res) {
- printf("Uploaded %" CURL_FORMAT_CURL_OFF_T " bytes\\n", ul);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SIZE_DOWNLOAD_T (3),
-.BR CURLINFO_SIZE_UPLOAD (3)
-
diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md
new file mode 100644
index 000000000..29874f9fd
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SIZE_UPLOAD_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SIZE_DOWNLOAD_T (3)
+ - CURLINFO_SIZE_UPLOAD (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SIZE_UPLOAD_T - get the number of uploaded bytes
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD_T,
+ curl_off_t *uploadp);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the total amount of bytes that
+were uploaded.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ curl_off_t ul;
+ res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &ul);
+ if(!res) {
+ printf("Uploaded %" CURL_FORMAT_CURL_OFF_T " bytes\n", ul);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3 b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3
deleted file mode 100644
index c79e48a71..000000000
--- a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SPEED_DOWNLOAD 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_SPEED_DOWNLOAD \- get download speed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD,
- double *speed);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the average download speed that curl
-measured for the complete download. Measured in bytes/second.
-
-\fICURLINFO_SPEED_DOWNLOAD_T(3)\fP is a newer replacement that returns a more
-sensible variable type.
-.SH PROTOCOLS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- double speed;
- res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed);
- if(!res) {
- printf("Download speed %.0f bytes/sec\\n", speed);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1. Deprecated since 7.55.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SIZE_UPLOAD_T (3),
-.BR CURLINFO_SPEED_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md
new file mode 100644
index 000000000..fe0766939
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SPEED_DOWNLOAD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SIZE_UPLOAD_T (3)
+ - CURLINFO_SPEED_UPLOAD (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SPEED_DOWNLOAD - get download speed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD,
+ double *speed);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the average download speed that curl
+measured for the complete download. Measured in bytes/second.
+
+CURLINFO_SPEED_DOWNLOAD_T(3) is a newer replacement that returns a more
+sensible variable type.
+
+# PROTOCOLS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ double speed;
+ res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed);
+ if(!res) {
+ printf("Download speed %.0f bytes/sec\n", speed);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1. Deprecated since 7.55.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3
deleted file mode 100644
index 9d308c6bf..000000000
--- a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SPEED_DOWNLOAD_T 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_SPEED_DOWNLOAD_T \- get download speed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD_T,
- curl_off_t *speed);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the average download speed
-that curl measured for the complete download. Measured in bytes/second.
-.SH PROTOCOLS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- curl_off_t speed;
- res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD_T, &speed);
- if(!res) {
- printf("Download speed %" CURL_FORMAT_CURL_OFF_T " bytes/sec\\n", speed);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SIZE_UPLOAD_T (3),
-.BR CURLINFO_SPEED_UPLOAD_T (3)
-
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md
new file mode 100644
index 000000000..c8bc2f867
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SPEED_DOWNLOAD_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SIZE_UPLOAD_T (3)
+ - CURLINFO_SPEED_UPLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SPEED_DOWNLOAD_T - get download speed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD_T,
+ curl_off_t *speed);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the average download speed
+that curl measured for the complete download. Measured in bytes/second.
+
+# PROTOCOLS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ curl_off_t speed;
+ res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD_T, &speed);
+ if(!res) {
+ printf("Download speed %" CURL_FORMAT_CURL_OFF_T " bytes/sec\n",
+ speed);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3 b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3
deleted file mode 100644
index 814a4fa8e..000000000
--- a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SPEED_UPLOAD 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_SPEED_UPLOAD \- get upload speed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD, double *speed);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the average upload speed that curl
-measured for the complete upload. Measured in bytes/second.
-
-\fICURLINFO_SPEED_UPLOAD_T(3)\fP is a newer replacement that returns a more
-sensible variable type.
-.SH PROTOCOLS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- double speed;
- res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed);
- if(!res) {
- printf("Upload speed %.0f bytes/sec\\n", speed);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1. Deprecated since 7.55.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SPEED_DOWNLOAD_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md
new file mode 100644
index 000000000..11ce92923
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SPEED_UPLOAD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SPEED_DOWNLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SPEED_UPLOAD - get upload speed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD, double *speed);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the average upload speed that curl
+measured for the complete upload. Measured in bytes/second.
+
+CURLINFO_SPEED_UPLOAD_T(3) is a newer replacement that returns a more
+sensible variable type.
+
+# PROTOCOLS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ double speed;
+ res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed);
+ if(!res) {
+ printf("Upload speed %.0f bytes/sec\n", speed);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1. Deprecated since 7.55.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3 b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3
deleted file mode 100644
index eff8554c0..000000000
--- a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SPEED_UPLOAD_T 3 "25 May 2017" libcurl libcurl
-.SH NAME
-CURLINFO_SPEED_UPLOAD_T \- get upload speed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD_T,
- curl_off_t *speed);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the average upload speed that
-curl measured for the complete upload. Measured in bytes/second.
-.SH PROTOCOLS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- curl_off_t speed;
- res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed);
- if(!res) {
- printf("Upload speed %" CURL_FORMAT_CURL_OFF_T " bytes/sec\\n", speed);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_SPEED_DOWNLOAD_T (3)
diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md
new file mode 100644
index 000000000..178e9a526
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SPEED_UPLOAD_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SPEED_DOWNLOAD_T (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SPEED_UPLOAD_T - get upload speed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD_T,
+ curl_off_t *speed);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the average upload speed that
+curl measured for the complete upload. Measured in bytes/second.
+
+# PROTOCOLS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ curl_off_t speed;
+ res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed);
+ if(!res) {
+ printf("Upload speed %" CURL_FORMAT_CURL_OFF_T " bytes/sec\n", speed);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3 b/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3
deleted file mode 100644
index 0375e79a4..000000000
--- a/docs/libcurl/opts/CURLINFO_SSL_ENGINES.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SSL_ENGINES 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_SSL_ENGINES \- get an slist of OpenSSL crypto-engines
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_ENGINES,
- struct curl_slist **engine_list);
-.fi
-.SH DESCRIPTION
-Pass the address of a 'struct curl_slist *' to receive a linked-list of
-OpenSSL crypto-engines supported. Note that engines are normally implemented
-in separate dynamic libraries. Hence not all the returned engines may be
-available at runtime. \fBNOTE:\fP you must call \fIcurl_slist_free_all(3)\fP
-on the list pointer once you are done with it, as libcurl does not free this
-data for you.
-.SH PROTOCOLS
-All TLS based ones.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- struct curl_slist *engines;
- res = curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
- if((res == CURLE_OK) && engines) {
- /* we have a list, free it when done using it */
- curl_slist_free_all(engines);
- }
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.12.3. Available in OpenSSL builds with "engine" support.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLOPT_SSLENGINE (3)
diff --git a/docs/libcurl/opts/CURLINFO_SSL_ENGINES.md b/docs/libcurl/opts/CURLINFO_SSL_ENGINES.md
new file mode 100644
index 000000000..9dbb0a1d1
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SSL_ENGINES.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SSL_ENGINES
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSLENGINE (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SSL_ENGINES - get an slist of OpenSSL crypto-engines
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_ENGINES,
+ struct curl_slist **engine_list);
+~~~
+
+# DESCRIPTION
+
+Pass the address of a 'struct curl_slist *' to receive a linked-list of
+OpenSSL crypto-engines supported. Note that engines are normally implemented
+in separate dynamic libraries. Hence not all the returned engines may be
+available at runtime. **NOTE:** you must call curl_slist_free_all(3)
+on the list pointer once you are done with it, as libcurl does not free this
+data for you.
+
+# PROTOCOLS
+
+All TLS based ones.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ struct curl_slist *engines;
+ res = curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
+ if((res == CURLE_OK) && engines) {
+ /* we have a list, free it when done using it */
+ curl_slist_free_all(engines);
+ }
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.12.3. Available in OpenSSL builds with "engine" support.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3 b/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3
deleted file mode 100644
index d66d7df60..000000000
--- a/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_SSL_VERIFYRESULT 3 "1 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_SSL_VERIFYRESULT \- get the result of the certificate verification
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_VERIFYRESULT,
- long *result);
-.fi
-.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).
-
-0 is a positive result. Non-zero is an error.
-.SH PROTOCOLS
-All using TLS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- long verifyresult;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, &verifyresult);
- printf("The peer verification said %s\\n", verifyresult?
- "BAAAD":"fine");
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.5. Only set by the OpenSSL/libressl/boringssl and GnuTLS backends.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_PROXY_SSL_VERIFYRESULT (3)
diff --git a/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md b/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md
new file mode 100644
index 000000000..fdc38f016
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_SSL_VERIFYRESULT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PROXY_SSL_VERIFYRESULT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_SSL_VERIFYRESULT - get the result of the certificate verification
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_VERIFYRESULT,
+ long *result);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a long to receive the result of the server SSL certificate
+verification that was requested (using the CURLOPT_SSL_VERIFYPEER(3)
+option).
+
+0 is a positive result. Non-zero is an error.
+
+# PROTOCOLS
+
+All using TLS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ long verifyresult;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res)
+ printf("error: %s\n", curl_easy_strerror(res));
+ curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, &verifyresult);
+ printf("The peer verification said %s\n", verifyresult?
+ "BAAAD":"fine");
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.5. Only set by the OpenSSL/libressl/boringssl and GnuTLS backends.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3 b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3
deleted file mode 100644
index 0c1793232..000000000
--- a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_STARTTRANSFER_TIME 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_STARTTRANSFER_TIME \- get the time until the first byte is received
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME,
- double *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the time, in seconds, it took from the
-start until the first byte is received by libcurl. This includes
-\fICURLINFO_PRETRANSFER_TIME(3)\fP and also the time the server needs to
-calculate the result.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- double start;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &start);
- if(CURLE_OK == res) {
- printf("Time: %.1f", start);
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.9.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_STARTTRANSFER_TIME_T (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md
new file mode 100644
index 000000000..d7c1f0884
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_STARTTRANSFER_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_STARTTRANSFER_TIME_T (3)
+ - CURLOPT_TIMEOUT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_STARTTRANSFER_TIME - get the time until the first byte is received
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME,
+ double *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the time, in seconds, it took from the
+start until the first byte is received by libcurl. This includes
+CURLINFO_PRETRANSFER_TIME(3) and also the time the server needs to
+calculate the result.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ double start;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &start);
+ if(CURLE_OK == res) {
+ printf("Time: %.1f", start);
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3 b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3
deleted file mode 100644
index 3ad2d525f..000000000
--- a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_STARTTRANSFER_TIME_T 3 "28 Apr 2018" libcurl libcurl
-.SH NAME
-CURLINFO_STARTTRANSFER_TIME_T \- get the time until the first byte is received
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the time, in microseconds,
-it took from the
-start until the first byte is received by libcurl. This includes
-\fICURLINFO_PRETRANSFER_TIME_T(3)\fP and also the time the server needs to
-calculate the result.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_off_t start;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME_T, &start);
- if(CURLE_OK == res) {
- printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", start / 1000000,
- (long)(start % 1000000));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_STARTTRANSFER_TIME (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md
new file mode 100644
index 000000000..481c7f5bd
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_STARTTRANSFER_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_STARTTRANSFER_TIME (3)
+ - CURLOPT_TIMEOUT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_STARTTRANSFER_TIME_T - get the time until the first byte is received
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_STARTTRANSFER_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the time, in microseconds,
+it took from the
+start until the first byte is received by libcurl. This includes
+CURLINFO_PRETRANSFER_TIME_T(3) and also the time the server needs to
+calculate the result.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t start;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME_T, &start);
+ if(CURLE_OK == res) {
+ printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", start / 1000000,
+ (long)(start % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_TLS_SESSION.3 b/docs/libcurl/opts/CURLINFO_TLS_SESSION.3
deleted file mode 100644
index 88166b099..000000000
--- a/docs/libcurl/opts/CURLINFO_TLS_SESSION.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_TLS_SESSION 3 "12 Sep 2015" libcurl libcurl
-.SH NAME
-CURLINFO_TLS_SESSION \- get TLS session info
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TLS_SESSION,
- struct curl_tlssessioninfo **session);
-.SH DESCRIPTION
-\fBThis option has been superseded\fP by \fICURLINFO_TLS_SSL_PTR(3)\fP which
-was added in 7.48.0. The only reason you would use this option instead is if
-you could be using a version of libcurl earlier than 7.48.0.
-
-This option is exactly the same as \fICURLINFO_TLS_SSL_PTR(3)\fP except in the
-case of OpenSSL. If the session \fIbackend\fP is CURLSSLBACKEND_OPENSSL the
-session \fIinternals\fP pointer varies depending on the option:
-
-\fICURLINFO_TLS_SESSION(3)\fP OpenSSL session \fIinternals\fP is \fBSSL_CTX *\fP.
-
-\fICURLINFO_TLS_SSL_PTR(3)\fP OpenSSL session \fIinternals\fP is \fBSSL *\fP.
-
-You can obtain an \fBSSL_CTX\fP pointer from an SSL pointer using OpenSSL
-function \fISSL_get_SSL_CTX(3)\fP. Therefore unless you need compatibility
-with older versions of libcurl use \fICURLINFO_TLS_SSL_PTR(3)\fP. Refer to
-that document for more information.
-.SH PROTOCOLS
-All TLS-based
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- struct curl_tlssessioninfo *tls;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- res = curl_easy_perform(curl);
- curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &tls);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.34.0. Deprecated since 7.48.0 and supported OpenSSL, GnuTLS, and
-NSS only up until this version was released.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_TLS_SSL_PTR (3)
diff --git a/docs/libcurl/opts/CURLINFO_TLS_SESSION.md b/docs/libcurl/opts/CURLINFO_TLS_SESSION.md
new file mode 100644
index 000000000..98cc2d67c
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_TLS_SESSION.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_TLS_SESSION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_TLS_SSL_PTR (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_TLS_SESSION - get TLS session info
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TLS_SESSION,
+ struct curl_tlssessioninfo **session);
+~~~
+
+# DESCRIPTION
+
+**This option has been superseded** by CURLINFO_TLS_SSL_PTR(3) which
+was added in 7.48.0. The only reason you would use this option instead is if
+you could be using a version of libcurl earlier than 7.48.0.
+
+This option is exactly the same as CURLINFO_TLS_SSL_PTR(3) except in the
+case of OpenSSL. If the session *backend* is CURLSSLBACKEND_OPENSSL the
+session *internals* pointer varies depending on the option:
+
+CURLINFO_TLS_SESSION(3) OpenSSL session *internals* is **SSL_CTX ***.
+
+CURLINFO_TLS_SSL_PTR(3) OpenSSL session *internals* is **SSL ***.
+
+You can obtain an **SSL_CTX** pointer from an SSL pointer using OpenSSL
+function *SSL_get_SSL_CTX(3)*. Therefore unless you need compatibility
+with older versions of libcurl use CURLINFO_TLS_SSL_PTR(3). Refer to
+that document for more information.
+
+# PROTOCOLS
+
+All TLS-based
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ struct curl_tlssessioninfo *tls;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(res)
+ printf("error: %s\n", curl_easy_strerror(res));
+ curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &tls);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.34.0. Deprecated since 7.48.0 and supported OpenSSL, GnuTLS, and
+NSS only up until this version was released.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3 b/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3
deleted file mode 100644
index 53d084d48..000000000
--- a/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.3
+++ /dev/null
@@ -1,165 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_TLS_SSL_PTR 3 "23 Feb 2016" libcurl libcurl
-.SH NAME
-CURLINFO_TLS_SESSION, CURLINFO_TLS_SSL_PTR \- get TLS session info
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TLS_SSL_PTR,
- struct curl_tlssessioninfo **session);
-
-/* if you need compatibility with libcurl < 7.48.0 use
- CURLINFO_TLS_SESSION instead: */
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TLS_SESSION,
- struct curl_tlssessioninfo **session);
-.SH DESCRIPTION
-Pass a pointer to a \fIstruct curl_tlssessioninfo *\fP. The pointer is
-initialized to refer to a \fIstruct curl_tlssessioninfo *\fP that contains an
-enum indicating the SSL library used for the handshake and a pointer to the
-respective internal TLS session structure of this underlying SSL library.
-
-This option may be useful for example to extract certificate information in a
-format convenient for further processing, such as manual validation. Refer to
-the \fBLIMITATIONS\fP section.
-
-.nf
-struct curl_tlssessioninfo {
- curl_sslbackend backend;
- void *internals;
-};
-.fi
-
-The \fIbackend\fP struct member is one of the defines in the CURLSSLBACKEND_*
-series: CURLSSLBACKEND_NONE (when built without TLS support),
-CURLSSLBACKEND_WOLFSSL, CURLSSLBACKEND_SECURETRANSPORT, CURLSSLBACKEND_GNUTLS,
-CURLSSLBACKEND_MBEDTLS, CURLSSLBACKEND_NSS, CURLSSLBACKEND_OPENSSL,
-CURLSSLBACKEND_SCHANNEL or CURLSSLBACKEND_MESALINK. (Note that the OpenSSL
-forks are all reported as just OpenSSL here.)
-
-The \fIinternals\fP struct member points to a TLS library specific pointer for
-the active ("in use") SSL connection, with the following underlying types:
-.RS
-.IP GnuTLS
-\fBgnutls_session_t\fP
-.IP NSS
-\fBPRFileDesc *\fP
-.IP OpenSSL
-\fICURLINFO_TLS_SESSION(3)\fP: \fBSSL_CTX *\fP
-
-\fICURLINFO_TLS_SSL_PTR(3)\fP: \fBSSL *\fP
-.RE
-Since 7.48.0 the \fIinternals\fP member can point to these other SSL backends
-as well:
-.RS
-.IP mbedTLS
-\fBmbedTLS_ssl_context *\fP
-.IP "Secure Channel"
-\fBCtxtHandle *\fP
-.IP "Secure Transport"
-\fBSSLContext *\fP
-.IP "wolfSSL"
-\fBSSL *\fP
-.RE
-
-If the \fIinternals\fP pointer is NULL then either the SSL backend is not
-supported, an SSL session has not yet been established or the connection is no
-longer associated with the easy handle (e.g. \fIcurl_easy_perform(3)\fP has
-returned).
-.SH LIMITATIONS
-This option has some limitations that could make it unsafe when it comes to
-the manual verification of certificates.
-
-This option only retrieves the first in-use SSL session pointer for your easy
-handle, however your easy handle may have more than one in-use SSL session if
-using FTP over SSL. That is because the FTP protocol has a control channel and
-a data channel and one or both may be over SSL. Currently there is no way to
-retrieve a second in-use SSL session associated with an easy handle.
-
-This option has not been thoroughly tested with clear text protocols that can
-be upgraded/downgraded to/from SSL: FTP, SMTP, POP3, IMAP when used with
-\fICURLOPT_USE_SSL(3)\fP. Though you can to retrieve the SSL pointer, it's
-possible that before you can do that, data (including auth) may have already
-been sent over a connection after it was upgraded.
-
-Renegotiation. If unsafe renegotiation or renegotiation in a way that the
-certificate is allowed to change is allowed by your SSL library this may occur
-and the certificate may change, and data may continue to be sent or received
-after renegotiation but before you are able to get the (possibly) changed SSL
-pointer, with the (possibly) changed certificate information.
-
-Instead of using this option to poll for certificate changes use
-\fICURLOPT_SSL_CTX_FUNCTION(3)\fP to set a verification callback, if supported.
-That is safer and does not suffer from any of the problems above.
-
-How are you using this option? Are you affected by any of these limitations?
-Please let us know by making a comment at
-https://github.com/curl/curl/issues/685
-.SH PROTOCOLS
-All TLS-based
-.SH EXAMPLE
-.nf
-#include <curl/curl.h>
-#include <openssl/ssl.h>
-
-CURL *curl;
-static size_t wf(void *ptr, size_t size, size_t nmemb, void *stream)
-{
- const struct curl_tlssessioninfo *info = NULL;
- CURLcode res = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &info);
- if(info && !res) {
- if(CURLSSLBACKEND_OPENSSL == info->backend) {
- printf("OpenSSL ver. %s\\n", SSL_get_version((SSL*)info->internals));
- }
- }
- return size * nmemb;
-}
-
-int main(int argc, char** argv)
-{
- CURLcode res;
- curl = curl_easy_init();
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, wf);
- res = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- }
- return res;
-}
-.fi
-.SH AVAILABILITY
-Added in 7.48.0.
-
-This option supersedes \fICURLINFO_TLS_SESSION(3)\fP which was added in 7.34.0.
-This option is exactly the same as that option except in the case of OpenSSL.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_TLS_SESSION (3)
diff --git a/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md b/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md
new file mode 100644
index 000000000..4fc246adf
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md
@@ -0,0 +1,174 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_TLS_SSL_PTR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_TLS_SESSION (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_TLS_SESSION, CURLINFO_TLS_SSL_PTR - get TLS session info
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TLS_SSL_PTR,
+ struct curl_tlssessioninfo **session);
+
+/* if you need compatibility with libcurl < 7.48.0 use
+ CURLINFO_TLS_SESSION instead: */
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TLS_SESSION,
+ struct curl_tlssessioninfo **session);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *struct curl_tlssessioninfo **. The pointer is initialized
+to refer to a *struct curl_tlssessioninfo ** that contains an enum indicating
+the SSL library used for the handshake and a pointer to the respective
+internal TLS session structure of this underlying SSL library.
+
+This option may be useful for example to extract certificate information in a
+format convenient for further processing, such as manual validation. Refer to
+the **LIMITATIONS** section.
+
+~~~c
+struct curl_tlssessioninfo {
+ curl_sslbackend backend;
+ void *internals;
+};
+~~~
+
+The *backend* struct member is one of the defines in the CURLSSLBACKEND_*
+series: CURLSSLBACKEND_NONE (when built without TLS support),
+CURLSSLBACKEND_WOLFSSL, CURLSSLBACKEND_SECURETRANSPORT, CURLSSLBACKEND_GNUTLS,
+CURLSSLBACKEND_MBEDTLS, CURLSSLBACKEND_NSS, CURLSSLBACKEND_OPENSSL,
+CURLSSLBACKEND_SCHANNEL or CURLSSLBACKEND_MESALINK. (Note that the OpenSSL
+forks are all reported as just OpenSSL here.)
+
+The *internals* struct member points to a TLS library specific pointer for
+the active ("in use") SSL connection, with the following underlying types:
+
+## GnuTLS
+
+**gnutls_session_t**
+
+## NSS
+
+**PRFileDesc ***
+
+## OpenSSL
+
+CURLINFO_TLS_SESSION(3): **SSL_CTX ***
+
+CURLINFO_TLS_SSL_PTR(3): **SSL ***
+Since 7.48.0 the *internals* member can point to these other SSL backends
+as well:
+
+## mbedTLS
+
+**mbedTLS_ssl_context ***
+
+## Secure Channel
+
+**CtxtHandle ***
+
+## Secure Transport
+
+**SSLContext ***
+
+## wolfSSL
+
+**SSL ***
+
+If the *internals* pointer is NULL then either the SSL backend is not
+supported, an SSL session has not yet been established or the connection is no
+longer associated with the easy handle (e.g. curl_easy_perform(3) has
+returned).
+
+# LIMITATIONS
+
+This option has some limitations that could make it unsafe when it comes to
+the manual verification of certificates.
+
+This option only retrieves the first in-use SSL session pointer for your easy
+handle, however your easy handle may have more than one in-use SSL session if
+using FTP over SSL. That is because the FTP protocol has a control channel and
+a data channel and one or both may be over SSL. Currently there is no way to
+retrieve a second in-use SSL session associated with an easy handle.
+
+This option has not been thoroughly tested with clear text protocols that can
+be upgraded/downgraded to/from SSL: FTP, SMTP, POP3, IMAP when used with
+CURLOPT_USE_SSL(3). Though you can to retrieve the SSL pointer, it is possible
+that before you can do that, data (including auth) may have already been sent
+over a connection after it was upgraded.
+
+Renegotiation. If unsafe renegotiation or renegotiation in a way that the
+certificate is allowed to change is allowed by your SSL library this may occur
+and the certificate may change, and data may continue to be sent or received
+after renegotiation but before you are able to get the (possibly) changed SSL
+pointer, with the (possibly) changed certificate information.
+
+Instead of using this option to poll for certificate changes use
+CURLOPT_SSL_CTX_FUNCTION(3) to set a verification callback, if supported.
+That is safer and does not suffer from any of the problems above.
+
+How are you using this option? Are you affected by any of these limitations?
+Please let us know by making a comment at
+https://github.com/curl/curl/issues/685
+
+# PROTOCOLS
+
+All TLS-based
+
+# EXAMPLE
+
+~~~c
+#include <curl/curl.h>
+#include <openssl/ssl.h>
+
+CURL *curl;
+static size_t wf(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ const struct curl_tlssessioninfo *info = NULL;
+ CURLcode res = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &info);
+ if(info && !res) {
+ if(CURLSSLBACKEND_OPENSSL == info->backend) {
+ printf("OpenSSL ver. %s\n", SSL_get_version((SSL*)info->internals));
+ }
+ }
+ return size * nmemb;
+}
+
+int main(int argc, char **argv)
+{
+ CURLcode res;
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, wf);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+ return res;
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.48.0.
+
+This option supersedes CURLINFO_TLS_SESSION(3) which was added in 7.34.0.
+This option is exactly the same as that option except in the case of OpenSSL.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3 b/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3
deleted file mode 100644
index 12a8efa3a..000000000
--- a/docs/libcurl/opts/CURLINFO_TOTAL_TIME.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_TOTAL_TIME 3 "28 Aug 2015" libcurl libcurl
-.SH NAME
-CURLINFO_TOTAL_TIME \- get total time of previous transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME, double *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a double to receive the total time in seconds for the
-previous transfer, including name resolving, TCP connect etc. The double
-represents the time in seconds, including fractions.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- double total;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total);
- if(CURLE_OK == res) {
- printf("Time: %.1f", total);
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.4.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_TOTAL_TIME_T (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME.md b/docs/libcurl/opts/CURLINFO_TOTAL_TIME.md
new file mode 100644
index 000000000..c6af1694e
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_TOTAL_TIME.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_TOTAL_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_TOTAL_TIME_T (3)
+ - CURLOPT_TIMEOUT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_TOTAL_TIME - get total time of previous transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME, double *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a double to receive the total time in seconds for the
+previous transfer, including name resolving, TCP connect etc. The double
+represents the time in seconds, including fractions.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ double total;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total);
+ if(CURLE_OK == res) {
+ printf("Time: %.1f", total);
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.4.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3 b/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3
deleted file mode 100644
index d2bc9e886..000000000
--- a/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_TOTAL_TIME_T 3 "28 Apr 2018" libcurl libcurl
-.SH NAME
-CURLINFO_TOTAL_TIME_T \- get total time of previous transfer in microseconds
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME_T,
- curl_off_t *timep);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_off_t to receive the total time in microseconds
-for the previous transfer, including name resolving, TCP connect etc.
-The curl_off_t represents the time in microseconds.
-
-When a redirect is followed, the time from each request is added together.
-
-See also the TIMES overview in the \fIcurl_easy_getinfo(3)\fP man page.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_off_t total;
- curl_easy_setopt(curl, CURLOPT_URL, url);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total);
- if(CURLE_OK == res) {
- printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", total / 1000000,
- (long)(total % 1000000));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_TOTAL_TIME (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md b/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md
new file mode 100644
index 000000000..488d5d3aa
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_TOTAL_TIME_T
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_TOTAL_TIME (3)
+ - CURLOPT_TIMEOUT (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_TOTAL_TIME_T - get total time of previous transfer in microseconds
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_TOTAL_TIME_T,
+ curl_off_t *timep);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_off_t to receive the total time in microseconds
+for the previous transfer, including name resolving, TCP connect etc.
+The curl_off_t represents the time in microseconds.
+
+When a redirect is followed, the time from each request is added together.
+
+See also the TIMES overview in the curl_easy_getinfo(3) man page.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_off_t total;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ res = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total);
+ if(CURLE_OK == res) {
+ printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", total / 1000000,
+ (long)(total % 1000000));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLINFO_XFER_ID.3 b/docs/libcurl/opts/CURLINFO_XFER_ID.3
deleted file mode 100644
index c10e5d55e..000000000
--- a/docs/libcurl/opts/CURLINFO_XFER_ID.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLINFO_XFER_ID 3 "07 June 2023" "libcurl" "libcurl"
-.SH NAME
-CURLINFO_XFER_ID \- get the ID of a transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_XFER_ID,
- curl_off_t *xfer_id);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the identifier of the
-current/last transfer done with the handle. Stores -1 if no transfer
-has been started yet for the handle.
-
-The transfer id is unique among all transfers performed using the same
-connection cache. This is implicitly the case for all transfers in the
-same multi handle.
-
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Perform the request */
- res = curl_easy_perform(curl);
-
- if(!res) {
- curl_off_t xfer_id;
- res = curl_easy_getinfo(curl, CURLINFO_XFER_ID, &xfer_id);
- if(!res) {
- printf("Transfer ID: %" CURL_FORMAT_CURL_OFF_T "\\n", xfer_id);
- }
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 8.2.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR curl_easy_setopt (3),
-.BR CURLINFO_CONN_ID (3)
diff --git a/docs/libcurl/opts/CURLINFO_XFER_ID.md b/docs/libcurl/opts/CURLINFO_XFER_ID.md
new file mode 100644
index 000000000..b32a46b12
--- /dev/null
+++ b/docs/libcurl/opts/CURLINFO_XFER_ID.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLINFO_XFER_ID
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONN_ID (3)
+ - curl_easy_getinfo (3)
+ - curl_easy_setopt (3)
+---
+
+# NAME
+
+CURLINFO_XFER_ID - get the ID of a transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_XFER_ID,
+ curl_off_t *xfer_id);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a *curl_off_t* to receive the identifier of the
+current/last transfer done with the handle. Stores -1 if no transfer
+has been started yet for the handle.
+
+The transfer id is unique among all transfers performed using the same
+connection cache. This is implicitly the case for all transfers in the
+same multi handle.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Perform the request */
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ curl_off_t xfer_id;
+ res = curl_easy_getinfo(curl, CURLINFO_XFER_ID, &xfer_id);
+ if(!res) {
+ printf("Transfer ID: %" CURL_FORMAT_CURL_OFF_T "\n", xfer_id);
+ }
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 8.2.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3 b/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3
deleted file mode 100644
index 589b624bf..000000000
--- a/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 3 "4 Nov 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE \- chunk length threshold for pipelining
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE,
- long size);
-.fi
-.SH DESCRIPTION
-No function since pipelining was removed in 7.62.0.
-
-Pass a long with a \fBsize\fP in bytes. If a transfer in a pipeline is
-currently processing a chunked (Transfer-encoding: chunked) request with a
-current chunk length larger than \fICURLMOPT_CHUNK_LENGTH_PENALTY_SIZE(3)\fP,
-that pipeline is not considered for additional requests, even if it is shorter
-than \fICURLMOPT_MAX_PIPELINE_LENGTH(3)\fP.
-.SH DEFAULT
-The default value is 0, which means that the penalization is inactive.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURLM *m = curl_multi_init();
-long maxchunk = 10000;
-curl_multi_setopt(m, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, maxchunk);
-.fi
-.SH AVAILABILITY
-Added in 7.30.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE (3),
-.BR CURLMOPT_MAX_PIPELINE_LENGTH (3),
-.BR CURLMOPT_PIPELINING (3)
diff --git a/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md b/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md
new file mode 100644
index 000000000..127f4dd06
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE (3)
+ - CURLMOPT_MAX_PIPELINE_LENGTH (3)
+ - CURLMOPT_PIPELINING (3)
+---
+
+# NAME
+
+CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE - chunk length threshold for pipelining
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE,
+ long size);
+~~~
+
+# DESCRIPTION
+
+No function since pipelining was removed in 7.62.0.
+
+Pass a long with a **size** in bytes. If a transfer in a pipeline is
+currently processing a chunked (Transfer-encoding: chunked) request with a
+current chunk length larger than CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE(3),
+that pipeline is not considered for additional requests, even if it is shorter
+than CURLMOPT_MAX_PIPELINE_LENGTH(3).
+
+# DEFAULT
+
+The default value is 0, which means that the penalization is inactive.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ long maxchunk = 10000;
+ curl_multi_setopt(m, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, maxchunk);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.30.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3 b/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3
deleted file mode 100644
index 5a66d058e..000000000
--- a/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 3 "4 Nov 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE \- size threshold for pipelining penalty
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE,
- long size);
-.fi
-.SH DESCRIPTION
-No function since pipelining was removed in 7.62.0.
-
-Pass a long with a \fBsize\fP in bytes. If a transfer in a pipeline is
-currently processing a request with a Content-Length larger than this
-\fICURLMOPT_CONTENT_LENGTH_PENALTY_SIZE(3)\fP, that pipeline is not considered
-for additional requests, even if it is shorter than
-\fICURLMOPT_MAX_PIPELINE_LENGTH(3)\fP.
-.SH DEFAULT
-The default value is 0, which means that the size penalization is inactive.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURLM *m = curl_multi_init();
-long maxlength = 10000;
-curl_multi_setopt(m, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, maxlength);
-.fi
-.SH AVAILABILITY
-Added in 7.30.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE (3)
diff --git a/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md b/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md
new file mode 100644
index 000000000..d3e7abaf0
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md
@@ -0,0 +1,60 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE (3)
+ - CURLMOPT_PIPELINING (3)
+---
+
+# NAME
+
+CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE - size threshold for pipelining penalty
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE,
+ long size);
+~~~
+
+# DESCRIPTION
+
+No function since pipelining was removed in 7.62.0.
+
+Pass a long with a **size** in bytes. If a transfer in a pipeline is
+currently processing a request with a Content-Length larger than this
+CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE(3), that pipeline is not considered
+for additional requests, even if it is shorter than
+CURLMOPT_MAX_PIPELINE_LENGTH(3).
+
+# DEFAULT
+
+The default value is 0, which means that the size penalization is inactive.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ long maxlength = 10000;
+ curl_multi_setopt(m, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, maxlength);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.30.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3 b/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3
deleted file mode 100644
index 97468201e..000000000
--- a/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_MAXCONNECTS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_MAXCONNECTS \- size of connection cache
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAXCONNECTS, long max);
-.fi
-.SH DESCRIPTION
-Pass a long indicating the \fBmax\fP. The set number is used as the maximum
-amount of simultaneously open connections that libcurl may keep in its
-connection cache after completed use. By default libcurl enlarges the size for
-each added easy handle to make it fit 4 times the number of added easy
-handles.
-
-By setting this option, you can prevent the cache size from growing beyond the
-limit set by you.
-
-When the cache is full, curl closes the oldest one in the cache to prevent the
-number of open connections from increasing.
-
-This option is for the multi handle's use only, when using the easy interface
-you should instead use the \fICURLOPT_MAXCONNECTS(3)\fP option.
-
-See \fICURLMOPT_MAX_TOTAL_CONNECTIONS(3)\fP for limiting the number of active
-connections.
-
-.SH DEFAULT
-See DESCRIPTION
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURLM *m = curl_multi_init();
-/* only keep 10 connections in the cache */
-curl_multi_setopt(m, CURLMOPT_MAXCONNECTS, 10L);
-.fi
-.SH AVAILABILITY
-Added in 7.16.3
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_MAX_HOST_CONNECTIONS (3),
-.BR CURLOPT_MAXCONNECTS (3)
diff --git a/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.md b/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.md
new file mode 100644
index 000000000..9a5457fa5
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_MAXCONNECTS.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_MAXCONNECTS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_MAX_HOST_CONNECTIONS (3)
+ - CURLOPT_MAXCONNECTS (3)
+---
+
+# NAME
+
+CURLMOPT_MAXCONNECTS - size of connection cache
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAXCONNECTS, long max);
+~~~
+
+# DESCRIPTION
+
+Pass a long indicating the **max**. The set number is used as the maximum
+amount of simultaneously open connections that libcurl may keep in its
+connection cache after completed use. By default libcurl enlarges the size for
+each added easy handle to make it fit 4 times the number of added easy
+handles.
+
+By setting this option, you can prevent the cache size from growing beyond the
+limit set by you.
+
+When the cache is full, curl closes the oldest one in the cache to prevent the
+number of open connections from increasing.
+
+This option is for the multi handle's use only, when using the easy interface
+you should instead use the CURLOPT_MAXCONNECTS(3) option.
+
+See CURLMOPT_MAX_TOTAL_CONNECTIONS(3) for limiting the number of active
+connections.
+
+# DEFAULT
+
+See DESCRIPTION
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ /* only keep 10 connections in the cache */
+ curl_multi_setopt(m, CURLMOPT_MAXCONNECTS, 10L);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.3
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3 b/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3
deleted file mode 100644
index 64dc2b563..000000000
--- a/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.3
+++ /dev/null
@@ -1,58 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_MAX_CONCURRENT_STREAMS 3 "06 Nov 2019" libcurl libcurl
-.SH NAME
-CURLMOPT_MAX_CONCURRENT_STREAMS \- max concurrent streams for http2
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_CONCURRENT_STREAMS,
- long max);
-.fi
-.SH DESCRIPTION
-Pass a long indicating the \fBmax\fP. The set number is used as the maximum
-number of concurrent streams for a connections that libcurl should support on
-connections done using HTTP/2.
-
-Valid values range from 1 to 2147483647 (2^31 - 1) and defaults to 100. The
-value passed here would be honored based on other system resources properties.
-.SH DEFAULT
-100
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- CURLM *m = curl_multi_init();
- /* max concurrent streams 200 */
- curl_multi_setopt(m, CURLMOPT_MAX_CONCURRENT_STREAMS, 200L);
-.fi
-.SH AVAILABILITY
-Added in 7.67.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_MAXCONNECTS (3),
-.BR CURLOPT_MAXCONNECTS (3)
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.md b/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.md
new file mode 100644
index 000000000..247199444
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_MAX_CONCURRENT_STREAMS.md
@@ -0,0 +1,59 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_MAX_CONCURRENT_STREAMS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_MAXCONNECTS (3)
+ - CURLOPT_MAXCONNECTS (3)
+---
+
+# NAME
+
+CURLMOPT_MAX_CONCURRENT_STREAMS - max concurrent streams for http2
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_CONCURRENT_STREAMS,
+ long max);
+~~~
+
+# DESCRIPTION
+
+Pass a long indicating the **max**. The set number is used as the maximum
+number of concurrent streams libcurl should support on connections done using
+HTTP/2 or HTTP/3.
+
+Valid values range from 1 to 2147483647 (2^31 - 1) and defaults to 100. The
+value passed here would be honored based on other system resources properties.
+
+# DEFAULT
+
+100
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ /* max concurrent streams 200 */
+ curl_multi_setopt(m, CURLMOPT_MAX_CONCURRENT_STREAMS, 200L);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.67.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3 b/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3
deleted file mode 100644
index a9bf0ad78..000000000
--- a/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_MAX_HOST_CONNECTIONS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_MAX_HOST_CONNECTIONS \- max number of connections to a single host
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_HOST_CONNECTIONS,
- long max);
-.fi
-.SH DESCRIPTION
-Pass a long to indicate \fBmax\fP. The set number is used as the maximum
-amount of simultaneously open connections to a single host (a host being the
-same as a host name + port number pair). For each new session to a host,
-libcurl might open a new connection up to the limit set by
-\fICURLMOPT_MAX_HOST_CONNECTIONS(3)\fP. When the limit is reached, new
-sessions are kept pending until a connection becomes available.
-
-The default \fBmax\fP value is 0, unlimited. This set limit is also used for
-proxy connections, and then the proxy is considered to be the host for which
-this limit counts.
-
-When more transfers are added to the multi handle than what can be performed
-due to the set limit, they are queued up waiting for their chance. When that
-happens, the \fICURLOPT_TIMEOUT_MS(3)\fP timeout is inclusive of the waiting
-time, meaning that if you set a too narrow timeout in such a case the transfer
-might never even start before it times out.
-
-Even in the queued up situation, the \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
-timeout is however treated as a per-connect timeout.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURLM *m = curl_multi_init();
-/* do no more than 2 connections per host */
-curl_multi_setopt(m, CURLMOPT_MAX_HOST_CONNECTIONS, 2L);
-.fi
-.SH AVAILABILITY
-Added in 7.30.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_MAXCONNECTS (3),
-.BR CURLMOPT_MAX_TOTAL_CONNECTIONS (3)
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.md b/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.md
new file mode 100644
index 000000000..75c4768f6
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_MAX_HOST_CONNECTIONS.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_MAX_HOST_CONNECTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_MAXCONNECTS (3)
+ - CURLMOPT_MAX_TOTAL_CONNECTIONS (3)
+---
+
+# NAME
+
+CURLMOPT_MAX_HOST_CONNECTIONS - max number of connections to a single host
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_HOST_CONNECTIONS,
+ long max);
+~~~
+
+# DESCRIPTION
+
+Pass a long to indicate **max**. The set number is used as the maximum amount
+of simultaneously open connections to a single host (a host being the same as
+a hostname + port number pair). For each new session to a host, libcurl might
+open a new connection up to the limit set by
+CURLMOPT_MAX_HOST_CONNECTIONS(3). When the limit is reached, new sessions are
+kept pending until a connection becomes available.
+
+The default **max** value is 0, unlimited. This set limit is also used for
+proxy connections, and then the proxy is considered to be the host for which
+this limit counts.
+
+When more transfers are added to the multi handle than what can be performed
+due to the set limit, they are queued up waiting for their chance. When that
+happens, the CURLOPT_TIMEOUT_MS(3) timeout is inclusive of the waiting
+time, meaning that if you set a too narrow timeout in such a case the transfer
+might never even start before it times out.
+
+Even in the queued up situation, the CURLOPT_CONNECTTIMEOUT_MS(3)
+timeout is however treated as a per-connect timeout.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ /* do no more than 2 connections per host */
+ curl_multi_setopt(m, CURLMOPT_MAX_HOST_CONNECTIONS, 2L);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.30.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3 b/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
deleted file mode 100644
index 1785eb427..000000000
--- a/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_MAX_PIPELINE_LENGTH 3 "4 Nov 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_MAX_PIPELINE_LENGTH \- maximum number of requests in a pipeline
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_PIPELINE_LENGTH,
- long max);
-.fi
-.SH DESCRIPTION
-No function since pipelining was removed in 7.62.0.
-
-Pass a long. The set \fBmax\fP number is used as the maximum amount of
-outstanding requests in an HTTP/1.1 pipeline. This option is only used for
-HTTP/1.1 pipelining, not for HTTP/2 multiplexing.
-
-When this limit is reached, libcurl creates another connection to the same
-host (see \fICURLMOPT_MAX_HOST_CONNECTIONS(3)\fP), or queue the request until
-one of the pipelines to the host is ready to accept a request. Thus, the
-total number of requests in-flight is \fICURLMOPT_MAX_HOST_CONNECTIONS(3)\fP *
-\fICURLMOPT_MAX_PIPELINE_LENGTH(3)\fP.
-.SH DEFAULT
-5
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURLM *m = curl_multi_init();
-/* set a more conservative pipe length */
-curl_multi_setopt(m, CURLMOPT_MAX_PIPELINE_LENGTH, 3L);
-.fi
-.SH AVAILABILITY
-Added in 7.30.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLMOPT_MAX_HOST_CONNECTIONS (3)
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.md b/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.md
new file mode 100644
index 000000000..bad638e5f
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_MAX_PIPELINE_LENGTH.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_MAX_PIPELINE_LENGTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_MAX_HOST_CONNECTIONS (3)
+ - CURLMOPT_PIPELINING (3)
+---
+
+# NAME
+
+CURLMOPT_MAX_PIPELINE_LENGTH - maximum number of requests in a pipeline
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_PIPELINE_LENGTH,
+ long max);
+~~~
+
+# DESCRIPTION
+
+No function since pipelining was removed in 7.62.0.
+
+Pass a long. The set **max** number is used as the maximum amount of
+outstanding requests in an HTTP/1.1 pipeline. This option is only used for
+HTTP/1.1 pipelining, not for HTTP/2 multiplexing.
+
+When this limit is reached, libcurl creates another connection to the same
+host (see CURLMOPT_MAX_HOST_CONNECTIONS(3)), or queue the request until one
+ of the pipelines to the host is ready to accept a request. Thus, the total
+number of requests in-flight is CURLMOPT_MAX_HOST_CONNECTIONS(3) *
+CURLMOPT_MAX_PIPELINE_LENGTH(3).
+
+# DEFAULT
+
+5
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ /* set a more conservative pipe length */
+ curl_multi_setopt(m, CURLMOPT_MAX_PIPELINE_LENGTH, 3L);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.30.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3 b/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
deleted file mode 100644
index 0b7094414..000000000
--- a/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_MAX_TOTAL_CONNECTIONS 3 "4 Nov 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_MAX_TOTAL_CONNECTIONS \- max simultaneously open connections
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_TOTAL_CONNECTIONS,
- long amount);
-.fi
-.SH DESCRIPTION
-Pass a long for the \fBamount\fP. The set number is used as the maximum number
-of simultaneously open connections in total using this multi handle. For each
-new session, libcurl might open a new connection up to the limit set by
-\fICURLMOPT_MAX_TOTAL_CONNECTIONS(3)\fP. When the limit is reached, new
-sessions are held pending until there are available connections. If
-\fICURLMOPT_PIPELINING(3)\fP is enabled, libcurl can try multiplexing if the
-host is capable of it.
-
-When more transfers are added to the multi handle than what can be performed
-due to the set limit, they get queued up waiting for their chance. When that
-happens, the \fICURLOPT_TIMEOUT_MS(3)\fP timeout is counted inclusive of the
-waiting time, meaning that if you set a too narrow timeout in such a case the
-transfer might never even start before it times out.
-
-Even in the queued up situation, the \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
-timeout is however treated as a per-connect timeout.
-.SH DEFAULT
-The default value is 0, which means that there is no limit. It is then simply
-controlled by the number of easy handles added.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURLM *m = curl_multi_init();
-/* never do more than 15 connections */
-curl_multi_setopt(m, CURLMOPT_MAX_TOTAL_CONNECTIONS, 15L);
-.fi
-.SH AVAILABILITY
-Added in 7.30.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_MAXCONNECTS (3),
-.BR CURLMOPT_MAX_HOST_CONNECTIONS (3)
diff --git a/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.md b/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.md
new file mode 100644
index 000000000..859bb2ad5
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_MAX_TOTAL_CONNECTIONS.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_MAX_TOTAL_CONNECTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_MAXCONNECTS (3)
+ - CURLMOPT_MAX_HOST_CONNECTIONS (3)
+---
+
+# NAME
+
+CURLMOPT_MAX_TOTAL_CONNECTIONS - max simultaneously open connections
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_MAX_TOTAL_CONNECTIONS,
+ long amount);
+~~~
+
+# DESCRIPTION
+
+Pass a long for the **amount**. The set number is used as the maximum number
+of simultaneously open connections in total using this multi handle. For each
+new session, libcurl might open a new connection up to the limit set by
+CURLMOPT_MAX_TOTAL_CONNECTIONS(3). When the limit is reached, new
+sessions are held pending until there are available connections. If
+CURLMOPT_PIPELINING(3) is enabled, libcurl can try multiplexing if the
+host is capable of it.
+
+When more transfers are added to the multi handle than what can be performed
+due to the set limit, they get queued up waiting for their chance. When that
+happens, the CURLOPT_TIMEOUT_MS(3) timeout is counted inclusive of the
+waiting time, meaning that if you set a too narrow timeout in such a case the
+transfer might never even start before it times out.
+
+Even in the queued up situation, the CURLOPT_CONNECTTIMEOUT_MS(3)
+timeout is however treated as a per-connect timeout.
+
+# DEFAULT
+
+The default value is 0, which means that there is no limit. It is then simply
+controlled by the number of easy handles added.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ /* never do more than 15 connections */
+ curl_multi_setopt(m, CURLMOPT_MAX_TOTAL_CONNECTIONS, 15L);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.30.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING.3 b/docs/libcurl/opts/CURLMOPT_PIPELINING.3
deleted file mode 100644
index de7ccc967..000000000
--- a/docs/libcurl/opts/CURLMOPT_PIPELINING.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_PIPELINING 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_PIPELINING \- enable HTTP pipelining and multiplexing
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, long bitmask);
-.fi
-.SH DESCRIPTION
-Pass in the correct value in the \fBbitmask\fP parameter to instruct libcurl
-to enable multiplexing for this multi handle.
-
-With multiplexing enabled, libcurl attempts to do multiple transfers over the
-same connection when doing parallel transfers to the same hosts.
-
-.IP CURLPIPE_NOTHING (0)
-Default, which means doing no attempts at multiplexing.
-.IP CURLPIPE_HTTP1 (1)
-This bit is deprecated and has no effect since version 7.62.0.
-.IP CURLPIPE_MULTIPLEX (2)
-If this bit is set, libcurl tries to multiplex the new transfer over an
-existing connection if possible. This requires HTTP/2 or HTTP/3.
-.SH DEFAULT
-Since 7.62.0, \fBCURLPIPE_MULTIPLEX\fP is enabled by default.
-
-Before that, default was \fBCURLPIPE_NOTHING\fP.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURLM *m = curl_multi_init();
-/* try HTTP/2 multiplexing */
-curl_multi_setopt(m, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
-.fi
-.SH AVAILABILITY
-Added in 7.16.0. Multiplex support bit added in 7.43.0. HTTP/1 Pipelining
-support was disabled in 7.62.0.
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE (3),
-.BR CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE (3),
-.BR CURLMOPT_MAX_HOST_CONNECTIONS (3),
-.BR CURLMOPT_MAX_PIPELINE_LENGTH (3),
-.BR CURLMOPT_MAXCONNECTS (3),
-.BR CURLMOPT_PIPELINING_SITE_BL (3)
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING.md b/docs/libcurl/opts/CURLMOPT_PIPELINING.md
new file mode 100644
index 000000000..3df71b54f
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_PIPELINING.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_PIPELINING
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE (3)
+ - CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE (3)
+ - CURLMOPT_MAXCONNECTS (3)
+ - CURLMOPT_MAX_HOST_CONNECTIONS (3)
+ - CURLMOPT_MAX_PIPELINE_LENGTH (3)
+ - CURLMOPT_PIPELINING_SITE_BL (3)
+---
+
+# NAME
+
+CURLMOPT_PIPELINING - enable HTTP pipelining and multiplexing
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass in the correct value in the **bitmask** parameter to instruct libcurl
+to enable multiplexing for this multi handle.
+
+With multiplexing enabled, libcurl attempts to do multiple transfers over the
+same connection when doing parallel transfers to the same hosts.
+
+## CURLPIPE_NOTHING (0)
+
+Default, which means doing no attempts at multiplexing.
+
+## CURLPIPE_HTTP1 (1)
+
+This bit is deprecated and has no effect since version 7.62.0.
+
+## CURLPIPE_MULTIPLEX (2)
+
+If this bit is set, libcurl tries to multiplex the new transfer over an
+existing connection if possible. This requires HTTP/2 or HTTP/3.
+
+# DEFAULT
+
+Since 7.62.0, **CURLPIPE_MULTIPLEX** is enabled by default.
+
+Before that, default was **CURLPIPE_NOTHING**.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ /* try HTTP/2 multiplexing */
+ curl_multi_setopt(m, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.0. Multiplex support bit added in 7.43.0. HTTP/1 Pipelining
+support was disabled in 7.62.0.
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3 b/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3
deleted file mode 100644
index 95d475dbe..000000000
--- a/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_PIPELINING_SERVER_BL 3 "4 Nov 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_PIPELINING_SERVER_BL \- pipelining server block list
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SERVER_BL,
- char **servers);
-.fi
-.SH DESCRIPTION
-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 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 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 block list.
-.SH DEFAULT
-The default value is NULL, which means that there is no block list.
-.SH PROTOCOLS
-.SH EXAMPLE
-.nf
- char *server_block_list[] =
- {
- "Microsoft-IIS/6.0",
- "nginx/0.8.54",
- NULL
- };
-
- curl_multi_setopt(m, CURLMOPT_PIPELINING_SERVER_BL, server_block_list);
-.fi
-.SH AVAILABILITY
-Added in 7.30.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLMOPT_PIPELINING_SITE_BL (3)
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.md b/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.md
new file mode 100644
index 000000000..226700806
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_PIPELINING_SERVER_BL.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_PIPELINING_SERVER_BL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PIPELINING (3)
+ - CURLMOPT_PIPELINING_SITE_BL (3)
+---
+
+# NAME
+
+CURLMOPT_PIPELINING_SERVER_BL - pipelining server block list
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SERVER_BL,
+ char **servers);
+~~~
+
+# DESCRIPTION
+
+No function since pipelining was removed in 7.62.0.
+
+Pass a **servers** array of char *, ending with a NULL entry. This is a list
+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 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 block list.
+
+# DEFAULT
+
+The default value is NULL, which means that there is no block list.
+
+# PROTOCOLS
+
+# EXAMPLE
+
+~~~c
+static char *server_block_list[] =
+{
+ "Microsoft-IIS/6.0",
+ "nginx/0.8.54",
+ NULL
+};
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ curl_multi_setopt(m, CURLMOPT_PIPELINING_SERVER_BL, server_block_list);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.30.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3 b/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3
deleted file mode 100644
index 0e4e52e1a..000000000
--- a/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_PIPELINING_SITE_BL 3 "4 Nov 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_PIPELINING_SITE_BL \- pipelining host block list
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SITE_BL,
- char **hosts);
-.fi
-.SH DESCRIPTION
-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 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 block list.
-.SH DEFAULT
-The default value is NULL, which means that there is no block list.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
- char *site_block_list[] =
- {
- "www.haxx.se",
- "www.example.com:1234",
- NULL
- };
-
- curl_multi_setopt(m, CURLMOPT_PIPELINING_SITE_BL, site_block_list);
-.fi
-.SH AVAILABILITY
-Added in 7.30.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLMOPT_PIPELINING_SERVER_BL (3)
diff --git a/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.md b/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.md
new file mode 100644
index 000000000..a212c4f63
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_PIPELINING_SITE_BL.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_PIPELINING_SITE_BL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PIPELINING (3)
+ - CURLMOPT_PIPELINING_SERVER_BL (3)
+---
+
+# NAME
+
+CURLMOPT_PIPELINING_SITE_BL - pipelining host block list
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SITE_BL,
+ char **hosts);
+~~~
+
+# DESCRIPTION
+
+No function since pipelining was removed in 7.62.0.
+
+Pass a **hosts** array of char *, ending with a NULL entry. This is a list
+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 block list.
+
+# DEFAULT
+
+The default value is NULL, which means that there is no block list.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+static char *site_block_list[] =
+{
+ "www.haxx.se",
+ "www.example.com:1234",
+ NULL
+};
+
+int main(void)
+{
+ CURLM *m = curl_multi_init();
+ curl_multi_setopt(m, CURLMOPT_PIPELINING_SITE_BL, site_block_list);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.30.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_PUSHDATA.3 b/docs/libcurl/opts/CURLMOPT_PUSHDATA.3
deleted file mode 100644
index 2b1968417..000000000
--- a/docs/libcurl/opts/CURLMOPT_PUSHDATA.3
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_PUSHDATA 3 "1 Jun 2015" libcurl libcurl
-.SH NAME
-CURLMOPT_PUSHDATA \- pointer to pass to push callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PUSHDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Set a \fIpointer\fP to pass as the last argument to the
-\fICURLMOPT_PUSHFUNCTION(3)\fP callback. The pointer is not touched or used by
-libcurl itself, only passed on to the callback function.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-/* only allow pushes for file names starting with "push-" */
-int push_callback(CURL *parent,
- CURL *easy,
- size_t num_headers,
- struct curl_pushheaders *headers,
- void *clientp)
-{
- char *headp;
- int *transfers = (int *)clientp;
- FILE *out;
- headp = curl_pushheader_byname(headers, ":path");
- if(headp && !strncmp(headp, "/push-", 6)) {
- fprintf(stderr, "The PATH is %s\\n", headp);
-
- /* save the push here */
- out = fopen("pushed-stream", "wb");
-
- /* write to this file */
- curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
-
- (*transfers)++; /* one more */
-
- return CURL_PUSH_OK;
- }
- return CURL_PUSH_DENY;
-}
-
-curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, push_callback);
-curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &counter);
-.fi
-.SH AVAILABILITY
-Added in 7.44.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLMOPT_PUSHFUNCTION (3),
-.BR CURLOPT_PIPEWAIT (3),
-.BR RFC 7540
diff --git a/docs/libcurl/opts/CURLMOPT_PUSHDATA.md b/docs/libcurl/opts/CURLMOPT_PUSHDATA.md
new file mode 100644
index 000000000..23e8785f2
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_PUSHDATA.md
@@ -0,0 +1,87 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_PUSHDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PIPELINING (3)
+ - CURLMOPT_PUSHFUNCTION (3)
+ - CURLOPT_PIPEWAIT (3)
+ - RFC 7540
+---
+
+# NAME
+
+CURLMOPT_PUSHDATA - pointer to pass to push callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PUSHDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Set a *pointer* to pass as the last argument to the
+CURLMOPT_PUSHFUNCTION(3) callback. The pointer is not touched or used by
+libcurl itself, only passed on to the callback function.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+#include <string.h>
+
+/* only allow pushes for file names starting with "push-" */
+int push_callback(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *clientp)
+{
+ char *headp;
+ int *transfers = (int *)clientp;
+ FILE *out;
+ headp = curl_pushheader_byname(headers, ":path");
+ if(headp && !strncmp(headp, "/push-", 6)) {
+ fprintf(stderr, "The PATH is %s\n", headp);
+
+ /* save the push here */
+ out = fopen("pushed-stream", "wb");
+
+ /* write to this file */
+ curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
+
+ (*transfers)++; /* one more */
+
+ return CURL_PUSH_OK;
+ }
+ return CURL_PUSH_DENY;
+}
+
+int main(void)
+{
+ int counter;
+ CURLM *multi = curl_multi_init();
+ curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, push_callback);
+ curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &counter);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.44.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3 b/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3
deleted file mode 100644
index 9e0d8b9f2..000000000
--- a/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.3
+++ /dev/null
@@ -1,132 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_PUSHFUNCTION 3 "1 Jun 2015" libcurl libcurl
-.SH NAME
-CURLMOPT_PUSHFUNCTION \- callback that approves or denies server pushes
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int curl_push_callback(CURL *parent,
- CURL *easy,
- size_t num_headers,
- struct curl_pushheaders *headers,
- void *clientp);
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PUSHFUNCTION,
- curl_push_callback func);
-.fi
-.SH DESCRIPTION
-This callback gets called when a new HTTP/2 stream is being pushed by the
-server (using the PUSH_PROMISE frame). If no push callback is set, all offered
-pushes are denied automatically.
-.SH CALLBACK DESCRIPTION
-The callback gets its arguments like this:
-
-\fIparent\fP is the handle of the stream on which this push arrives. The new
-handle has been duplicated from the parent, meaning that it has gotten all its
-options inherited. It is then up to the application to alter any options if
-desired.
-
-\fIeasy\fP is a newly created handle that represents this upcoming transfer.
-
-\fInum_headers\fP is the number of name+value pairs that was received and can
-be accessed
-
-\fIheaders\fP is a handle used to access push headers using the accessor
-functions described below. This only accesses and provides the PUSH_PROMISE
-headers, the normal response headers are provided in the header callback as
-usual.
-
-\fIclientp\fP is the pointer set with \fICURLMOPT_PUSHDATA(3)\fP
-
-If the callback returns CURL_PUSH_OK, the new easy handle is added to the
-multi handle, the callback must not do that by itself.
-
-The callback can access PUSH_PROMISE headers with two accessor
-functions. These functions can only be used from within this callback and they
-can only access the PUSH_PROMISE headers: \fIcurl_pushheader_byname(3)\fP and
-\fIcurl_pushheader_bynum(3)\fP. The normal response headers are passed to the
-header callback for pushed streams just as for normal streams.
-
-The header fields can also be accessed with \fIcurl_easy_header(3)\fP,
-introduced in later libcurl versions.
-.SH CALLBACK RETURN VALUE
-.IP "CURL_PUSH_OK (0)"
-The application has accepted the stream and it can now start receiving data,
-the ownership of the CURL handle has been taken over by the application.
-.IP "CURL_PUSH_DENY (1)"
-The callback denies the stream and no data reaches the application, the easy
-handle is destroyed by libcurl.
-.IP "CURL_PUSH_ERROROUT (2)"
-Returning this code rejects the pushed stream and returns an error back on the
-parent stream making it get closed with an error. (Added in 7.72.0)
-.IP *
-All other return codes are reserved for future use.
-.SH DEFAULT
-NULL, no callback
-.SH PROTOCOLS
-HTTP(S) (HTTP/2 only)
-.SH EXAMPLE
-.nf
-/* only allow pushes for file names starting with "push-" */
-int push_callback(CURL *parent,
- CURL *easy,
- size_t num_headers,
- struct curl_pushheaders *headers,
- void *clientp)
-{
- char *headp;
- int *transfers = (int *)clientp;
- FILE *out;
- headp = curl_pushheader_byname(headers, ":path");
- if(headp && !strncmp(headp, "/push-", 6)) {
- fprintf(stderr, "The PATH is %s\\n", headp);
-
- /* save the push here */
- out = fopen("pushed-stream", "wb");
-
- /* write to this file */
- curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
-
- (*transfers)++; /* one more */
-
- return CURL_PUSH_OK;
- }
- return CURL_PUSH_DENY;
-}
-
-curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, push_callback);
-curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &counter);
-.fi
-.SH AVAILABILITY
-Added in 7.44.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PUSHDATA (3),
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLOPT_PIPEWAIT (3),
-.BR RFC 7540
diff --git a/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.md b/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.md
new file mode 100644
index 000000000..903ac06fb
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_PUSHFUNCTION.md
@@ -0,0 +1,148 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_PUSHFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PIPELINING (3)
+ - CURLMOPT_PUSHDATA (3)
+ - CURLOPT_PIPEWAIT (3)
+ - RFC 7540
+---
+
+# NAME
+
+CURLMOPT_PUSHFUNCTION - callback that approves or denies server pushes
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int curl_push_callback(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *clientp);
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PUSHFUNCTION,
+ curl_push_callback func);
+~~~
+
+# DESCRIPTION
+
+This callback gets called when a new HTTP/2 stream is being pushed by the
+server (using the PUSH_PROMISE frame). If no push callback is set, all offered
+pushes are denied automatically.
+
+# CALLBACK DESCRIPTION
+
+The callback gets its arguments like this:
+
+*parent* is the handle of the stream on which this push arrives. The new
+handle has been duplicated from the parent, meaning that it has gotten all its
+options inherited. It is then up to the application to alter any options if
+desired.
+
+*easy* is a newly created handle that represents this upcoming transfer.
+
+*num_headers* is the number of name+value pairs that was received and can
+be accessed
+
+*headers* is a handle used to access push headers using the accessor
+functions described below. This only accesses and provides the PUSH_PROMISE
+headers, the normal response headers are provided in the header callback as
+usual.
+
+*clientp* is the pointer set with CURLMOPT_PUSHDATA(3)
+
+If the callback returns CURL_PUSH_OK, the new easy handle is added to the
+multi handle, the callback must not do that by itself.
+
+The callback can access PUSH_PROMISE headers with two accessor
+functions. These functions can only be used from within this callback and they
+can only access the PUSH_PROMISE headers: curl_pushheader_byname(3) and
+curl_pushheader_bynum(3). The normal response headers are passed to the
+header callback for pushed streams just as for normal streams.
+
+The header fields can also be accessed with curl_easy_header(3),
+introduced in later libcurl versions.
+
+# CALLBACK RETURN VALUE
+
+## CURL_PUSH_OK (0)
+
+The application has accepted the stream and it can now start receiving data,
+the ownership of the CURL handle has been taken over by the application.
+
+## CURL_PUSH_DENY (1)
+
+The callback denies the stream and no data reaches the application, the easy
+handle is destroyed by libcurl.
+
+## CURL_PUSH_ERROROUT (2)
+
+Returning this code rejects the pushed stream and returns an error back on the
+parent stream making it get closed with an error. (Added in 7.72.0)
+
+## *
+
+All other return codes are reserved for future use.
+
+# DEFAULT
+
+NULL, no callback
+
+# PROTOCOLS
+
+HTTP(S) (HTTP/2 only)
+
+# EXAMPLE
+
+~~~c
+#include <string.h>
+
+/* only allow pushes for file names starting with "push-" */
+int push_callback(CURL *parent,
+ CURL *easy,
+ size_t num_headers,
+ struct curl_pushheaders *headers,
+ void *clientp)
+{
+ char *headp;
+ int *transfers = (int *)clientp;
+ FILE *out;
+ headp = curl_pushheader_byname(headers, ":path");
+ if(headp && !strncmp(headp, "/push-", 6)) {
+ fprintf(stderr, "The PATH is %s\n", headp);
+
+ /* save the push here */
+ out = fopen("pushed-stream", "wb");
+
+ /* write to this file */
+ curl_easy_setopt(easy, CURLOPT_WRITEDATA, out);
+
+ (*transfers)++; /* one more */
+
+ return CURL_PUSH_OK;
+ }
+ return CURL_PUSH_DENY;
+}
+
+int main(void)
+{
+ int counter;
+ CURLM *multi = curl_multi_init();
+ curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, push_callback);
+ curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &counter);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.44.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3 b/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3
deleted file mode 100644
index 4dd103bee..000000000
--- a/docs/libcurl/opts/CURLMOPT_SOCKETDATA.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_SOCKETDATA 3 "3 Nov 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_SOCKETDATA \- custom pointer passed to the socket callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_SOCKETDATA, void *pointer);
-.SH DESCRIPTION
-A data \fIpointer\fP to pass to the socket callback set with the
-\fICURLMOPT_SOCKETFUNCTION(3)\fP option.
-
-This pointer is not touched by libcurl but is only passed in as the socket
-callbacks's \fBclientp\fP argument.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
-{
- GlobalInfo *g = (GlobalInfo*) cbp;
- SockInfo *fdp = (SockInfo*) sockp;
-
- if(what == CURL_POLL_REMOVE) {
- remsock(fdp);
- }
- else {
- if(!fdp) {
- addsock(s, e, what, g);
- }
- else {
- setsock(fdp, s, e, what, g);
- }
- }
- return 0;
-}
-
-main()
-{
- GlobalInfo setup;
- /* ... use socket callback and custom pointer */
- curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
- curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, &setup);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.4
-.SH RETURN VALUE
-Returns CURLM_OK.
-.SH "SEE ALSO"
-.BR curl_multi_socket_action (3),
-.BR CURLMOPT_SOCKETFUNCTION (3),
-.BR CURLMOPT_TIMERFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLMOPT_SOCKETDATA.md b/docs/libcurl/opts/CURLMOPT_SOCKETDATA.md
new file mode 100644
index 000000000..f4de8c331
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_SOCKETDATA.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_SOCKETDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_SOCKETFUNCTION (3)
+ - CURLMOPT_TIMERFUNCTION (3)
+ - curl_multi_socket_action (3)
+---
+
+# NAME
+
+CURLMOPT_SOCKETDATA - custom pointer passed to the socket callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_SOCKETDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+A data *pointer* to pass to the socket callback set with the
+CURLMOPT_SOCKETFUNCTION(3) option.
+
+This pointer is not touched by libcurl but is only passed in as the socket
+callbacks's **clientp** argument.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *ours;
+};
+
+static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
+{
+ struct priv *p = sockp;
+ printf("my ptr: %p\n", p->ours);
+
+ if(what == CURL_POLL_REMOVE) {
+ /* remove the socket from our collection */
+ }
+ if(what & CURL_POLL_IN) {
+ /* wait for read on this socket */
+ }
+ if(what & CURL_POLL_OUT) {
+ /* wait for write on this socket */
+ }
+
+ return 0;
+}
+
+int main(void)
+{
+ struct priv setup;
+ CURLM *multi = curl_multi_init();
+ /* ... use socket callback and custom pointer */
+ curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
+ curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, &setup);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.4
+
+# RETURN VALUE
+
+Returns CURLM_OK.
diff --git a/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3 b/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3
deleted file mode 100644
index fa4272e13..000000000
--- a/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.3
+++ /dev/null
@@ -1,122 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_SOCKETFUNCTION 3 "3 Nov 2016" libcurl libcurl
-.SH NAME
-CURLMOPT_SOCKETFUNCTION \- callback informed about what to wait for
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int socket_callback(CURL *easy, /* easy handle */
- curl_socket_t s, /* socket */
- int what, /* describes the socket */
- void *clientp, /* private callback pointer */
- void *socketp); /* private socket pointer */
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-When the \fIcurl_multi_socket_action(3)\fP function is called, it uses this
-callback to inform the application about updates in the socket (file
-descriptor) status by doing none, one, or multiple calls to the
-\fBsocket_callback\fP. The callback function gets status updates with changes
-since the previous time the callback was called. If the given callback pointer
-is set to NULL, no callback is called.
-
-libcurl then expects the application to monitor the sockets for the specific
-activities and tell libcurl again when something happens on one of them. Tell
-libcurl by calling \fIcurl_multi_socket_action(3)\fP.
-.SH "CALLBACK ARGUMENTS"
-\fIeasy\fP identifies the specific transfer for which this update is related.
-
-\fIs\fP is the specific socket this function invocation concerns. If the
-\fBwhat\fP argument is not CURL_POLL_REMOVE then it holds information about
-what activity on this socket the application is supposed to
-monitor. Subsequent calls to this callback might update the \fBwhat\fP bits
-for a socket that is already monitored.
-
-The socket callback should return 0 on success, and -1 on error. If this
-callback returns error, \fBall\fP transfers currently in progress in this
-multi handle are aborted and made to fail.
-
-\fBclientp\fP is set with \fICURLMOPT_SOCKETDATA(3)\fP.
-
-\fBsocketp\fP is set with \fIcurl_multi_assign(3)\fP or NULL.
-
-The \fBwhat\fP parameter informs the callback on the status of the given
-socket. It can hold one of these values:
-.IP CURL_POLL_IN
-Wait for incoming data. For the socket to become readable.
-.IP CURL_POLL_OUT
-Wait for outgoing data. For the socket to become writable.
-.IP CURL_POLL_INOUT
-Wait for incoming and outgoing data. For the socket to become readable or
-writable.
-.IP CURL_POLL_REMOVE
-The specified socket/file descriptor is no longer used by libcurl for any
-active transfer. It might soon be added again.
-.SH DEFAULT
-NULL (no callback)
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
-{
- GlobalInfo *g = cbp;
- SockInfo *fdp = sockp;
-
- if(what == CURL_POLL_REMOVE) {
- remsock(fdp);
- }
- else {
- if(!fdp) {
- addsock(s, e, what, g);
- }
- else {
- setsock(fdp, s, e, what, g);
- }
- }
- return 0;
-}
-
-main()
-{
- GlobalInfo setup;
- /* ... use socket callback and custom pointer */
- curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
- curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, &setup);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.4
-.SH RETURN VALUE
-Returns CURLM_OK.
-.SH "SEE ALSO"
-.BR curl_multi_socket_action (3),
-.BR CURLMOPT_SOCKETDATA (3),
-.BR CURLMOPT_TIMERFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md b/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md
new file mode 100644
index 000000000..5b34db5f3
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md
@@ -0,0 +1,135 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_SOCKETFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_SOCKETDATA (3)
+ - CURLMOPT_TIMERFUNCTION (3)
+ - curl_multi_socket_action (3)
+---
+
+# NAME
+
+CURLMOPT_SOCKETFUNCTION - callback informed about what to wait for
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int socket_callback(CURL *easy, /* easy handle */
+ curl_socket_t s, /* socket */
+ int what, /* describes the socket */
+ void *clientp, /* private callback pointer */
+ void *socketp); /* private socket pointer */
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+When the curl_multi_socket_action(3) function is called, it uses this
+callback to inform the application about updates in the socket (file
+descriptor) status by doing none, one, or multiple calls to the
+**socket_callback**. The callback function gets status updates with changes
+since the previous time the callback was called. If the given callback pointer
+is set to NULL, no callback is called.
+
+libcurl then expects the application to monitor the sockets for the specific
+activities and tell libcurl again when something happens on one of them. Tell
+libcurl by calling curl_multi_socket_action(3).
+
+# CALLBACK ARGUMENTS
+
+*easy* identifies the specific transfer for which this update is related.
+
+*s* is the specific socket this function invocation concerns. If the
+**what** argument is not CURL_POLL_REMOVE then it holds information about
+what activity on this socket the application is supposed to
+monitor. Subsequent calls to this callback might update the **what** bits
+for a socket that is already monitored.
+
+The socket callback should return 0 on success, and -1 on error. If this
+callback returns error, **all** transfers currently in progress in this
+multi handle are aborted and made to fail.
+
+**clientp** is set with CURLMOPT_SOCKETDATA(3).
+
+**socketp** is set with curl_multi_assign(3) or NULL.
+
+The **what** parameter informs the callback on the status of the given
+socket. It can hold one of these values:
+
+## CURL_POLL_IN
+
+Wait for incoming data. For the socket to become readable.
+
+## CURL_POLL_OUT
+
+Wait for outgoing data. For the socket to become writable.
+
+## CURL_POLL_INOUT
+
+Wait for incoming and outgoing data. For the socket to become readable or
+writable.
+
+## CURL_POLL_REMOVE
+
+The specified socket/file descriptor is no longer used by libcurl for any
+active transfer. It might soon be added again.
+
+# DEFAULT
+
+NULL (no callback)
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *ours;
+};
+
+static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
+{
+ struct priv *p = sockp;
+ printf("our ptr: %p\n", p->ours);
+
+ if(what == CURL_POLL_REMOVE) {
+ /* remove the socket from our collection */
+ }
+ if(what & CURL_POLL_IN) {
+ /* wait for read on this socket */
+ }
+ if(what & CURL_POLL_OUT) {
+ /* wait for write on this socket */
+ }
+
+ return 0;
+}
+
+int main(void)
+{
+ struct priv setup;
+ CURLM *multi = curl_multi_init();
+ /* ... use socket callback and custom pointer */
+ curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
+ curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, &setup);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.4
+
+# RETURN VALUE
+
+Returns CURLM_OK.
diff --git a/docs/libcurl/opts/CURLMOPT_TIMERDATA.3 b/docs/libcurl/opts/CURLMOPT_TIMERDATA.3
deleted file mode 100644
index 1da6d4a28..000000000
--- a/docs/libcurl/opts/CURLMOPT_TIMERDATA.3
+++ /dev/null
@@ -1,85 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_TIMERDATA 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_TIMERDATA \- custom pointer to pass to timer callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_TIMERDATA, void *pointer);
-.SH DESCRIPTION
-A data \fBpointer\fP to pass to the timer callback set with the
-\fICURLMOPT_TIMERFUNCTION(3)\fP option.
-
-This pointer is not touched by libcurl but is only be passed in to the timer
-callbacks's \fBclientp\fP argument.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static gboolean timeout_cb(gpointer user_data)
-{
- int running;
- if(user_data) {
- g_free(user_data);
- curl_multi_setopt(curl_handle, CURLMOPT_TIMERDATA, NULL);
- }
- curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, &running);
- return G_SOURCE_REMOVE;
-}
-
-static int timerfunc(CURLM *multi, long timeout_ms, void *clientp)
-{
- guint *id = clientp;
-
- if(id)
- g_source_remove(*id);
-
- /* -1 means we should just delete our timer. */
- if(timeout_ms == -1) {
- g_free(id);
- id = NULL;
- }
- else {
- if(!id)
- id = g_new(guint, 1);
- *id = g_timeout_add(timeout_ms, timeout_cb, id);
- }
- current_timer = id;
- return 0;
-}
-
-curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, timerfunc);
-.fi
-.SH AVAILABILITY
-Added in 7.16.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_TIMERFUNCTION (3),
-.BR CURLMOPT_SOCKETFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLMOPT_TIMERDATA.md b/docs/libcurl/opts/CURLMOPT_TIMERDATA.md
new file mode 100644
index 000000000..13bbd925b
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_TIMERDATA.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_TIMERDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_SOCKETFUNCTION (3)
+ - CURLMOPT_TIMERFUNCTION (3)
+---
+
+# NAME
+
+CURLMOPT_TIMERDATA - custom pointer to pass to timer callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_TIMERDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+A data **pointer** to pass to the timer callback set with the
+CURLMOPT_TIMERFUNCTION(3) option.
+
+This pointer is not touched by libcurl but is only be passed in to the timer
+callbacks's **clientp** argument.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static int timerfunc(CURLM *multi, long timeout_ms, void *clientp)
+{
+ struct priv *mydata = clientp;
+ printf("our ptr: %p\n", mydata->custom);
+
+ if(timeout_ms) {
+ /* this is the new single timeout to wait for */
+ }
+ else {
+ /* delete the timeout, nothing to wait for now */
+ }
+}
+
+int main(void)
+{
+ struct priv mydata;
+ CURLM *multi = curl_multi_init();
+ curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, timerfunc);
+ curl_multi_setopt(multi, CURLMOPT_TIMERDATA, &mydata);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3 b/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3
deleted file mode 100644
index 4914dc6f9..000000000
--- a/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.3
+++ /dev/null
@@ -1,113 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLMOPT_TIMERFUNCTION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLMOPT_TIMERFUNCTION \- callback to receive timeout values
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int timer_callback(CURLM *multi, /* multi handle */
- long timeout_ms, /* timeout in number of ms */
- void *clientp); /* private callback pointer */
-
-CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_TIMERFUNCTION, timer_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-Certain features, such as timeouts and retries, require you to call libcurl
-even when there is no activity on the file descriptors.
-
-Your callback function \fBtimer_callback\fP should install a non-repeating
-timer with an expire time of \fBtimeout_ms\fP milliseconds. When that timer
-fires, call either \fIcurl_multi_socket_action(3)\fP or
-\fIcurl_multi_perform(3)\fP, depending on which interface you use.
-
-A \fBtimeout_ms\fP value of -1 passed to this callback means you should delete
-the timer. All other values are valid expire times in number of milliseconds.
-
-The \fBtimer_callback\fP is called when the timeout expire time is changed.
-
-The \fBclientp\fP pointer is set with \fICURLMOPT_TIMERDATA(3)\fP.
-
-The timer callback should return 0 on success, and -1 on error. If this
-callback returns error, \fBall\fP transfers currently in progress in this
-multi handle are aborted and made to fail.
-
-This callback can be used instead of, or in addition to,
-\fIcurl_multi_timeout(3)\fP.
-
-\fBWARNING:\fP do not call libcurl directly from within the callback itself
-when the \fBtimeout_ms\fP value is zero, since it risks triggering an
-unpleasant recursive behavior that immediately calls another call to the
-callback with a zero timeout...
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static gboolean timeout_cb(gpointer user_data)
-{
- int running;
- if(user_data) {
- g_free(user_data);
- curl_multi_setopt(curl_handle, CURLMOPT_TIMERDATA, NULL);
- }
- curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, &running);
- return G_SOURCE_REMOVE;
-}
-
-static int timerfunc(CURLM *multi, long timeout_ms, void *clientp)
-{
- guint *id = clientp;
-
- if(id)
- g_source_remove(*id);
-
- /* -1 means we should just delete our timer. */
- if(timeout_ms == -1) {
- g_free(id);
- id = NULL;
- }
- else {
- if(!id)
- id = g_new(guint, 1);
- *id = g_timeout_add(timeout_ms, timeout_cb, id);
- }
- current_timer = id;
- return 0;
-}
-
-curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, timerfunc);
-.fi
-.SH AVAILABILITY
-Added in 7.16.0
-.SH RETURN VALUE
-Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_TIMERDATA (3),
-.BR CURLMOPT_SOCKETFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.md b/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.md
new file mode 100644
index 000000000..83a8fe7e0
--- /dev/null
+++ b/docs/libcurl/opts/CURLMOPT_TIMERFUNCTION.md
@@ -0,0 +1,103 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLMOPT_TIMERFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_SOCKETFUNCTION (3)
+ - CURLMOPT_TIMERDATA (3)
+---
+
+# NAME
+
+CURLMOPT_TIMERFUNCTION - callback to receive timeout values
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int timer_callback(CURLM *multi, /* multi handle */
+ long timeout_ms, /* timeout in number of ms */
+ void *clientp); /* private callback pointer */
+
+CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_TIMERFUNCTION, timer_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+Certain features, such as timeouts and retries, require you to call libcurl
+even when there is no activity on the file descriptors.
+
+Your callback function **timer_callback** should install a non-repeating
+timer with an expire time of **timeout_ms** milliseconds. When that timer
+fires, call either curl_multi_socket_action(3) or
+curl_multi_perform(3), depending on which interface you use.
+
+A **timeout_ms** value of -1 passed to this callback means you should delete
+the timer. All other values are valid expire times in number of milliseconds.
+
+The **timer_callback** is called when the timeout expire time is changed.
+
+The **clientp** pointer is set with CURLMOPT_TIMERDATA(3).
+
+The timer callback should return 0 on success, and -1 on error. If this
+callback returns error, **all** transfers currently in progress in this
+multi handle are aborted and made to fail.
+
+This callback can be used instead of, or in addition to,
+curl_multi_timeout(3).
+
+**WARNING:** do not call libcurl directly from within the callback itself
+when the **timeout_ms** value is zero, since it risks triggering an
+unpleasant recursive behavior that immediately calls another call to the
+callback with a zero timeout...
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static int timerfunc(CURLM *multi, long timeout_ms, void *clientp)
+{
+ struct priv *mydata = clientp;
+ printf("our ptr: %p\n", mydata->custom);
+
+ if(timeout_ms) {
+ /* this is the new single timeout to wait for */
+ }
+ else {
+ /* delete the timeout, nothing to wait for now */
+ }
+}
+
+int main(void)
+{
+ struct priv mydata;
+ CURLM *multi = curl_multi_init();
+ curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, timerfunc);
+ curl_multi_setopt(multi, CURLMOPT_TIMERDATA, &mydata);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.0
+
+# RETURN VALUE
+
+Returns CURLM_OK if the option is supported, and CURLM_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3 b/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3
deleted file mode 100644
index dcb34296f..000000000
--- a/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ABSTRACT_UNIX_SOCKET 3 "08 Jan 2017" libcurl libcurl
-.SH NAME
-CURLOPT_ABSTRACT_UNIX_SOCKET \- abstract Unix domain socket
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ABSTRACT_UNIX_SOCKET,
- char *path);
-.fi
-.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
-null-terminated string holding the path of the socket. The path is 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 byte.
-
-On non-supporting platforms, the abstract address is interpreted as an empty
-string and fails gracefully, generating a runtime error.
-
-This option shares the same semantics as \fICURLOPT_UNIX_SOCKET_PATH(3)\fP in
-which documentation more details can be found. Internally, these two options
-share the same storage and therefore only one of them can be set per handle.
-.SH DEFAULT
-Default is NULL.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- curl_easy_setopt(curl_handle, CURLOPT_ABSTRACT_UNIX_SOCKET, "/tmp/foo.sock");
- curl_easy_setopt(curl_handle, CURLOPT_URL, "http://localhost/");
-.fi
-
-.SH AVAILABILITY
-Added in 7.53.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_UNIX_SOCKET_PATH (3),
-.BR unix (7)
diff --git a/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.md b/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.md
new file mode 100644
index 000000000..33d2b7bcc
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ABSTRACT_UNIX_SOCKET.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ABSTRACT_UNIX_SOCKET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_UNIX_SOCKET_PATH (3)
+ - unix (7)
+---
+
+# NAME
+
+CURLOPT_ABSTRACT_UNIX_SOCKET - abstract Unix domain socket
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ABSTRACT_UNIX_SOCKET,
+ char *path);
+~~~
+
+# 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
+null-terminated string holding the path of the socket. The path is set to
+*path* 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 byte.
+
+On non-supporting platforms, the abstract address is interpreted as an empty
+string and fails gracefully, generating a runtime error.
+
+This option shares the same semantics as CURLOPT_UNIX_SOCKET_PATH(3) in
+which documentation more details can be found. Internally, these two options
+share the same storage and therefore only one of them can be set per handle.
+
+# DEFAULT
+
+Default is NULL.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_ABSTRACT_UNIX_SOCKET, "/tmp/foo.sock");
+ curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.53.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3
deleted file mode 100644
index 92dcf8757..000000000
--- a/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ACCEPTTIMEOUT_MS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_ACCEPTTIMEOUT_MS \- timeout waiting for FTP server to connect back
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPTTIMEOUT_MS, long ms);
-.fi
-.SH DESCRIPTION
-Pass a long telling libcurl the maximum number of milliseconds to wait for a
-server to connect back to libcurl when an active FTP connection is used.
-.SH DEFAULT
-60000 milliseconds
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/path/file");
-
- /* wait no more than 5 seconds for FTP server responses */
- curl_easy_setopt(curl, CURLOPT_ACCEPTTIMEOUT_MS, 5000L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.24.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECTTIMEOUT_MS (3),
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.md b/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.md
new file mode 100644
index 000000000..77615d886
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ACCEPTTIMEOUT_MS.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ACCEPTTIMEOUT_MS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT_MS (3)
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_ACCEPTTIMEOUT_MS - timeout waiting for FTP server to connect back
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPTTIMEOUT_MS, long ms);
+~~~
+
+# DESCRIPTION
+
+Pass a long telling libcurl the maximum number of milliseconds to wait for a
+server to connect back to libcurl when an active FTP connection is used.
+
+# DEFAULT
+
+60000 milliseconds
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/path/file");
+
+ /* wait no more than 5 seconds for FTP server responses */
+ curl_easy_setopt(curl, CURLOPT_ACCEPTTIMEOUT_MS, 5000L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.24.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3 b/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3
deleted file mode 100644
index 821bf2f28..000000000
--- a/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.3
+++ /dev/null
@@ -1,109 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ACCEPT_ENCODING 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_ACCEPT_ENCODING \- automatic decompression of HTTP downloads
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPT_ENCODING, char *enc);
-.fi
-.SH DESCRIPTION
-Pass a char * argument specifying what encoding you would like.
-
-Sets the contents of the Accept-Encoding: header sent in an HTTP request, and
-enables decoding of a response when a Content-Encoding: header is received.
-
-libcurl potentially supports several different compressed encodings depending
-on what support that has been built-in.
-
-To aid applications not having to bother about what specific algorithms this
-particular libcurl build supports, libcurl allows a zero-length string to be
-set ("") to ask for an Accept-Encoding: header to be used that contains all
-built-in supported encodings.
-
-Alternatively, you can specify exactly the encoding or list of encodings you
-want in the response. The following encodings are supported: \fIidentity\fP,
-meaning non-compressed, \fIdeflate\fP which requests the server to compress
-its response using the zlib algorithm, \fIgzip\fP which requests the gzip
-algorithm, (since curl 7.57.0) \fIbr\fP which is brotli and (since curl
-7.72.0) \fIzstd\fP which is zstd. Provide them in the string as a
-comma-separated list of accepted encodings, like: \fB"br, gzip, deflate"\fP.
-
-Set \fICURLOPT_ACCEPT_ENCODING(3)\fP to NULL to explicitly disable it, which
-makes libcurl not send an Accept-Encoding: header and not decompress received
-contents automatically.
-
-You can also opt to just include the Accept-Encoding: header in your request
-with \fICURLOPT_HTTPHEADER(3)\fP but then there is no automatic decompressing
-when receiving data.
-
-This is a request, not an order; the server may or may not do it. This option
-must be set (to any non-NULL value) or else any unsolicited encoding done by
-the server is ignored.
-
-Servers might respond with Content-Encoding even without getting a
-Accept-Encoding: in the request. Servers might respond with a different
-Content-Encoding than what was asked for in the request.
-
-The Content-Length: servers send for a compressed response is supposed to
-indicate the length of the compressed content so when auto decoding is enabled
-it may not match the sum of bytes reported by the write callbacks (although,
-sending the length of the non-compressed content is a common server mistake).
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* enable all supported built-in compressions */
- curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was called CURLOPT_ENCODING before 7.21.6
-
-The specific libcurl you are using must have been built with zlib to be able to
-decompress gzip and deflate responses, with the brotli library to
-decompress brotli responses and with the zstd library to decompress zstd
-responses.
-.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_HTTP_CONTENT_DECODING (3),
-.BR CURLOPT_HTTPHEADER (3),
-.BR CURLOPT_TRANSFER_ENCODING (3)
diff --git a/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md b/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md
new file mode 100644
index 000000000..9bba40d9d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md
@@ -0,0 +1,110 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ACCEPT_ENCODING
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPHEADER (3)
+ - CURLOPT_HTTP_CONTENT_DECODING (3)
+ - CURLOPT_TRANSFER_ENCODING (3)
+---
+
+# NAME
+
+CURLOPT_ACCEPT_ENCODING - automatic decompression of HTTP downloads
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ACCEPT_ENCODING, char *enc);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer argument specifying what encoding you would like.
+
+Sets the contents of the Accept-Encoding: header sent in an HTTP request, and
+enables decoding of a response when a Content-Encoding: header is received.
+
+libcurl potentially supports several different compressed encodings depending
+on what support that has been built-in.
+
+To aid applications not having to bother about what specific algorithms this
+particular libcurl build supports, libcurl allows a zero-length string to be
+set ("") to ask for an Accept-Encoding: header to be used that contains all
+built-in supported encodings.
+
+Alternatively, you can specify exactly the encoding or list of encodings you
+want in the response. The following encodings are supported: *identity*,
+meaning non-compressed, *deflate* which requests the server to compress
+its response using the zlib algorithm, *gzip* which requests the gzip
+algorithm, (since curl 7.57.0) *br* which is brotli and (since curl
+7.72.0) *zstd* which is zstd. Provide them in the string as a
+comma-separated list of accepted encodings, like: **"br, gzip, deflate"**.
+
+Set CURLOPT_ACCEPT_ENCODING(3) to NULL to explicitly disable it, which
+makes libcurl not send an Accept-Encoding: header and not decompress received
+contents automatically.
+
+You can also opt to just include the Accept-Encoding: header in your request
+with CURLOPT_HTTPHEADER(3) but then there is no automatic decompressing
+when receiving data.
+
+This is a request, not an order; the server may or may not do it. This option
+must be set (to any non-NULL value) or else any unsolicited encoding done by
+the server is ignored.
+
+Servers might respond with Content-Encoding even without getting a
+Accept-Encoding: in the request. Servers might respond with a different
+Content-Encoding than what was asked for in the request.
+
+The Content-Length: servers send for a compressed response is supposed to
+indicate the length of the compressed content so when auto decoding is enabled
+it may not match the sum of bytes reported by the write callbacks (although,
+sending the length of the non-compressed content is a common server mistake).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* enable all supported built-in compressions */
+ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was called CURLOPT_ENCODING before 7.21.6
+
+The specific libcurl you are using must have been built with zlib to be able to
+decompress gzip and deflate responses, with the brotli library to
+decompress brotli responses and with the zstd library to decompress zstd
+responses.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3 b/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3
deleted file mode 100644
index e3d3e128a..000000000
--- a/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ADDRESS_SCOPE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_ADDRESS_SCOPE \- scope id for IPv6 addresses
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ADDRESS_SCOPE, long scope);
-.fi
-.SH DESCRIPTION
-Pass a long specifying the scope id value to use when connecting to IPv6 addresses.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All, when using IPv6
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- long my_scope_id;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- my_scope_id = if_nametoindex("eth0");
- curl_easy_setopt(curl, CURLOPT_ADDRESS_SCOPE, my_scope_id);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-Returns CURLE_BAD_FUNCTION_ARGUMENT if set to a negative value.
-.SH "SEE ALSO"
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md b/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md
new file mode 100644
index 000000000..78526bd39
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ADDRESS_SCOPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_ADDRESS_SCOPE - scope id for IPv6 addresses
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ADDRESS_SCOPE, long scope);
+~~~
+
+# DESCRIPTION
+
+Pass a long specifying the scope id value to use when connecting to IPv6 addresses.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All, when using IPv6
+
+# EXAMPLE
+
+~~~c
+#include <net/if.h> /* for if_nametoindex() */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ long my_scope_id;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ my_scope_id = if_nametoindex("eth0");
+ curl_easy_setopt(curl, CURLOPT_ADDRESS_SCOPE, my_scope_id);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+Returns CURLE_BAD_FUNCTION_ARGUMENT if set to a negative value.
diff --git a/docs/libcurl/opts/CURLOPT_ALTSVC.3 b/docs/libcurl/opts/CURLOPT_ALTSVC.3
deleted file mode 100644
index 7338580f5..000000000
--- a/docs/libcurl/opts/CURLOPT_ALTSVC.3
+++ /dev/null
@@ -1,91 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ALTSVC 3 "5 Feb 2019" libcurl libcurl
-.SH NAME
-CURLOPT_ALTSVC \- alt-svc cache file name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ALTSVC, char *filename);
-.fi
-.SH DESCRIPTION
-Pass in a pointer to a \fIfilename\fP to instruct libcurl to use that file as
-the Alt-Svc cache to read existing cache contents from and possibly also write
-it back to after a transfer, unless \fBCURLALTSVC_READONLYFILE\fP is set in
-\fICURLOPT_ALTSVC_CTRL(3)\fP.
-
-Specify a blank file name ("") to make libcurl not load from a file at all.
-.SH DEFAULT
-NULL. The alt-svc cache is not read nor written to file.
-.SH PROTOCOLS
-HTTPS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, CURLALTSVC_H1);
- curl_easy_setopt(curl, CURLOPT_ALTSVC, "altsvc-cache.txt");
- curl_easy_perform(curl);
-}
-.fi
-.SH "FILE FORMAT"
-A text based file with one line per alt-svc entry and each line consists of
-nine space-separated fields.
-
-An example line could look like
-
- h2 www.example 8443 h3 second.example 443 "20190808 06:18:37" 1 0
-
-The fields of that line are:
-
-.IP h2
-ALPN id for the source origin
-.IP www.example
-Host name for the source origin
-.IP 8443
-Port number for the source origin
-.IP h3
-ALPN id for the destination host
-.IP second.example
-Host name for the destination host
-.IP 443
-Port number for the destination host
-.IP 2019*
-Expiration date and time of this entry within double quotes. The date format
-is "YYYYMMDD HH:MM:SS" and the time zone is GMT.
-.IP 1
-Boolean (1 or 0) if "persist" was set for this entry
-.IP 0
-Integer priority value (not currently used)
-.SH AVAILABILITY
-Added in 7.64.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ALTSVC_CTRL (3),
-.BR CURLOPT_CONNECT_TO (3),
-.BR CURLOPT_COOKIEFILE (3),
-.BR CURLOPT_RESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_ALTSVC.md b/docs/libcurl/opts/CURLOPT_ALTSVC.md
new file mode 100644
index 000000000..6f6408474
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ALTSVC.md
@@ -0,0 +1,111 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ALTSVC
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ALTSVC_CTRL (3)
+ - CURLOPT_CONNECT_TO (3)
+ - CURLOPT_COOKIEFILE (3)
+ - CURLOPT_RESOLVE (3)
+---
+<!-- markdown-link-check-disable -->
+# NAME
+
+CURLOPT_ALTSVC - alt-svc cache file name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ALTSVC, char *filename);
+~~~
+
+# DESCRIPTION
+
+Pass in a pointer to a *filename* to instruct libcurl to use that file as
+the Alt-Svc cache to read existing cache contents from and possibly also write
+it back to after a transfer, unless **CURLALTSVC_READONLYFILE** is set in
+CURLOPT_ALTSVC_CTRL(3).
+
+Specify a blank filename ("") to make libcurl not load from a file at all.
+
+# DEFAULT
+
+NULL. The alt-svc cache is not read nor written to file.
+
+# PROTOCOLS
+
+HTTPS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, CURLALTSVC_H1);
+ curl_easy_setopt(curl, CURLOPT_ALTSVC, "altsvc-cache.txt");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# FILE FORMAT
+
+A text based file with one line per alt-svc entry and each line consists of
+nine space-separated fields.
+
+An example line could look like
+
+ h2 www.example.com 8443 h3 second.example.com 443 "20190808 06:18:37" 1 0
+
+The fields of that line are:
+
+## h2
+
+ALPN id for the source origin
+
+## www.example.comp
+
+Hostname for the source origin
+
+## 8443
+
+Port number for the source origin
+
+## h3
+
+ALPN id for the destination host
+
+## second.example.com
+
+Hostname for the destination host
+
+## 443
+
+Port number for the destination host
+
+## 2019*
+
+Expiration date and time of this entry within double quotes. The date format
+is "YYYYMMDD HH:MM:SS" and the time zone is GMT.
+
+## 1
+
+Boolean (1 or 0) if "persist" was set for this entry
+
+## 0
+
+Integer priority value (not currently used)
+
+# AVAILABILITY
+
+Added in 7.64.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3 b/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3
deleted file mode 100644
index c8318f8d0..000000000
--- a/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ALTSVC_CTRL 3 "5 Feb 2019" libcurl libcurl
-.SH NAME
-CURLOPT_ALTSVC_CTRL \- control alt-svc behavior
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-#define CURLALTSVC_READONLYFILE (1<<2)
-#define CURLALTSVC_H1 (1<<3)
-#define CURLALTSVC_H2 (1<<4)
-#define CURLALTSVC_H3 (1<<5)
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ALTSVC_CTRL, long bitmask);
-.fi
-.SH DESCRIPTION
-Populate the long \fIbitmask\fP with the correct set of features to instruct
-libcurl how to handle Alt-Svc for the transfers using this handle.
-
-libcurl only accepts Alt-Svc headers over a secure transport, meaning
-HTTPS. It also only completes a request to an alternative origin if that
-origin is properly hosted over HTTPS. These requirements are there to make
-sure both the source and the destination are legitimate.
-
-Alternative services are only used when setting up new connections. If there
-exists an existing connection to the host in the connection pool, then that is
-preferred.
-
-Setting any bit enables the alt-svc engine.
-.IP "CURLALTSVC_READONLYFILE"
-Do not write the alt-svc cache back to the file specified with
-\fICURLOPT_ALTSVC(3)\fP even if it gets updated. By default a file specified
-with that option is read and written to as deemed necessary.
-.IP "CURLALTSVC_H1"
-Accept alternative services offered over HTTP/1.1.
-.IP "CURLALTSVC_H2"
-Accept alternative services offered over HTTP/2. This is only used if libcurl
-was also built to actually support HTTP/2, otherwise this bit is ignored.
-.IP "CURLALTSVC_H3"
-Accept alternative services offered over HTTP/3. This is only used if libcurl
-was also built to actually support HTTP/3, otherwise this bit is ignored.
-.SH DEFAULT
-Alt-Svc handling is disabled by default. If \fICURLOPT_ALTSVC(3)\fP is set,
-\fICURLOPT_ALTSVC_CTRL(3)\fP has a default value corresponding to
-CURLALTSVC_H1 | CURLALTSVC_H2 | CURLALTSVC_H3 - the HTTP/2 and HTTP/3 bits are
-only set if libcurl was built with support for those versions.
-.SH PROTOCOLS
-HTTPS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, (long)CURLALTSVC_H1);
- curl_easy_setopt(curl, CURLOPT_ALTSVC, "altsvc-cache.txt");
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.64.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ALTSVC (3),
-.BR CURLOPT_CONNECT_TO (3),
-.BR CURLOPT_RESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.md b/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.md
new file mode 100644
index 000000000..538fc801a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ALTSVC_CTRL.md
@@ -0,0 +1,97 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ALTSVC_CTRL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ALTSVC (3)
+ - CURLOPT_CONNECT_TO (3)
+ - CURLOPT_RESOLVE (3)
+---
+
+# NAME
+
+CURLOPT_ALTSVC_CTRL - control alt-svc behavior
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+#define CURLALTSVC_READONLYFILE (1<<2)
+#define CURLALTSVC_H1 (1<<3)
+#define CURLALTSVC_H2 (1<<4)
+#define CURLALTSVC_H3 (1<<5)
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ALTSVC_CTRL, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Populate the long *bitmask* with the correct set of features to instruct
+libcurl how to handle Alt-Svc for the transfers using this handle.
+
+libcurl only accepts Alt-Svc headers over a secure transport, meaning
+HTTPS. It also only completes a request to an alternative origin if that
+origin is properly hosted over HTTPS. These requirements are there to make
+sure both the source and the destination are legitimate.
+
+Alternative services are only used when setting up new connections. If there
+exists an existing connection to the host in the connection pool, then that is
+preferred.
+
+Setting any bit enables the alt-svc engine.
+
+## CURLALTSVC_READONLYFILE
+
+Do not write the alt-svc cache back to the file specified with
+CURLOPT_ALTSVC(3) even if it gets updated. By default a file specified
+with that option is read and written to as deemed necessary.
+
+## CURLALTSVC_H1
+
+Accept alternative services offered over HTTP/1.1.
+
+## CURLALTSVC_H2
+
+Accept alternative services offered over HTTP/2. This is only used if libcurl
+was also built to actually support HTTP/2, otherwise this bit is ignored.
+
+## CURLALTSVC_H3
+
+Accept alternative services offered over HTTP/3. This is only used if libcurl
+was also built to actually support HTTP/3, otherwise this bit is ignored.
+
+# DEFAULT
+
+Alt-Svc handling is disabled by default. If CURLOPT_ALTSVC(3) is set,
+CURLOPT_ALTSVC_CTRL(3) has a default value corresponding to
+CURLALTSVC_H1 | CURLALTSVC_H2 | CURLALTSVC_H3 - the HTTP/2 and HTTP/3 bits are
+only set if libcurl was built with support for those versions.
+
+# PROTOCOLS
+
+HTTPS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, (long)CURLALTSVC_H1);
+ curl_easy_setopt(curl, CURLOPT_ALTSVC, "altsvc-cache.txt");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.64.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_APPEND.3 b/docs/libcurl/opts/CURLOPT_APPEND.3
deleted file mode 100644
index 3ab46b47b..000000000
--- a/docs/libcurl/opts/CURLOPT_APPEND.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_APPEND 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_APPEND \- append to the remote file
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_APPEND, long append);
-.fi
-.SH DESCRIPTION
-A long parameter set to 1 tells the library to append to the remote file
-instead of overwrite it. This is only useful when uploading to an FTP site.
-.SH DEFAULT
-0 (disabled)
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
-
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/to/newfile");
- curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
- curl_easy_setopt(curl, CURLOPT_APPEND, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was known as CURLOPT_FTPAPPEND up to 7.16.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DIRLISTONLY (3),
-.BR CURLOPT_RESUME_FROM (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_APPEND.md b/docs/libcurl/opts/CURLOPT_APPEND.md
new file mode 100644
index 000000000..d507c3812
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_APPEND.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_APPEND
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DIRLISTONLY (3)
+ - CURLOPT_RESUME_FROM (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_APPEND - append to the remote file
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_APPEND, long append);
+~~~
+
+# DESCRIPTION
+
+A long parameter set to 1 tells the library to append to the remote file
+instead of overwrite it. This is only useful when uploading to an FTP site.
+
+# DEFAULT
+
+0 (disabled)
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/to/newfile");
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(curl, CURLOPT_APPEND, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was known as CURLOPT_FTPAPPEND up to 7.16.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_AUTOREFERER.3 b/docs/libcurl/opts/CURLOPT_AUTOREFERER.3
deleted file mode 100644
index 478e221ad..000000000
--- a/docs/libcurl/opts/CURLOPT_AUTOREFERER.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_AUTOREFERER 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_AUTOREFERER \- automatically update the referer header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AUTOREFERER, long autorefer);
-.fi
-.SH DESCRIPTION
-Pass a long parameter set to 1 to enable this. When enabled, libcurl
-automatically sets the Referer: header field in HTTP requests to the full URL
-when it follows a Location: redirect to a new destination.
-
-The automatic referer is set to the full previous URL even when redirects are
-done cross-origin or following redirects to insecure protocols. This is
-considered a minor privacy leak by some.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* follow redirects */
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
-
- /* set Referer: automatically when following redirects */
- curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_EFFECTIVE_URL (3),
-.BR CURLINFO_REDIRECT_URL (3),
-.BR CURLOPT_FOLLOWLOCATION (3),
-.BR CURLOPT_REFERER (3)
diff --git a/docs/libcurl/opts/CURLOPT_AUTOREFERER.md b/docs/libcurl/opts/CURLOPT_AUTOREFERER.md
new file mode 100644
index 000000000..d201a71ad
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_AUTOREFERER.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_AUTOREFERER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_EFFECTIVE_URL (3)
+ - CURLINFO_REDIRECT_URL (3)
+ - CURLINFO_REFERER (3)
+ - CURLOPT_FOLLOWLOCATION (3)
+ - CURLOPT_REFERER (3)
+---
+
+# NAME
+
+CURLOPT_AUTOREFERER - automatically update the referer header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AUTOREFERER, long autorefer);
+~~~
+
+# DESCRIPTION
+
+Pass a long parameter set to 1 to enable this. When enabled, libcurl
+automatically sets the Referer: header field in HTTP requests to the full URL
+when it follows a Location: redirect to a new destination.
+
+The automatic referer is set to the full previous URL even when redirects are
+done cross-origin or following redirects to insecure protocols. This is
+considered a minor privacy leak by some.
+
+With CURLINFO_REFERER(3), applications can extract the actually used
+referer header after the transfer.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* follow redirects */
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+
+ /* set Referer: automatically when following redirects */
+ curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3 b/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3
deleted file mode 100644
index 9dfc3e166..000000000
--- a/docs/libcurl/opts/CURLOPT_AWS_SIGV4.3
+++ /dev/null
@@ -1,108 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_AWS_SIGV4 3 "03 Jun 2020" libcurl libcurl
-.SH NAME
-CURLOPT_AWS_SIGV4 \- V4 signature
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AWS_SIGV4, char *param);
-.fi
-.SH DESCRIPTION
-Provides AWS V4 signature authentication on HTTP(S) header.
-.PP
-Pass a char * that is the collection of specific arguments are used for
-creating outgoing authentication headers. The format of the \fIparam\fP
-option is:
-.IP provider1[:provider2[:region[:service]]]
-.IP provider1,\ provider2
-The providers arguments are used for generating some authentication parameters
-such as "Algorithm", "date", "request type" and "signed headers".
-.IP region
-The argument is a geographic area of a resources collection.
-It is extracted from the host name specified in the URL if omitted.
-.IP service
-The argument is a function provided by a cloud.
-It is extracted from the host name specified in the URL if omitted.
-.PP
-NOTE: This call set \fICURLOPT_HTTPAUTH(3)\fP to CURLAUTH_AWS_SIGV4.
-Calling \fICURLOPT_HTTPAUTH(3)\fP with CURLAUTH_AWS_SIGV4 is the same
-as calling this with \fB"aws:amz"\fP in parameter.
-.PP
-Example with "Test:Try", when curl uses the algorithm, it generates
-\fB"TEST-HMAC-SHA256"\fP for "Algorithm", \fB"x-try-date"\fP and
-\fB"X-Try-Date"\fP for "date", \fB"test4_request"\fP for "request type",
-\fB"SignedHeaders=content-type;host;x-try-date"\fP for "signed headers"
-.PP
-If you use just "test", instead of "test:try", test is used for every
-generated string.
-.SH DEFAULT
-By default, the value of this parameter is NULL.
-Calling \fICURLOPT_HTTPAUTH(3)\fP with CURLAUTH_AWS_SIGV4 is the same
-as calling this with \fB"aws:amz"\fP in parameter.
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL,
- "https://service.region.example.com/uri");
- curl_easy_setopt(c, CURLOPT_AWS_SIGV4, "provider1:provider2");
-
- /* service and region can also be set in CURLOPT_AWS_SIGV4 */
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/uri");
- curl_easy_setopt(c, CURLOPT_AWS_SIGV4,
- "provider1:provider2:region:service");
-
- curl_easy_setopt(c, CURLOPT_USERPWD, "MY_ACCESS_KEY:MY_SECRET_KEY");
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.75.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH NOTES
-This option overrides the other auth types you might have set in
-\fICURLOPT_HTTPAUTH(3)\fP which should be highlighted as this makes this auth
-method special. This method cannot be combined with other auth types.
-.PP
-A sha256 checksum of the request payload is used as input to the signature
-calculation. For POST requests, this is a checksum of the provided
-\fICURLOPT_POSTFIELDS(3)\fP. Otherwise, it's the checksum of an empty buffer.
-For requests like PUT, you can provide your own checksum in an HTTP header named
-\fBx-provider2-content-sha256\fP.
-.PP
-For \fBaws:s3\fP, a \fBx-amz-content-sha256\fP header is added to every request
-if not already present. For s3 requests with unknown payload, this header takes
-the special value "UNSIGNED-PAYLOAD".
-.SH "SEE ALSO"
-.BR CURLOPT_HEADEROPT (3),
-.BR CURLOPT_HTTPAUTH (3),
-.BR CURLOPT_HTTPHEADER (3),
-.BR CURLOPT_PROXYAUTH (3)
diff --git a/docs/libcurl/opts/CURLOPT_AWS_SIGV4.md b/docs/libcurl/opts/CURLOPT_AWS_SIGV4.md
new file mode 100644
index 000000000..e19741aa6
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_AWS_SIGV4.md
@@ -0,0 +1,118 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_AWS_SIGV4
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADEROPT (3)
+ - CURLOPT_HTTPAUTH (3)
+ - CURLOPT_HTTPHEADER (3)
+ - CURLOPT_PROXYAUTH (3)
+---
+
+# NAME
+
+CURLOPT_AWS_SIGV4 - V4 signature
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_AWS_SIGV4, char *param);
+~~~
+
+# DESCRIPTION
+
+Provides AWS V4 signature authentication on HTTP(S) header.
+
+Pass a char pointer that is the collection of specific arguments are used for
+creating outgoing authentication headers. The format of the *param* option
+is:
+
+## provider1[:provider2[:region[:service]]]
+
+## provider1, provider2
+
+The providers arguments are used for generating some authentication parameters
+such as "Algorithm", "date", "request type" and "signed headers".
+
+## region
+
+The argument is a geographic area of a resources collection.
+It is extracted from the hostname specified in the URL if omitted.
+
+## service
+
+The argument is a function provided by a cloud. It is extracted from the
+hostname specified in the URL if omitted.
+
+NOTE: This call set CURLOPT_HTTPAUTH(3) to CURLAUTH_AWS_SIGV4.
+Calling CURLOPT_HTTPAUTH(3) with CURLAUTH_AWS_SIGV4 is the same
+as calling this with **"aws:amz"** in parameter.
+
+Example with "Test:Try", when curl uses the algorithm, it generates
+**"TEST-HMAC-SHA256"** for "Algorithm", **"x-try-date"** and
+**"X-Try-Date"** for "date", **"test4_request"** for "request type",
+**"SignedHeaders=content-type;host;x-try-date"** for "signed headers"
+
+If you use just "test", instead of "test:try", test is used for every
+generated string.
+
+# DEFAULT
+
+By default, the value of this parameter is NULL.
+Calling CURLOPT_HTTPAUTH(3) with CURLAUTH_AWS_SIGV4 is the same
+as calling this with **"aws:amz"** in parameter.
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "https://service.region.example.com/uri");
+ curl_easy_setopt(curl, CURLOPT_AWS_SIGV4, "provider1:provider2");
+
+ /* service and region can also be set in CURLOPT_AWS_SIGV4 */
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/uri");
+ curl_easy_setopt(curl, CURLOPT_AWS_SIGV4,
+ "provider1:provider2:region:service");
+
+ curl_easy_setopt(curl, CURLOPT_USERPWD, "MY_ACCESS_KEY:MY_SECRET_KEY");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.75.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+
+# NOTES
+
+This option overrides the other auth types you might have set in
+CURLOPT_HTTPAUTH(3) which should be highlighted as this makes this auth
+method special. This method cannot be combined with other auth types.
+
+A sha256 checksum of the request payload is used as input to the signature
+calculation. For POST requests, this is a checksum of the provided
+CURLOPT_POSTFIELDS(3). Otherwise, it is the checksum of an empty buffer. For
+requests like PUT, you can provide your own checksum in an HTTP header named
+**x-provider2-content-sha256**.
+
+For **aws:s3**, a **x-amz-content-sha256** header is added to every request
+if not already present. For s3 requests with unknown payload, this header takes
+the special value "UNSIGNED-PAYLOAD".
diff --git a/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3 b/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3
deleted file mode 100644
index 6a14076ee..000000000
--- a/docs/libcurl/opts/CURLOPT_BUFFERSIZE.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_BUFFERSIZE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_BUFFERSIZE \- receive buffer size
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_BUFFERSIZE, long size);
-.fi
-.SH DESCRIPTION
-Pass a long specifying your preferred \fIsize\fP (in bytes) for the receive
-buffer in libcurl. The main point of this would be that the write callback
-gets called more often and with smaller chunks. Secondly, for some protocols,
-there is a benefit of having a larger buffer for performance.
-
-This is just treated as a request, not an order. You cannot be guaranteed to
-actually get the given size.
-
-This buffer size is by default \fICURL_MAX_WRITE_SIZE\fP (16kB). The maximum
-buffer size allowed to be set is \fICURL_MAX_READ_SIZE\fP (10MB). The minimum
-buffer size allowed to be set is 1024.
-
-DO NOT set this option on a handle that is currently used for an active
-transfer as that may lead to unintended consequences.
-
-The maximum size was 512kB until 7.88.0.
-.SH DEFAULT
-CURL_MAX_WRITE_SIZE (16kB)
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/foo.bin");
-
- /* ask libcurl to allocate a larger receive buffer */
- curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 120000L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10. Growing the buffer was added in 7.53.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3),
-.BR CURLOPT_MAXFILESIZE (3),
-.BR CURLOPT_UPLOAD_BUFFERSIZE (3),
-.BR CURLOPT_WRITEFUNCTION (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_BUFFERSIZE.md b/docs/libcurl/opts/CURLOPT_BUFFERSIZE.md
new file mode 100644
index 000000000..1faebeef5
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_BUFFERSIZE.md
@@ -0,0 +1,79 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_BUFFERSIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAXFILESIZE (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+ - CURLOPT_UPLOAD_BUFFERSIZE (3)
+ - CURLOPT_WRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_BUFFERSIZE - receive buffer size
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_BUFFERSIZE, long size);
+~~~
+
+# DESCRIPTION
+
+Pass a long specifying your preferred *size* (in bytes) for the receive buffer
+in libcurl. The main point of this would be that the write callback gets
+called more often and with smaller chunks. Secondly, for some protocols, there
+is a benefit of having a larger buffer for performance.
+
+This is just treated as a request, not an order. You cannot be guaranteed to
+actually get the given size.
+
+This buffer size is by default *CURL_MAX_WRITE_SIZE* (16kB). The maximum
+buffer size allowed to be set is *CURL_MAX_READ_SIZE* (10MB). The minimum
+buffer size allowed to be set is 1024.
+
+DO NOT set this option on a handle that is currently used for an active
+transfer as that may lead to unintended consequences.
+
+The maximum size was 512kB until 7.88.0.
+
+# DEFAULT
+
+CURL_MAX_WRITE_SIZE (16kB)
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/foo.bin");
+
+ /* ask libcurl to allocate a larger receive buffer */
+ curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 120000L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10. Growing the buffer was added in 7.53.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO.3 b/docs/libcurl/opts/CURLOPT_CAINFO.3
deleted file mode 100644
index dc94c0cdc..000000000
--- a/docs/libcurl/opts/CURLOPT_CAINFO.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CAINFO 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CAINFO \- path to Certificate Authority (CA) bundle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO, char *path);
-.fi
-.SH DESCRIPTION
-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
-server's certificate, \fICURLOPT_CAINFO(3)\fP need not even indicate an
-accessible file.
-
-This option is by default set to the system path where libcurl's CA
-certificate bundle is assumed to be stored, as established at build time.
-
-(iOS and macOS) When curl uses Secure Transport this option is supported. If
-the option is not set, then curl uses the certificates in the system and user
-Keychain to verify the peer.
-
-(Schannel) This option is supported for Schannel in Windows 7 or later but we
-recommend not using it until Windows 8 since it works better starting then.
-If the option is not set, then curl uses the certificates in the Windows'
-store of root certificates (the default for Schannel).
-
-The application does not have to keep the string around after setting this
-option.
-
-The default value for this can be figured out with \fICURLINFO_CAINFO(3)\fP.
-.SH DEFAULT
-Built-in system specific. When curl is built with Secure Transport or
-Schannel, this option is not set by default.
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/certs/cabundle.pem");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-For the SSL engines that do not support certificate files the
-\fICURLOPT_CAINFO(3)\fP option is ignored. Schannel support added in libcurl
-7.60.
-.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 CURLINFO_CAINFO (3),
-.BR CURLOPT_CA_CACHE_TIMEOUT (3),
-.BR CURLOPT_CAINFO_BLOB (3),
-.BR CURLOPT_CAPATH (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO.md b/docs/libcurl/opts/CURLOPT_CAINFO.md
new file mode 100644
index 000000000..c46073ff8
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CAINFO.md
@@ -0,0 +1,87 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CAINFO
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CAINFO (3)
+ - CURLOPT_CAINFO_BLOB (3)
+ - CURLOPT_CAPATH (3)
+ - CURLOPT_CA_CACHE_TIMEOUT (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_CAINFO - path to Certificate Authority (CA) bundle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO, char *path);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to a null-terminated string naming a file holding one or
+more certificates to verify the peer with.
+
+If CURLOPT_SSL_VERIFYPEER(3) is zero and you avoid verifying the
+server's certificate, CURLOPT_CAINFO(3) need not even indicate an
+accessible file.
+
+This option is by default set to the system path where libcurl's CA
+certificate bundle is assumed to be stored, as established at build time.
+
+(iOS and macOS) When curl uses Secure Transport this option is supported. If
+the option is not set, then curl uses the certificates in the system and user
+Keychain to verify the peer.
+
+(Schannel) This option is supported for Schannel in Windows 7 or later but we
+recommend not using it until Windows 8 since it works better starting then.
+If the option is not set, then curl uses the certificates in the Windows'
+store of root certificates (the default for Schannel).
+
+The application does not have to keep the string around after setting this
+option.
+
+The default value for this can be figured out with CURLINFO_CAINFO(3).
+
+# DEFAULT
+
+Built-in system specific. When curl is built with Secure Transport or
+Schannel, this option is not set by default.
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/certs/cabundle.pem");
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+For the SSL engines that do not support certificate files the
+CURLOPT_CAINFO(3) option is ignored. Schannel support added in libcurl
+7.60.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3 b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
deleted file mode 100644
index ebb27111b..000000000
--- a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CAINFO_BLOB 3 "31 March 2021" libcurl libcurl
-.SH NAME
-CURLOPT_CAINFO_BLOB \- Certificate Authority (CA) bundle in PEM format
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO_BLOB,
- struct curl_blob *stblob);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a curl_blob structure, which contains information (pointer
-and size) about a memory block with binary data of PEM encoded content holding
-one or more certificates to verify the HTTPS server with.
-
-If \fICURLOPT_SSL_VERIFYPEER(3)\fP is zero and you avoid verifying the
-server's certificate, \fICURLOPT_CAINFO_BLOB(3)\fP is not needed.
-
-This option overrides \fICURLOPT_CAINFO(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-char *strpem; /* strpem must point to a PEM string */
-CURL *curl = curl_easy_init();
-if(curl) {
- struct curl_blob blob;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- blob.data = strpem;
- blob.len = strlen(strpem);
- blob.flags = CURL_BLOB_COPY;
- curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.77.0.
-
-This option is supported by the BearSSL (since 7.79.0), mbedTLS (since 7.81.0),
-rustls (since 7.82.0), wolfSSL (since 8.2.0), OpenSSL, Secure Transport and Schannel 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_CAINFO (3),
-.BR CURLOPT_CAPATH (3),
-.BR CURLOPT_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3)
diff --git a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md
new file mode 100644
index 000000000..be30446ff
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md
@@ -0,0 +1,84 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CAINFO_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_CAPATH (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_CAINFO_BLOB - Certificate Authority (CA) bundle in PEM format
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO_BLOB,
+ struct curl_blob *stblob);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a curl_blob structure, which contains information (pointer
+and size) about a memory block with binary data of PEM encoded content holding
+one or more certificates to verify the HTTPS server with.
+
+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.
+
+If CURLOPT_SSL_VERIFYPEER(3) is zero and you avoid verifying the
+server's certificate, CURLOPT_CAINFO_BLOB(3) is not needed.
+
+This option overrides CURLOPT_CAINFO(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+#include <string.h>
+
+int main(void)
+{
+ char *strpem; /* strpem must point to a PEM string */
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ struct curl_blob blob;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ blob.data = strpem;
+ blob.len = strlen(strpem);
+ blob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.77.0.
+
+This option is supported by the BearSSL (since 7.79.0), mbedTLS (since
+7.81.0), rustls (since 7.82.0), wolfSSL (since 8.2.0), OpenSSL, Secure
+Transport and Schannel backends.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_CAPATH.3 b/docs/libcurl/opts/CURLOPT_CAPATH.3
deleted file mode 100644
index 5a453beca..000000000
--- a/docs/libcurl/opts/CURLOPT_CAPATH.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CAPATH 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CAPATH \- directory holding CA certificates
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAPATH, char *capath);
-.fi
-.SH DESCRIPTION
-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
-\fICURLOPT_SSL_VERIFYPEER(3)\fP option.
-
-The \fICURLOPT_CAPATH(3)\fP function apparently does not work in Windows due
-to some limitation in OpenSSL.
-
-The application does not have to keep the string around after setting this
-option.
-
-The default value for this can be figured out with \fICURLINFO_CAPATH(3)\fP.
-.SH DEFAULT
-A default path detected at build time.
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_CAPATH, "/etc/cert-dir");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option is supported by the OpenSSL, GnuTLS and mbedTLS (since 7.56.0)
-backends.
-.SH RETURN VALUE
-CURLE_OK if supported; or an error such as:
-
-CURLE_NOT_BUILT_IN - Not supported by the SSL backend
-
-CURLE_UNKNOWN_OPTION
-
-CURLE_OUT_OF_MEMORY
-.SH "SEE ALSO"
-.BR CURLINFO_CAPATH (3),
-.BR CURLOPT_CAINFO (3),
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_CAPATH.md b/docs/libcurl/opts/CURLOPT_CAPATH.md
new file mode 100644
index 000000000..ff1362f52
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CAPATH.md
@@ -0,0 +1,79 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CAPATH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CAPATH (3)
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_CAPATH - directory holding CA certificates
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAPATH, char *capath);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer 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
+CURLOPT_SSL_VERIFYPEER(3) option.
+
+The CURLOPT_CAPATH(3) function apparently does not work in Windows due
+to some limitation in OpenSSL.
+
+The application does not have to keep the string around after setting this
+option.
+
+The default value for this can be figured out with CURLINFO_CAPATH(3).
+
+# DEFAULT
+
+A default path detected at build time.
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_CAPATH, "/etc/cert-dir");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option is supported by the OpenSSL, GnuTLS and mbedTLS (since 7.56.0)
+backends.
+
+# RETURN VALUE
+
+CURLE_OK if supported; or an error such as:
+
+CURLE_NOT_BUILT_IN - Not supported by the SSL backend
+
+CURLE_UNKNOWN_OPTION
+
+CURLE_OUT_OF_MEMORY
diff --git a/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.3
deleted file mode 100644
index 36d2bf74a..000000000
--- a/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CA_CACHE_TIMEOUT 3 "21 Dec 2022" libcurl libcurl
-.SH NAME
-CURLOPT_CA_CACHE_TIMEOUT \- life-time for cached certificate stores
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CA_CACHE_TIMEOUT, long age);
-.fi
-.SH DESCRIPTION
-Pass a long, this sets the timeout in seconds. This tells libcurl the maximum
-time any cached certificate store it has in memory may be kept and reused for
-new connections. Once the timeout has expired, a subsequent fetch requiring a
-certificate has to reload it.
-
-Building a certificate store from a \fICURLOPT_CAINFO(3)\fP file is a slow
-operation so curl may cache the generated certificate store internally to speed
-up future connections.
-
-Set to zero to completely disable caching, or set to -1 to retain the cached
-store remain forever. By default, libcurl caches this info for 24 hours.
-.SH DEFAULT
-86400 (24 hours)
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* only reuse certificate stores for a short time */
- curl_easy_setopt(curl, CURLOPT_CA_CACHE_TIMEOUT, 60L);
-
- ret = curl_easy_perform(curl);
-
- /* in this second request, the cache is not used if more than
- sixty seconds passed since the previous connection */
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was added in curl 7.87.0.
-
-Currently the only SSL backend to implement this certificate store caching
-functionality is the OpenSSL (and forks) backend.
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_CAINFO (3),
-.BR CURLOPT_CAINFO_BLOB (3),
-.BR CURLOPT_CAPATH (3),
-.BR CURLOPT_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3)
diff --git a/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.md b/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.md
new file mode 100644
index 000000000..ef52f976d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CA_CACHE_TIMEOUT.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CA_CACHE_TIMEOUT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_CAINFO_BLOB (3)
+ - CURLOPT_CAPATH (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_CA_CACHE_TIMEOUT - life-time for cached certificate stores
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CA_CACHE_TIMEOUT, long age);
+~~~
+
+# DESCRIPTION
+
+Pass a long, this sets the timeout in seconds. This tells libcurl the maximum
+time any cached certificate store it has in memory may be kept and reused for
+new connections. Once the timeout has expired, a subsequent fetch requiring a
+certificate has to reload it.
+
+Building a certificate store from a CURLOPT_CAINFO(3) file is a slow
+operation so curl may cache the generated certificate store internally to speed
+up future connections.
+
+Set to zero to completely disable caching, or set to -1 to retain the cached
+store remain forever. By default, libcurl caches this info for 24 hours.
+
+# DEFAULT
+
+86400 (24 hours)
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* only reuse certificate stores for a short time */
+ curl_easy_setopt(curl, CURLOPT_CA_CACHE_TIMEOUT, 60L);
+
+ res = curl_easy_perform(curl);
+
+ /* in this second request, the cache is not used if more than
+ sixty seconds passed since the previous connection */
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was added in curl 7.87.0.
+
+This option is supported by OpenSSL and its forks (since 7.87.0) and Schannel
+(since 8.5.0).
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_CERTINFO.3 b/docs/libcurl/opts/CURLOPT_CERTINFO.3
deleted file mode 100644
index 146362960..000000000
--- a/docs/libcurl/opts/CURLOPT_CERTINFO.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CERTINFO 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CERTINFO \- request SSL certificate information
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CERTINFO, long certinfo);
-.fi
-.SH DESCRIPTION
-Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With
-this enabled, libcurl extracts lots of information and data about the
-certificates in the certificate chain used in the SSL connection. This data
-may then be retrieved after a transfer using \fIcurl_easy_getinfo(3)\fP and
-its option \fICURLINFO_CERTINFO(3)\fP.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All TLS-based
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
-
- /* connect to any HTTPS site, trusted or not */
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
-
- curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
-
- res = curl_easy_perform(curl);
-
- if (!res) {
- struct curl_certinfo *ci;
- res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci);
-
- if (!res) {
- printf("%d certs!\\n", ci->num_of_certs);
-
- for(i = 0; i < ci->num_of_certs; i++) {
- struct curl_slist *slist;
-
- for(slist = ci->certinfo[i]; slist; slist = slist->next)
- printf("%s\\n", slist->data);
- }
- }
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option is supported by the OpenSSL, GnuTLS, Schannel and Secure
-Transport backends. Schannel support added in 7.50.0. Secure Transport support
-added in 7.79.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_CAINFO (3),
-.BR CURLINFO_CAPATH (3),
-.BR CURLINFO_CERTINFO (3),
-.BR CURLOPT_CAINFO (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_CERTINFO.md b/docs/libcurl/opts/CURLOPT_CERTINFO.md
new file mode 100644
index 000000000..a69e1e950
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CERTINFO.md
@@ -0,0 +1,90 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CERTINFO
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CAINFO (3)
+ - CURLINFO_CAPATH (3)
+ - CURLINFO_CERTINFO (3)
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_CERTINFO - request SSL certificate information
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CERTINFO, long certinfo);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With
+this enabled, libcurl extracts lots of information and data about the
+certificates in the certificate chain used in the SSL connection. This data
+may then be retrieved after a transfer using curl_easy_getinfo(3) and
+its option CURLINFO_CERTINFO(3).
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All TLS-based
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/");
+
+ /* connect to any HTTPS site, trusted or not */
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+
+ curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L);
+
+ res = curl_easy_perform(curl);
+
+ if(!res) {
+ struct curl_certinfo *ci;
+ res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci);
+
+ if(!res) {
+ int i;
+ printf("%d certs!\n", ci->num_of_certs);
+
+ for(i = 0; i < ci->num_of_certs; i++) {
+ struct curl_slist *slist;
+
+ for(slist = ci->certinfo[i]; slist; slist = slist->next)
+ printf("%s\n", slist->data);
+ }
+ }
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option is supported by the OpenSSL, GnuTLS, Schannel and Secure
+Transport backends. Schannel support added in 7.50.0. Secure Transport support
+added in 7.79.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3
deleted file mode 100644
index a8b227357..000000000
--- a/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.3
+++ /dev/null
@@ -1,144 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CHUNK_BGN_FUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CHUNK_BGN_FUNCTION \- callback before a transfer with FTP wildcard match
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-struct curl_fileinfo {
- char *filename;
- curlfiletype filetype;
- time_t time; /* always zero! */
- unsigned int perm;
- int uid;
- int gid;
- curl_off_t size;
- long int hardlinks;
-
- struct {
- /* If some of these fields is not NULL, it is a pointer to b_data. */
- char *time;
- char *perm;
- char *user;
- char *group;
- char *target; /* pointer to the target filename of a symlink */
- } strings;
-
- unsigned int flags;
-
- /* used internally */
- char *b_data;
- size_t b_size;
- size_t b_used;
-};
-
-long chunk_bgn_callback(const void *transfer_info, void *ptr,
- int remains);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_BGN_FUNCTION,
- chunk_bgn_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl before a part of the stream is
-going to be transferred (if the transfer supports chunks).
-
-The \fItransfer_info\fP pointer points to a \fBcurl_fileinfo\fP struct with
-details about the file that is about to get transferred.
-
-This callback makes sense only when using the \fICURLOPT_WILDCARDMATCH(3)\fP
-option for now.
-
-The target of transfer_info parameter is a "feature depended" structure. For
-the FTP wildcard download, the target is \fBcurl_fileinfo\fP structure (see
-\fIcurl/curl.h\fP). The parameter \fIptr\fP is a pointer given by
-\fICURLOPT_CHUNK_DATA(3)\fP. The parameter remains contains number of chunks
-remaining per the transfer. If the feature is not available, the parameter has
-zero value.
-
-Return \fICURL_CHUNK_BGN_FUNC_OK\fP if everything is fine,
-\fICURL_CHUNK_BGN_FUNC_SKIP\fP if you want to skip the concrete chunk or
-\fICURL_CHUNK_BGN_FUNC_FAIL\fP to tell libcurl to stop if some error occurred.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-static long file_is_coming(struct curl_fileinfo *finfo,
- struct callback_data *data,
- int remains)
-{
- printf("%3d %40s %10luB ", remains, finfo->filename,
- (unsigned long)finfo->size);
-
- switch(finfo->filetype) {
- case CURLFILETYPE_DIRECTORY:
- printf(" DIR\\n");
- break;
- case CURLFILETYPE_FILE:
- printf("FILE ");
- break;
- default:
- printf("OTHER\\n");
- break;
- }
-
- if(finfo->filetype == CURLFILETYPE_FILE) {
- /* do not transfer files >= 50B */
- if(finfo->size > 50) {
- printf("SKIPPED\\n");
- return CURL_CHUNK_BGN_FUNC_SKIP;
- }
-
- data->output = fopen(finfo->filename, "wb");
- if(!data->output) {
- return CURL_CHUNK_BGN_FUNC_FAIL;
- }
- }
-
- return CURL_CHUNK_BGN_FUNC_OK;
-}
-
-int main()
-{
- /* data for callback */
- struct callback_data callback_info;
-
- /* callback is called before download of concrete file started */
- curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming);
- curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &callback_info);
-}
-.fi
-.SH AVAILABILITY
-This was added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CHUNK_END_FUNCTION (3),
-.BR CURLOPT_WILDCARDMATCH (3)
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.md b/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.md
new file mode 100644
index 000000000..a208c9bbe
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CHUNK_BGN_FUNCTION.md
@@ -0,0 +1,152 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CHUNK_BGN_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CHUNK_END_FUNCTION (3)
+ - CURLOPT_WILDCARDMATCH (3)
+---
+
+# NAME
+
+CURLOPT_CHUNK_BGN_FUNCTION - callback before a transfer with FTP wildcard match
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+struct curl_fileinfo {
+ char *filename;
+ curlfiletype filetype;
+ time_t time; /* always zero! */
+ unsigned int perm;
+ int uid;
+ int gid;
+ curl_off_t size;
+ long int hardlinks;
+
+ struct {
+ /* If some of these fields is not NULL, it is a pointer to b_data. */
+ char *time;
+ char *perm;
+ char *user;
+ char *group;
+ char *target; /* pointer to the target filename of a symlink */
+ } strings;
+
+ unsigned int flags;
+
+ /* used internally */
+ char *b_data;
+ size_t b_size;
+ size_t b_used;
+};
+
+long chunk_bgn_callback(const void *transfer_info, void *ptr,
+ int remains);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_BGN_FUNCTION,
+ chunk_bgn_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl before a part of the stream is
+going to be transferred (if the transfer supports chunks).
+
+The *transfer_info* pointer points to a **curl_fileinfo** struct with
+details about the file that is about to get transferred.
+
+This callback makes sense only when using the CURLOPT_WILDCARDMATCH(3)
+option for now.
+
+The target of transfer_info parameter is a "feature depended" structure. For
+the FTP wildcard download, the target is **curl_fileinfo** structure (see
+*curl/curl.h*). The parameter *ptr* is a pointer given by
+CURLOPT_CHUNK_DATA(3). The parameter remains contains number of chunks
+remaining per the transfer. If the feature is not available, the parameter has
+zero value.
+
+Return *CURL_CHUNK_BGN_FUNC_OK* if everything is fine,
+*CURL_CHUNK_BGN_FUNC_SKIP* if you want to skip the concrete chunk or
+*CURL_CHUNK_BGN_FUNC_FAIL* to tell libcurl to stop if some error occurred.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+#include <stdio.h>
+
+struct callback_data {
+ FILE *output;
+};
+
+static long file_is_coming(struct curl_fileinfo *finfo,
+ void *ptr,
+ int remains)
+{
+ struct callback_data *data = ptr;
+ printf("%3d %40s %10luB ", remains, finfo->filename,
+ (unsigned long)finfo->size);
+
+ switch(finfo->filetype) {
+ case CURLFILETYPE_DIRECTORY:
+ printf(" DIR\n");
+ break;
+ case CURLFILETYPE_FILE:
+ printf("FILE ");
+ break;
+ default:
+ printf("OTHER\n");
+ break;
+ }
+
+ if(finfo->filetype == CURLFILETYPE_FILE) {
+ /* do not transfer files >= 50B */
+ if(finfo->size > 50) {
+ printf("SKIPPED\n");
+ return CURL_CHUNK_BGN_FUNC_SKIP;
+ }
+
+ data->output = fopen(finfo->filename, "wb");
+ if(!data->output) {
+ return CURL_CHUNK_BGN_FUNC_FAIL;
+ }
+ }
+
+ return CURL_CHUNK_BGN_FUNC_OK;
+}
+
+int main()
+{
+ /* data for callback */
+ struct callback_data callback_info;
+
+ CURL *curl = curl_easy_init();
+
+ /* callback is called before download of concrete file started */
+ curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming);
+ curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &callback_info);
+}
+~~~
+
+# AVAILABILITY
+
+This was added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3 b/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3
deleted file mode 100644
index 785c010cf..000000000
--- a/docs/libcurl/opts/CURLOPT_CHUNK_DATA.3
+++ /dev/null
@@ -1,95 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CHUNK_DATA 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CHUNK_DATA \- pointer passed to the FTP chunk callbacks
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_DATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP that is untouched by libcurl and passed as the ptr
-argument to the \fICURLOPT_CHUNK_BGN_FUNCTION(3)\fP and
-\fICURLOPT_CHUNK_END_FUNCTION(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-static long file_is_coming(struct curl_fileinfo *finfo,
- struct callback_data *data,
- int remains)
-{
- printf("%3d %40s %10luB ", remains, finfo->filename,
- (unsigned long)finfo->size);
-
- switch(finfo->filetype) {
- case CURLFILETYPE_DIRECTORY:
- printf(" DIR\\n");
- break;
- case CURLFILETYPE_FILE:
- printf("FILE ");
- break;
- default:
- printf("OTHER\\n");
- break;
- }
-
- if(finfo->filetype == CURLFILETYPE_FILE) {
- /* do not transfer files >= 50B */
- if(finfo->size > 50) {
- printf("SKIPPED\\n");
- return CURL_CHUNK_BGN_FUNC_SKIP;
- }
-
- data->output = fopen(finfo->filename, "wb");
- if(!data->output) {
- return CURL_CHUNK_BGN_FUNC_FAIL;
- }
- }
-
- return CURL_CHUNK_BGN_FUNC_OK;
-}
-
-int main()
-{
- /* data for callback */
- struct callback_data callback_info;
-
- /* callback is called before download of concrete file started */
- curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming);
- curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &callback_info);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CHUNK_BGN_FUNCTION (3),
-.BR CURLOPT_WILDCARDMATCH (3)
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_DATA.md b/docs/libcurl/opts/CURLOPT_CHUNK_DATA.md
new file mode 100644
index 000000000..3640ec8df
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CHUNK_DATA.md
@@ -0,0 +1,102 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CHUNK_DATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CHUNK_BGN_FUNCTION (3)
+ - CURLOPT_WILDCARDMATCH (3)
+---
+
+# NAME
+
+CURLOPT_CHUNK_DATA - pointer passed to the FTP chunk callbacks
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_DATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* that is untouched by libcurl and passed as the ptr
+argument to the CURLOPT_CHUNK_BGN_FUNCTION(3) and
+CURLOPT_CHUNK_END_FUNCTION(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+#include <stdio.h>
+
+struct callback_data {
+ FILE *output;
+};
+
+static long file_is_coming(struct curl_fileinfo *finfo,
+ void *ptr,
+ int remains)
+{
+ struct callback_data *data = ptr;
+ printf("%3d %40s %10luB ", remains, finfo->filename,
+ (unsigned long)finfo->size);
+
+ switch(finfo->filetype) {
+ case CURLFILETYPE_DIRECTORY:
+ printf(" DIR\n");
+ break;
+ case CURLFILETYPE_FILE:
+ printf("FILE ");
+ break;
+ default:
+ printf("OTHER\n");
+ break;
+ }
+
+ if(finfo->filetype == CURLFILETYPE_FILE) {
+ /* do not transfer files >= 50B */
+ if(finfo->size > 50) {
+ printf("SKIPPED\n");
+ return CURL_CHUNK_BGN_FUNC_SKIP;
+ }
+
+ data->output = fopen(finfo->filename, "wb");
+ if(!data->output) {
+ return CURL_CHUNK_BGN_FUNC_FAIL;
+ }
+ }
+
+ return CURL_CHUNK_BGN_FUNC_OK;
+}
+
+int main()
+{
+ /* data for callback */
+ struct callback_data callback_info;
+
+ CURL *curl = curl_easy_init();
+
+ /* callback is called before download of concrete file started */
+ curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming);
+ curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &callback_info);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3
deleted file mode 100644
index c5b752b67..000000000
--- a/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CHUNK_END_FUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CHUNK_END_FUNCTION \- callback after a transfer with FTP wildcard match
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-long chunk_end_callback(void *ptr);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_END_FUNCTION,
- chunk_end_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This function gets called by libcurl as soon as a part of the stream has been
-transferred (or skipped).
-
-Return \fICURL_CHUNK_END_FUNC_OK\fP if everything is fine or
-\fBCURL_CHUNK_END_FUNC_FAIL\fP to tell the lib to stop if some error occurred.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-static long file_is_downloaded(struct callback_data *data)
-{
- if(data->output) {
- fclose(data->output);
- data->output = 0x0;
- }
- return CURL_CHUNK_END_FUNC_OK;
-}
-
-int main()
-{
- /* data for callback */
- struct callback_data callback_info;
- curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);
- curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &callback_info);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CHUNK_BGN_FUNCTION (3),
-.BR CURLOPT_WILDCARDMATCH (3)
diff --git a/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.md b/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.md
new file mode 100644
index 000000000..2d67afe20
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CHUNK_END_FUNCTION.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CHUNK_END_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CHUNK_BGN_FUNCTION (3)
+ - CURLOPT_WILDCARDMATCH (3)
+---
+
+# NAME
+
+CURLOPT_CHUNK_END_FUNCTION - callback after a transfer with FTP wildcard match
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+long chunk_end_callback(void *ptr);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CHUNK_END_FUNCTION,
+ chunk_end_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This function gets called by libcurl as soon as a part of the stream has been
+transferred (or skipped).
+
+Return *CURL_CHUNK_END_FUNC_OK* if everything is fine or
+**CURL_CHUNK_END_FUNC_FAIL** to tell the lib to stop if some error occurred.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+#include <stdio.h>
+
+struct callback_data {
+ FILE *output;
+};
+
+static long file_is_downloaded(struct callback_data *data)
+{
+ if(data->output) {
+ fclose(data->output);
+ data->output = 0x0;
+ }
+ return CURL_CHUNK_END_FUNC_OK;
+}
+
+int main()
+{
+ /* data for callback */
+ struct callback_data callback_info;
+
+ CURL *curl = curl_easy_init();
+
+ curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);
+ curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &callback_info);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3 b/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3
deleted file mode 100644
index 25601d4a6..000000000
--- a/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.3
+++ /dev/null
@@ -1,61 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CLOSESOCKETDATA 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CLOSESOCKETDATA \- pointer passed to the socket close callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CLOSESOCKETDATA,
- void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP that remains untouched by libcurl and passed as the first
-argument in the closesocket callback set with
-\fICURLOPT_CLOSESOCKETFUNCTION(3)\fP.
-.SH DEFAULT
-The default value of this parameter is NULL.
-.SH PROTOCOLS
-All except file:
-.SH EXAMPLE
-.nf
-static int closesocket(void *clientp, curl_socket_t item)
-{
- printf("libcurl wants to close %d now\\n", (int)item);
- return 0;
-}
-
-/* call this function to close sockets */
-curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket);
-curl_easy_setopt(curl, CURLOPT_CLOSESOCKETDATA, &sockfd);
-.fi
-.SH AVAILABILITY
-Added in 7.21.7
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CLOSESOCKETFUNCTION (3),
-.BR CURLOPT_OPENSOCKETFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.md b/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.md
new file mode 100644
index 000000000..2dd74777b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CLOSESOCKETDATA.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CLOSESOCKETDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CLOSESOCKETFUNCTION (3)
+ - CURLOPT_OPENSOCKETFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_CLOSESOCKETDATA - pointer passed to the socket close callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CLOSESOCKETDATA,
+ void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* that remains untouched by libcurl and passed as the first
+argument in the closesocket callback set with
+CURLOPT_CLOSESOCKETFUNCTION(3).
+
+# DEFAULT
+
+The default value of this parameter is NULL.
+
+# PROTOCOLS
+
+All except file:
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static int closesocket(void *clientp, curl_socket_t item)
+{
+ struct priv *my = clientp;
+ printf("our ptr: %p\n", my->custom);
+
+ printf("libcurl wants to close %d now\n", (int)item);
+ return 0;
+}
+
+int main(void)
+{
+ struct priv myown;
+ CURL *curl = curl_easy_init();
+
+ /* call this function to close sockets */
+ curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket);
+ curl_easy_setopt(curl, CURLOPT_CLOSESOCKETDATA, &myown);
+
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.7
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3 b/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3
deleted file mode 100644
index 27efd61af..000000000
--- a/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CLOSESOCKETFUNCTION 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CLOSESOCKETFUNCTION \- callback to socket close replacement
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int closesocket_callback(void *clientp, curl_socket_t item);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CLOSESOCKETFUNCTION,
- closesocket_callback);
-.fi
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl instead of the \fIclose(3)\fP or
-\fIclosesocket(3)\fP call when sockets are closed (not for any other file
-descriptors). This is pretty much the reverse to the
-\fICURLOPT_OPENSOCKETFUNCTION(3)\fP option. Return 0 to signal success and 1
-if there was an error.
-
-The \fIclientp\fP pointer is set with
-\fICURLOPT_CLOSESOCKETDATA(3)\fP. \fIitem\fP is the socket libcurl wants to be
-closed.
-.SH DEFAULT
-By default libcurl uses the standard socket close function.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static int closesocket(void *clientp, curl_socket_t item)
-{
- printf("libcurl wants to close %d now\\n", (int)item);
- return 0;
-}
-
-/* call this function to close sockets */
-curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket);
-curl_easy_setopt(curl, CURLOPT_CLOSESOCKETDATA, &sockfd);
-.fi
-.SH AVAILABILITY
-Added in 7.21.7
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CLOSESOCKETDATA (3),
-.BR CURLOPT_OPENSOCKETFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.md b/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.md
new file mode 100644
index 000000000..e93e28c1e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CLOSESOCKETFUNCTION.md
@@ -0,0 +1,86 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CLOSESOCKETFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CLOSESOCKETDATA (3)
+ - CURLOPT_OPENSOCKETFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_CLOSESOCKETFUNCTION - callback to socket close replacement
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int closesocket_callback(void *clientp, curl_socket_t item);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CLOSESOCKETFUNCTION,
+ closesocket_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl instead of the *close(3)* or
+*closesocket(3)* call when sockets are closed (not for any other file
+descriptors). This is pretty much the reverse to the
+CURLOPT_OPENSOCKETFUNCTION(3) option. Return 0 to signal success and 1
+if there was an error.
+
+The *clientp* pointer is set with
+CURLOPT_CLOSESOCKETDATA(3). *item* is the socket libcurl wants to be
+closed.
+
+# DEFAULT
+
+By default libcurl uses the standard socket close function.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static int closesocket(void *clientp, curl_socket_t item)
+{
+ struct priv *my = clientp;
+ printf("our ptr: %p\n", my->custom);
+
+ printf("libcurl wants to close %d now\n", (int)item);
+ return 0;
+}
+
+int main(void)
+{
+ struct priv myown;
+ CURL *curl = curl_easy_init();
+
+ /* call this function to close sockets */
+ curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket);
+ curl_easy_setopt(curl, CURLOPT_CLOSESOCKETDATA, &myown);
+
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.7
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3 b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3
deleted file mode 100644
index c9091cb52..000000000
--- a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CONNECTTIMEOUT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CONNECTTIMEOUT \- timeout for the connect phase
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT, long timeout);
-.fi
-.SH DESCRIPTION
-Pass a long. It should contain the maximum time in seconds that you allow the
-connection phase to the server to take. This timeout only limits the
-connection phase, it has no impact once it has connected. Set to zero to
-switch to the default built-in connection timeout - 300 seconds. See also the
-\fICURLOPT_TIMEOUT(3)\fP option.
-
-\fICURLOPT_CONNECTTIMEOUT_MS(3)\fP is the same function but set in milliseconds.
-
-If both \fICURLOPT_CONNECTTIMEOUT(3)\fP and \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
-are set, the value set last is used.
-
-The "connection phase" is considered complete when the requested TCP, TLS or
-QUIC handshakes are done.
-
-The connection timeout set with \fICURLOPT_CONNECTTIMEOUT(3)\fP is included in
-the general all-covering \fICURLOPT_TIMEOUT(3)\fP.
-
-With \fICURLOPT_CONNECTTIMEOUT(3)\fP set to 3 and \fICURLOPT_TIMEOUT(3)\fP set
-to 5, the operation can never last longer than 5 seconds, and the connection
-phase cannot last longer than 3 seconds.
-
-With \fICURLOPT_CONNECTTIMEOUT(3)\fP set to 4 and \fICURLOPT_TIMEOUT(3)\fP set
-to 2, the operation can never last longer than 2 seconds. Including the
-connection phase.
-
-This option may cause libcurl to use the SIGALRM signal to timeout system
-calls on builds not using asynch DNS. In unix-like systems, this might cause
-signals to be used unless \fICURLOPT_NOSIGNAL(3)\fP is set.
-.SH DEFAULT
-300
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* complete connection within 10 seconds */
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK. Returns CURLE_BAD_FUNCTION_ARGUMENT if set to a negative
-value or a value that when converted to milliseconds is too large.
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECTTIMEOUT_MS (3),
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.md b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.md
new file mode 100644
index 000000000..07513fdee
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT.md
@@ -0,0 +1,89 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CONNECTTIMEOUT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT_MS (3)
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_CONNECTTIMEOUT - timeout for the connect phase
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT, long timeout);
+~~~
+
+# DESCRIPTION
+
+Pass a long. It should contain the maximum time in seconds that you allow the
+connection phase to the server to take. This timeout only limits the
+connection phase, it has no impact once it has connected. Set to zero to
+switch to the default built-in connection timeout - 300 seconds. See also the
+CURLOPT_TIMEOUT(3) option.
+
+CURLOPT_CONNECTTIMEOUT_MS(3) is the same function but set in milliseconds.
+
+If both CURLOPT_CONNECTTIMEOUT(3) and CURLOPT_CONNECTTIMEOUT_MS(3)
+are set, the value set last is used.
+
+The "connection phase" is considered complete when the requested TCP, TLS or
+QUIC handshakes are done.
+
+The connection timeout set with CURLOPT_CONNECTTIMEOUT(3) is included in
+the general all-covering CURLOPT_TIMEOUT(3).
+
+With CURLOPT_CONNECTTIMEOUT(3) set to 3 and CURLOPT_TIMEOUT(3) set
+to 5, the operation can never last longer than 5 seconds, and the connection
+phase cannot last longer than 3 seconds.
+
+With CURLOPT_CONNECTTIMEOUT(3) set to 4 and CURLOPT_TIMEOUT(3) set
+to 2, the operation can never last longer than 2 seconds. Including the
+connection phase.
+
+This option may cause libcurl to use the SIGALRM signal to timeout system
+calls on builds not using asynch DNS. In unix-like systems, this might cause
+signals to be used unless CURLOPT_NOSIGNAL(3) is set.
+
+# DEFAULT
+
+300
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* complete connection within 10 seconds */
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK. Returns CURLE_BAD_FUNCTION_ARGUMENT if set to a negative
+value or a value that when converted to milliseconds is too large.
diff --git a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3
deleted file mode 100644
index ec83ca35b..000000000
--- a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CONNECTTIMEOUT_MS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CONNECTTIMEOUT_MS \- timeout for the connect phase
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT_MS,
- long timeout);
-.fi
-.SH DESCRIPTION
-Pass a long. It should contain the maximum time in milliseconds that you allow
-the connection phase to the server to take.
-
-See \fICURLOPT_CONNECTTIMEOUT(3)\fP for details.
-.SH DEFAULT
-300000
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* complete connection within 10000 milliseconds */
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 10000L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECTTIMEOUT (3),
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.md b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.md
new file mode 100644
index 000000000..b8508e7de
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CONNECTTIMEOUT_MS.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CONNECTTIMEOUT_MS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT (3)
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_CONNECTTIMEOUT_MS - timeout for the connect phase
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECTTIMEOUT_MS,
+ long timeout);
+~~~
+
+# DESCRIPTION
+
+Pass a long. It should contain the maximum time in milliseconds that you allow
+the connection phase to the server to take.
+
+See CURLOPT_CONNECTTIMEOUT(3) for details.
+
+# DEFAULT
+
+300000
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* complete connection within 10000 milliseconds */
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 10000L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3 b/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3
deleted file mode 100644
index ca71a669a..000000000
--- a/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.3
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CONNECT_ONLY 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CONNECT_ONLY \- stop when connected to target server
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECT_ONLY, long only);
-.fi
-.SH DESCRIPTION
-Pass a long. If the parameter equals 1, it tells the library to perform all
-the required proxy authentication and connection setup, but no data transfer,
-and then return.
-
-The option can be used to simply test a connection to a server, but is more
-useful when used with the \fICURLINFO_ACTIVESOCKET(3)\fP option to
-\fIcurl_easy_getinfo(3)\fP as the library can set up the connection and then
-the application can obtain the most recently used socket for special data
-transfers.
-
-Since 7.86.0, this option can be set to '2' and if HTTP or WebSocket are used,
-libcurl performs the request and reads all response headers before handing
-over control to the application.
-
-Transfers marked connect only do not reuse any existing connections and
-connections marked connect only are not allowed to get reused.
-
-If the connect only transfer is done using the multi interface, the particular
-easy handle must remain added to the multi handle for as long as the
-application wants to use it. Once it has been removed with
-\fIcurl_multi_remove_handle(3)\fP, \fIcurl_easy_send(3)\fP and
-\fIcurl_easy_recv(3)\fP do not function.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP, SMTP, POP3 and IMAP. For WS and WSS starting in 7.86.0.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
- ret = curl_easy_perform(curl);
- if(ret == CURLE_OK) {
- /* only connected! */
- }
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_recv (3),
-.BR curl_easy_send (3),
-.BR CURLOPT_HTTPPROXYTUNNEL (3),
-.BR CURLOPT_VERBOSE (3)
diff --git a/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md b/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md
new file mode 100644
index 000000000..3312936af
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CONNECT_ONLY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPPROXYTUNNEL (3)
+ - CURLOPT_VERBOSE (3)
+ - curl_easy_recv (3)
+ - curl_easy_send (3)
+---
+
+# NAME
+
+CURLOPT_CONNECT_ONLY - stop when connected to target server
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECT_ONLY, long only);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If the parameter equals 1, it tells the library to perform all
+the required proxy authentication and connection setup, but no data transfer,
+and then return.
+
+The option can be used to simply test a connection to a server, but is more
+useful when used with the CURLINFO_ACTIVESOCKET(3) option to
+curl_easy_getinfo(3) as the library can set up the connection and then
+the application can obtain the most recently used socket for special data
+transfers.
+
+Since 7.86.0, this option can be set to '2' and if HTTP or WebSocket are used,
+libcurl performs the request and reads all response headers before handing
+over control to the application.
+
+Transfers marked connect only do not reuse any existing connections and
+connections marked connect only are not allowed to get reused.
+
+If the connect only transfer is done using the multi interface, the particular
+easy handle must remain added to the multi handle for as long as the
+application wants to use it. Once it has been removed with
+curl_multi_remove_handle(3), curl_easy_send(3) and
+curl_easy_recv(3) do not function.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP, SMTP, POP3 and IMAP. For WS and WSS starting in 7.86.0.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
+ ret = curl_easy_perform(curl);
+ if(ret == CURLE_OK) {
+ /* only connected! */
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CONNECT_TO.3 b/docs/libcurl/opts/CURLOPT_CONNECT_TO.3
deleted file mode 100644
index 1c4b80b64..000000000
--- a/docs/libcurl/opts/CURLOPT_CONNECT_TO.3
+++ /dev/null
@@ -1,116 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CONNECT_TO 3 "10 April 2016" libcurl libcurl
-.SH NAME
-CURLOPT_CONNECT_TO \- connect to a specific host and port instead of the URL's host and port
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECT_TO,
- struct curl_slist *connect_to);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a linked list of strings with "connect to" information to
-use for establishing network connections with this handle. The linked list
-should be a fully valid list of \fBstruct curl_slist\fP structs properly
-filled in. Use \fIcurl_slist_append(3)\fP to create the list and
-\fIcurl_slist_free_all(3)\fP to clean up an entire list.
-
-Each single string should be written using the format
-HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT where HOST is the host of the
-request, PORT is the port of the request, CONNECT-TO-HOST is the host name to
-connect to, and CONNECT-TO-PORT is the port to connect to.
-
-The first string that matches the request's host and port is used.
-
-Dotted numerical IP addresses are supported for HOST and CONNECT-TO-HOST.
-A numerical IPv6 address must be written within [brackets].
-
-Any of the four values may be empty. When the HOST or PORT is empty, the host
-or port always match (the request's host or port is ignored). When
-CONNECT-TO-HOST or CONNECT-TO-PORT is empty, the "connect to" feature is
-disabled for the host or port, and the request's host or port are used to
-establish the network connection.
-
-This option is suitable to direct the request at a specific server, e.g. at a
-specific cluster node in a cluster of servers.
-
-The "connect to" host and port are only used to establish the network
-connection. They do NOT affect the host and port that are used for TLS/SSL
-(e.g. SNI, certificate verification) or for the application protocols.
-
-In contrast to \fICURLOPT_RESOLVE(3)\fP, the option
-\fICURLOPT_CONNECT_TO(3)\fP does not pre-populate the DNS cache and therefore
-it does not affect future transfers of other easy handles that have been added
-to the same multi handle.
-
-The "connect to" host and port are ignored if they are equal to the host and
-the port in the request URL, because connecting to the host and the port in
-the request URL is the default behavior.
-
-If an HTTP proxy is used for a request having a special "connect to" host or
-port, and the "connect to" host or port differs from the request's host and
-port, the HTTP proxy is automatically switched to tunnel mode for this
-specific request. This is necessary because it is not possible to connect to a
-specific host or port in normal (non-tunnel) mode.
-
-When this option is passed to \fIcurl_easy_setopt(3)\fP, libcurl does not copy
-the list so you \fBmust\fP keep it around until you no longer use this
-\fIhandle\fP for a transfer before you call \fIcurl_slist_free_all(3)\fP on
-the list.
-
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl;
-struct curl_slist *connect_to = NULL;
-connect_to = curl_slist_append(NULL, "example.com::server1.example.com:");
-
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_perform(curl);
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-
-curl_slist_free_all(connect_to);
-.fi
-.SH AVAILABILITY
-Added in 7.49.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FOLLOWLOCATION (3),
-.BR CURLOPT_HTTPPROXYTUNNEL (3),
-.BR CURLOPT_RESOLVE (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_CONNECT_TO.md b/docs/libcurl/opts/CURLOPT_CONNECT_TO.md
new file mode 100644
index 000000000..8aea3ffa9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CONNECT_TO.md
@@ -0,0 +1,114 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CONNECT_TO
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FOLLOWLOCATION (3)
+ - CURLOPT_HTTPPROXYTUNNEL (3)
+ - CURLOPT_RESOLVE (3)
+ - CURLOPT_URL (3)
+---
+
+# NAME
+
+CURLOPT_CONNECT_TO - connect to another host and port instead
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONNECT_TO,
+ struct curl_slist *connect_to);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of strings with "connect to" information to
+use for establishing network connections with this handle. The linked list
+should be a fully valid list of **struct curl_slist** structs properly filled
+in. Use curl_slist_append(3) to create the list and curl_slist_free_all(3) to
+clean up an entire list.
+
+Each single string should be written using the format
+HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT where HOST is the host of the
+request, PORT is the port of the request, CONNECT-TO-HOST is the hostname to
+connect to, and CONNECT-TO-PORT is the port to connect to.
+
+The first string that matches the request's host and port is used.
+
+Dotted numerical IP addresses are supported for HOST and CONNECT-TO-HOST.
+A numerical IPv6 address must be written within [brackets].
+
+Any of the four values may be empty. When the HOST or PORT is empty, the host
+or port always match (the request's host or port is ignored). When
+CONNECT-TO-HOST or CONNECT-TO-PORT is empty, the "connect to" feature is
+disabled for the host or port, and the request's host or port are used to
+establish the network connection.
+
+This option is suitable to direct the request at a specific server, e.g. at a
+specific cluster node in a cluster of servers.
+
+The "connect to" host and port are only used to establish the network
+connection. They do NOT affect the host and port that are used for TLS/SSL
+(e.g. SNI, certificate verification) or for the application protocols.
+
+In contrast to CURLOPT_RESOLVE(3), the option CURLOPT_CONNECT_TO(3) does not
+pre-populate the DNS cache and therefore it does not affect future transfers
+of other easy handles that have been added to the same multi handle.
+
+The "connect to" host and port are ignored if they are equal to the host and
+the port in the request URL, because connecting to the host and the port in
+the request URL is the default behavior.
+
+If an HTTP proxy is used for a request having a special "connect to" host or
+port, and the "connect to" host or port differs from the request's host and
+port, the HTTP proxy is automatically switched to tunnel mode for this
+specific request. This is necessary because it is not possible to connect to a
+specific host or port in normal (non-tunnel) mode.
+
+When this option is passed to curl_easy_setopt(3), libcurl does not copy the
+list so you **must** keep it around until you no longer use this *handle* for
+a transfer before you call curl_slist_free_all(3) on the list.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl;
+ struct curl_slist *connect_to = NULL;
+ connect_to = curl_slist_append(NULL, "example.com::server1.example.com:");
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_CONNECT_TO, connect_to);
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+
+ curl_slist_free_all(connect_to);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.49.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3
deleted file mode 100644
index 9d14df7cd..000000000
--- a/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.3
+++ /dev/null
@@ -1,106 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CONV_FROM_NETWORK_FUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CONV_FROM_NETWORK_FUNCTION \- convert data from network to host encoding
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode conv_callback(char *ptr, size_t length);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONV_FROM_NETWORK_FUNCTION,
- conv_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-Applies to non-ASCII platforms. \fIcurl_version_info(3)\fP returns the
-\fBCURL_VERSION_CONV\fP feature bit set if this option is provided.
-
-The data to be converted is in a buffer pointed to by the \fIptr\fP parameter.
-The amount of data to convert is indicated by the \fIlength\fP parameter. The
-converted data overlays the input data in the buffer pointed to by the ptr
-parameter. \fICURLE_OK\fP must be returned upon successful conversion. A
-CURLcode return value defined by curl.h, such as \fICURLE_CONV_FAILED\fP,
-should be returned if an error was encountered.
-
-\fICURLOPT_CONV_FROM_NETWORK_FUNCTION(3)\fP converts to host encoding from the
-network encoding. It is used when commands or ASCII data are received over
-the network.
-
-If you set a callback pointer to NULL, or do not set it at all, the built-in
-libcurl iconv functions are used. If HAVE_ICONV was not defined when libcurl
-was built, and no callback has been established, the conversion returns the
-\fBCURLE_CONV_REQD\fP error code.
-
-If \fBHAVE_ICONV\fP is defined, \fBCURL_ICONV_CODESET_OF_HOST\fP must also be
-defined. For example:
-
- \&#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
-
-The iconv code in libcurl defaults the network and UTF8 codeset names as
-follows:
-
- \&#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
-
- \&#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
-
-You need to override these definitions if they are different on your system.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP, SMTP, IMAP, POP3
-.SH EXAMPLE
-.nf
-static CURLcode my_conv_from_ascii_to_ebcdic(char *buffer, size_t length)
-{
- char *tempptrin, *tempptrout;
- size_t bytes = length;
- int rc;
- tempptrin = tempptrout = buffer;
- rc = platform_a2e(&tempptrin, &bytes, &tempptrout, &bytes);
- if(rc == PLATFORM_CONV_OK) {
- return CURLE_OK;
- }
- else {
- return CURLE_CONV_FAILED;
- }
-}
-
-/* use platform-specific functions for codeset conversions */
-curl_easy_setopt(curl, CURLOPT_CONV_FROM_NETWORK_FUNCTION,
- my_conv_from_ascii_to_ebcdic);
-.fi
-.SH AVAILABILITY
-Not available and deprecated since 7.82.0.
-
-Available only if \fBCURL_DOES_CONVERSIONS\fP was defined when libcurl was
-built.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CONV_FROM_UTF8_FUNCTION (3),
-.BR CURLOPT_CONV_TO_NETWORK_FUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.md b/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.md
new file mode 100644
index 000000000..7460a1e90
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CONV_FROM_NETWORK_FUNCTION.md
@@ -0,0 +1,114 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CONV_FROM_NETWORK_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONV_FROM_UTF8_FUNCTION (3)
+ - CURLOPT_CONV_TO_NETWORK_FUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_CONV_FROM_NETWORK_FUNCTION - convert data from network to host encoding
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode conv_callback(char *ptr, size_t length);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ conv_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+Applies to non-ASCII platforms. curl_version_info(3) returns the
+**CURL_VERSION_CONV** feature bit set if this option is provided.
+
+The data to be converted is in a buffer pointed to by the *ptr* parameter.
+The amount of data to convert is indicated by the *length* parameter. The
+converted data overlays the input data in the buffer pointed to by the ptr
+parameter. *CURLE_OK* must be returned upon successful conversion. A
+CURLcode return value defined by curl.h, such as *CURLE_CONV_FAILED*,
+should be returned if an error was encountered.
+
+CURLOPT_CONV_FROM_NETWORK_FUNCTION(3) converts to host encoding from the
+network encoding. It is used when commands or ASCII data are received over the
+network.
+
+If you set a callback pointer to NULL, or do not set it at all, the built-in
+libcurl iconv functions are used. If HAVE_ICONV was not defined when libcurl
+was built, and no callback has been established, the conversion returns the
+**CURLE_CONV_REQD** error code.
+
+If **HAVE_ICONV** is defined, **CURL_ICONV_CODESET_OF_HOST** must also be
+defined. For example:
+
+~~~c
+#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
+~~~
+
+The iconv code in libcurl defaults the network and UTF8 codeset names as
+follows:
+
+~~~
+#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
+
+#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
+~~~
+
+You need to override these definitions if they are different on your system.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP, SMTP, IMAP, POP3
+
+# EXAMPLE
+
+~~~c
+static CURLcode my_conv_from_ascii_to_ebcdic(char *buffer, size_t length)
+{
+ int rc = 0;
+
+ /* in-place convert 'buffer' from ASCII to EBCDIC */
+
+ if(rc == 0) {
+ /* success */
+ return CURLE_OK;
+ }
+ else {
+ return CURLE_CONV_FAILED;
+ }
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+
+ /* use platform-specific functions for codeset conversions */
+ curl_easy_setopt(curl, CURLOPT_CONV_FROM_NETWORK_FUNCTION,
+ my_conv_from_ascii_to_ebcdic);
+}
+~~~
+
+# AVAILABILITY
+
+Not available and deprecated since 7.82.0.
+
+Available only if **CURL_DOES_CONVERSIONS** was defined when libcurl was
+built.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3
deleted file mode 100644
index d4ae0c54d..000000000
--- a/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.3
+++ /dev/null
@@ -1,104 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CONV_FROM_UTF8_FUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CONV_FROM_UTF8_FUNCTION \- convert data from UTF8 to host encoding
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode conv_callback(char *ptr, size_t length);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONV_FROM_UTF8_FUNCTION,
- conv_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-Applies to non-ASCII platforms. \fIcurl_version_info(3)\fP returns the
-CURL_VERSION_CONV feature bit set if this option is provided.
-
-The data to be converted is in a buffer pointed to by the \fIptr\fP parameter.
-The amount of data to convert is indicated by the \fIlength\fP parameter. The
-converted data overlays the input data in the buffer pointed to by the ptr
-parameter. \fICURLE_OK\fP must be returned upon successful conversion. A
-CURLcode return value defined by curl.h, such as \fICURLE_CONV_FAILED\fP,
-should be returned if an error was encountered.
-
-\fICURLOPT_CONV_FROM_UTF8_FUNCTION(3)\fP converts to host encoding from UTF8
-encoding. It is required only for SSL processing.
-
-If you set a callback pointer to NULL, or do not set it at all, the built-in
-libcurl iconv functions are used. If HAVE_ICONV was not defined when libcurl
-was built, and no callback has been established, the conversion returns the
-CURLE_CONV_REQD error code.
-
-If HAVE_ICONV is defined, CURL_ICONV_CODESET_OF_HOST must also be defined.
-For example:
-
- \&#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
-
-The iconv code in libcurl defaults the network and UTF8 codeset names as
-follows:
-
- \&#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
-
- \&#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
-
-You need to override these definitions if they are different on your system.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-TLS-based protocols.
-.SH EXAMPLE
-.nf
-static CURLcode my_conv_from_utf8_to_ebcdic(char *buffer, size_t length)
-{
- char *tempptrin, *tempptrout;
- size_t bytes = length;
- int rc;
- tempptrin = tempptrout = buffer;
- rc = platform_u2e(&tempptrin, &bytes, &tempptrout, &bytes);
- if(rc == PLATFORM_CONV_OK) {
- return CURLE_OK;
- }
- else {
- return CURLE_CONV_FAILED;
- }
-}
-
-curl_easy_setopt(curl, CURLOPT_CONV_FROM_UTF8_FUNCTION,
- my_conv_from_utf8_to_ebcdic);
-.fi
-.SH AVAILABILITY
-Not available and deprecated since 7.82.0.
-
-Available only if \fBCURL_DOES_CONVERSIONS\fP was defined when libcurl was
-built.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CONV_FROM_NETWORK_FUNCTION (3),
-.BR CURLOPT_CONV_TO_NETWORK_FUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.md b/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.md
new file mode 100644
index 000000000..1f7d704e9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CONV_FROM_UTF8_FUNCTION.md
@@ -0,0 +1,107 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CONV_FROM_UTF8_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONV_FROM_NETWORK_FUNCTION (3)
+ - CURLOPT_CONV_TO_NETWORK_FUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_CONV_FROM_UTF8_FUNCTION - convert data from UTF8 to host encoding
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode conv_callback(char *ptr, size_t length);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONV_FROM_UTF8_FUNCTION,
+ conv_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+Applies to non-ASCII platforms. curl_version_info(3) returns the
+CURL_VERSION_CONV feature bit set if this option is provided.
+
+The data to be converted is in a buffer pointed to by the *ptr* parameter.
+The amount of data to convert is indicated by the *length* parameter. The
+converted data overlays the input data in the buffer pointed to by the ptr
+parameter. *CURLE_OK* must be returned upon successful conversion. A
+CURLcode return value defined by curl.h, such as *CURLE_CONV_FAILED*,
+should be returned if an error was encountered.
+
+CURLOPT_CONV_FROM_UTF8_FUNCTION(3) converts to host encoding from UTF8
+encoding. It is required only for SSL processing.
+
+If you set a callback pointer to NULL, or do not set it at all, the built-in
+libcurl iconv functions are used. If HAVE_ICONV was not defined when libcurl
+was built, and no callback has been established, the conversion returns the
+CURLE_CONV_REQD error code.
+
+If HAVE_ICONV is defined, CURL_ICONV_CODESET_OF_HOST must also be defined.
+For example:
+~~~c
+ #define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
+~~~
+
+The iconv code in libcurl defaults the network and UTF8 codeset names as
+follows:
+~~~c
+#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
+
+#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
+~~~
+
+You need to override these definitions if they are different on your system.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+TLS-based protocols.
+
+# EXAMPLE
+
+~~~c
+static CURLcode my_conv_from_utf8_to_ebcdic(char *buffer, size_t length)
+{
+ int rc = 0;
+ /* in-place convert 'buffer' from UTF-8 to EBCDIC */
+ if(rc == 0) {
+ /* success */
+ return CURLE_OK;
+ }
+ else {
+ return CURLE_CONV_FAILED;
+ }
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ curl_easy_setopt(curl, CURLOPT_CONV_FROM_UTF8_FUNCTION,
+ my_conv_from_utf8_to_ebcdic);
+}
+~~~
+
+# AVAILABILITY
+
+Not available and deprecated since 7.82.0.
+
+Available only if **CURL_DOES_CONVERSIONS** was defined when libcurl was
+built.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3
deleted file mode 100644
index a334078a4..000000000
--- a/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.3
+++ /dev/null
@@ -1,105 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CONV_TO_NETWORK_FUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CONV_TO_NETWORK_FUNCTION \- convert data to network from host encoding
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode conv_callback(char *ptr, size_t length);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONV_TO_NETWORK_FUNCTION,
- conv_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-Applies to non-ASCII platforms. \fIcurl_version_info(3)\fP returns the
-CURL_VERSION_CONV feature bit set if this option is provided.
-
-The data to be converted is in a buffer pointed to by the \fIptr\fP parameter.
-The amount of data to convert is indicated by the \fIlength\fP parameter. The
-converted data overlays the input data in the buffer pointed to by the ptr
-parameter. \fICURLE_OK\fP must be returned upon successful conversion. A
-CURLcode return value defined by curl.h, such as \fICURLE_CONV_FAILED\fP,
-should be returned if an error was encountered.
-
-\fICURLOPT_CONV_TO_NETWORK_FUNCTION(3)\fP converts from host encoding to the
-network encoding. It is used when commands or ASCII data are sent over the
-network.
-
-If you set a callback pointer to NULL, or do not set it at all, the built-in
-libcurl iconv functions are used. If HAVE_ICONV was not defined when libcurl
-was built, and no callback has been established, the conversion returns the
-CURLE_CONV_REQD error code.
-
-If HAVE_ICONV is defined, CURL_ICONV_CODESET_OF_HOST must also be defined.
-For example:
-
- \&#define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
-
-The iconv code in libcurl defaults the network and UTF8 codeset names as
-follows:
-
- \&#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
-
- \&#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
-
-You need to override these definitions if they are different on your system.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP, SMTP, IMAP, POP3
-.SH EXAMPLE
-.nf
-static CURLcode my_conv_from_ebcdic_to_ascii(char *buffer, size_t length)
-{
- char *tempptrin, *tempptrout;
- size_t bytes = length;
- int rc;
- tempptrin = tempptrout = buffer;
- rc = platform_e2a(&tempptrin, &bytes, &tempptrout, &bytes);
- if(rc == PLATFORM_CONV_OK) {
- return CURLE_OK;
- }
- else {
- return CURLE_CONV_FAILED;
- }
-}
-
-curl_easy_setopt(curl, CURLOPT_CONV_TO_NETWORK_FUNCTION,
- my_conv_from_ebcdic_to_ascii);
-.fi
-.SH AVAILABILITY
-Not available and deprecated since 7.82.0.
-
-Available only if \fBCURL_DOES_CONVERSIONS\fP was defined when libcurl was
-built.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CONV_FROM_NETWORK_FUNCTION (3),
-.BR CURLOPT_CONV_FROM_UTF8_FUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.md b/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.md
new file mode 100644
index 000000000..13d9da867
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CONV_TO_NETWORK_FUNCTION.md
@@ -0,0 +1,110 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CONV_TO_NETWORK_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONV_FROM_NETWORK_FUNCTION (3)
+ - CURLOPT_CONV_FROM_UTF8_FUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_CONV_TO_NETWORK_FUNCTION - convert data to network from host encoding
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode conv_callback(char *ptr, size_t length);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CONV_TO_NETWORK_FUNCTION,
+ conv_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+Applies to non-ASCII platforms. curl_version_info(3) returns the
+CURL_VERSION_CONV feature bit set if this option is provided.
+
+The data to be converted is in a buffer pointed to by the *ptr* parameter.
+The amount of data to convert is indicated by the *length* parameter. The
+converted data overlays the input data in the buffer pointed to by the ptr
+parameter. *CURLE_OK* must be returned upon successful conversion. A CURLcode
+return value defined by curl.h, such as *CURLE_CONV_FAILED*, should be
+returned if an error was encountered.
+
+CURLOPT_CONV_TO_NETWORK_FUNCTION(3) converts from host encoding to the
+network encoding. It is used when commands or ASCII data are sent over the
+network.
+
+If you set a callback pointer to NULL, or do not set it at all, the built-in
+libcurl iconv functions are used. If HAVE_ICONV was not defined when libcurl
+was built, and no callback has been established, the conversion returns the
+CURLE_CONV_REQD error code.
+
+If HAVE_ICONV is defined, CURL_ICONV_CODESET_OF_HOST must also be defined.
+For example:
+~~~c
+define CURL_ICONV_CODESET_OF_HOST "IBM-1047"
+~~~
+
+The iconv code in libcurl defaults the network and UTF8 codeset names as
+follows:
+
+~~~c
+#define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
+
+#define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
+~~~
+
+You need to override these definitions if they are different on your system.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP, SMTP, IMAP, POP3
+
+# EXAMPLE
+
+~~~c
+static CURLcode my_conv_from_ebcdic_to_ascii(char *buffer, size_t length)
+{
+ int rc = 0;
+ /* in-place convert 'buffer' from EBCDIC to ASCII */
+ if(rc == 0) {
+ /* success */
+ return CURLE_OK;
+ }
+ else {
+ return CURLE_CONV_FAILED;
+ }
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+
+ curl_easy_setopt(curl, CURLOPT_CONV_TO_NETWORK_FUNCTION,
+ my_conv_from_ebcdic_to_ascii);
+}
+~~~
+
+# AVAILABILITY
+
+Not available and deprecated since 7.82.0.
+
+Available only if **CURL_DOES_CONVERSIONS** was defined when libcurl was
+built.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_COOKIE.3 b/docs/libcurl/opts/CURLOPT_COOKIE.3
deleted file mode 100644
index b7de3ebe2..000000000
--- a/docs/libcurl/opts/CURLOPT_COOKIE.3
+++ /dev/null
@@ -1,90 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_COOKIE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_COOKIE \- HTTP Cookie header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIE, char *cookie);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter. It is used to set one
-or more cookies 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.
-
-To set multiple cookies, set them all using a single option concatenated like
-this: "name1=content1; name2=content2;" etc.
-
-This option sets the cookie header explicitly in the outgoing request(s). If
-multiple requests are done due to authentication, followed redirections or
-similar, they all get this cookie passed on.
-
-The cookies set by this option are separate from the internal cookie storage
-held by the cookie engine and they are not be modified by it. If you enable
-the cookie engine and either you have imported a cookie of the same name
-(e.g. 'foo') or the server has set one, it has no effect on the cookies you
-set here. A request to the server sends both the 'foo' held by the cookie
-engine and the 'foo' held by this option. To set a cookie that is instead held
-by the cookie engine and can be modified by the server use
-\fICURLOPT_COOKIELIST(3)\fP.
-
-Using this option multiple times makes the last set string override the
-previous ones.
-
-This option does not enable the cookie engine. Use \fICURLOPT_COOKIEFILE(3)\fP
-or \fICURLOPT_COOKIEJAR(3)\fP to enable parsing and sending cookies
-automatically.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL, no cookies
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_COOKIE, "tool=curl; fun=yes;");
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-If HTTP is enabled
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is enabled, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLINFO_COOKIELIST (3),
-.BR CURLOPT_COOKIEFILE (3),
-.BR CURLOPT_COOKIEJAR (3),
-.BR CURLOPT_COOKIELIST (3),
-.BR CURLOPT_HTTPHEADER (3)
diff --git a/docs/libcurl/opts/CURLOPT_COOKIE.md b/docs/libcurl/opts/CURLOPT_COOKIE.md
new file mode 100644
index 000000000..4e2955d8a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_COOKIE.md
@@ -0,0 +1,97 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_COOKIE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_COOKIELIST (3)
+ - CURLOPT_COOKIEFILE (3)
+ - CURLOPT_COOKIEJAR (3)
+ - CURLOPT_COOKIELIST (3)
+ - CURLOPT_HTTPHEADER (3)
+---
+
+# NAME
+
+CURLOPT_COOKIE - HTTP Cookie header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIE, char *cookie);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. It is used to set one
+or more cookies 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.
+
+To set multiple cookies, set them all using a single option concatenated like
+this: "name1=content1; name2=content2;" etc.
+
+This option sets the cookie header explicitly in the outgoing request(s). If
+multiple requests are done due to authentication, followed redirections or
+similar, they all get this cookie passed on.
+
+The cookies set by this option are separate from the internal cookie storage
+held by the cookie engine and they are not be modified by it. If you enable
+the cookie engine and either you have imported a cookie of the same name
+(e.g. 'foo') or the server has set one, it has no effect on the cookies you
+set here. A request to the server sends both the 'foo' held by the cookie
+engine and the 'foo' held by this option. To set a cookie that is instead held
+by the cookie engine and can be modified by the server use
+CURLOPT_COOKIELIST(3).
+
+Using this option multiple times makes the last set string override the
+previous ones.
+
+This option does not enable the cookie engine. Use CURLOPT_COOKIEFILE(3)
+or CURLOPT_COOKIEJAR(3) to enable parsing and sending cookies
+automatically.
+
+The application does not have to keep the string around after setting this
+option.
+
+If libcurl is built with PSL (*Public Suffix List*) support, it detects and
+discards cookies that are specified for such suffix domains that should not be
+allowed to have cookies. If libcurl is *not* built with PSL support, it has no
+ability to stop super cookies. PSL support is identified by the
+**CURL_VERSION_PSL** feature bit returned by curl_version_info(3).
+
+# DEFAULT
+
+NULL, no cookies
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_COOKIE, "tool=curl; fun=yes;");
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If HTTP is enabled
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_COOKIEFILE.3 b/docs/libcurl/opts/CURLOPT_COOKIEFILE.3
deleted file mode 100644
index 08e9582fc..000000000
--- a/docs/libcurl/opts/CURLOPT_COOKIEFILE.3
+++ /dev/null
@@ -1,97 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_COOKIEFILE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_COOKIEFILE \- file name to read cookies from
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEFILE, char *filename);
-.fi
-.SH DESCRIPTION
-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.
-
-It also enables the cookie engine, making libcurl parse and send cookies on
-subsequent requests with this handle.
-
-By passing the empty string ("") to this option, you enable the cookie engine
-without reading any initial cookies. If you tell libcurl the file name is "-"
-(just a single minus sign), libcurl instead reads from stdin.
-
-This option only \fBreads\fP cookies. To make libcurl write cookies to file,
-see \fICURLOPT_COOKIEJAR(3)\fP.
-
-If you read cookies from a plain HTTP headers file and it does not specify a
-domain in the Set-Cookie line, then the cookie is not sent since the cookie
-domain cannot match the target URL's. To address this, set a domain in
-Set-Cookie line (doing that includes subdomains) or preferably: use the
-Netscape format.
-
-If you use this option multiple times, you add more files to read cookies
-from.
-
-The application does not have to keep the string around after setting this
-option.
-
-Setting this option to NULL (since 7.77.0) explicitly disables the cookie
-engine and clears the list of files to read cookies from.
-.SH SECURITY
-This document previously mentioned how specifying a non-existing file can also
-enable the cookie engine. While true, we strongly advise against using that
-method as it is too hard to be sure that files that stay that way in the long
-run.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* get cookies from an existing file */
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH "Cookie file format"
-The cookie file format and general cookie concepts in curl are described
-online here: https://curl.se/docs/http-cookies.html
-.SH AVAILABILITY
-As long as HTTP is supported
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_COOKIE (3),
-.BR CURLOPT_COOKIEJAR (3),
-.BR CURLOPT_COOKIESESSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_COOKIEFILE.md b/docs/libcurl/opts/CURLOPT_COOKIEFILE.md
new file mode 100644
index 000000000..87dce1b1a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_COOKIEFILE.md
@@ -0,0 +1,103 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_COOKIEFILE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_COOKIE (3)
+ - CURLOPT_COOKIEJAR (3)
+ - CURLOPT_COOKIESESSION (3)
+---
+
+# NAME
+
+CURLOPT_COOKIEFILE - filename to read cookies from
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEFILE, char *filename);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. It should point to
+the filename 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.
+
+It also enables the cookie engine, making libcurl parse and send cookies on
+subsequent requests with this handle.
+
+By passing the empty string ("") to this option, you enable the cookie engine
+without reading any initial cookies. If you tell libcurl the filename is "-"
+(just a single minus sign), libcurl instead reads from stdin.
+
+This option only **reads** cookies. To make libcurl write cookies to file,
+see CURLOPT_COOKIEJAR(3).
+
+If you read cookies from a plain HTTP headers file and it does not specify a
+domain in the Set-Cookie line, then the cookie is not sent since the cookie
+domain cannot match the target URL's. To address this, set a domain in
+Set-Cookie line (doing that includes subdomains) or preferably: use the
+Netscape format.
+
+If you use this option multiple times, you add more files to read cookies
+from.
+
+The application does not have to keep the string around after setting this
+option.
+
+Setting this option to NULL (since 7.77.0) explicitly disables the cookie
+engine and clears the list of files to read cookies from.
+
+# SECURITY
+
+This document previously mentioned how specifying a non-existing file can also
+enable the cookie engine. While true, we strongly advise against using that
+method as it is too hard to be sure that files that stay that way in the long
+run.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* get cookies from an existing file */
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# Cookie file format
+
+The cookie file format and general cookie concepts in curl are described
+online here: https://curl.se/docs/http-cookies.html
+
+# AVAILABILITY
+
+As long as HTTP is supported
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_COOKIEJAR.3 b/docs/libcurl/opts/CURLOPT_COOKIEJAR.3
deleted file mode 100644
index f84d99a16..000000000
--- a/docs/libcurl/opts/CURLOPT_COOKIEJAR.3
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_COOKIEJAR 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_COOKIEJAR \- file name to store cookies to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEJAR, char *filename);
-.fi
-.SH DESCRIPTION
-Pass a \fIfilename\fP as a char *, null-terminated. This makes libcurl write
-all internally known cookies to the specified file when
-\fIcurl_easy_cleanup(3)\fP is called. If no cookies are kept in memory at that
-time, no file is created. Specify "-" as filename to instead have the cookies
-written to stdout. Using this option also enables cookies for this session, so
-if you for example follow a redirect it makes matching cookies get sent
-accordingly.
-
-Note that libcurl does not read any cookies from the cookie jar specified with
-this option. To read cookies from a file, use \fICURLOPT_COOKIEFILE(3)\fP.
-
-If the cookie jar file cannot be created or written to (when the
-\fIcurl_easy_cleanup(3)\fP is called), libcurl does not and cannot report an
-error for this. Using \fICURLOPT_VERBOSE(3)\fP or
-\fICURLOPT_DEBUGFUNCTION(3)\fP displays a warning, but that is the only
-visible feedback you get about this possibly lethal situation.
-
-Cookies are imported in the Set-Cookie format without a domain name are not
-exported by this option.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* export cookies to this file when closing the handle */
- curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "/tmp/cookies.txt");
-
- ret = curl_easy_perform(curl);
-
- /* close the handle, write the cookies! */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_COOKIE (3),
-.BR CURLOPT_COOKIEFILE (3),
-.BR CURLOPT_COOKIELIST (3)
diff --git a/docs/libcurl/opts/CURLOPT_COOKIEJAR.md b/docs/libcurl/opts/CURLOPT_COOKIEJAR.md
new file mode 100644
index 000000000..ec0d273eb
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_COOKIEJAR.md
@@ -0,0 +1,86 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_COOKIEJAR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_COOKIE (3)
+ - CURLOPT_COOKIEFILE (3)
+ - CURLOPT_COOKIELIST (3)
+---
+
+# NAME
+
+CURLOPT_COOKIEJAR - filename to store cookies to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEJAR, char *filename);
+~~~
+
+# DESCRIPTION
+
+Pass a *filename* as a char *, null-terminated. This makes libcurl write
+all internally known cookies to the specified file when
+curl_easy_cleanup(3) is called. If no cookies are kept in memory at that
+time, no file is created. Specify "-" as filename to instead have the cookies
+written to stdout. Using this option also enables cookies for this session, so
+if you for example follow a redirect it makes matching cookies get sent
+accordingly.
+
+Note that libcurl does not read any cookies from the cookie jar specified with
+this option. To read cookies from a file, use CURLOPT_COOKIEFILE(3).
+
+If the cookie jar file cannot be created or written to (when the
+curl_easy_cleanup(3) is called), libcurl does not and cannot report an
+error for this. Using CURLOPT_VERBOSE(3) or
+CURLOPT_DEBUGFUNCTION(3) displays a warning, but that is the only
+visible feedback you get about this possibly lethal situation.
+
+Cookies are imported in the Set-Cookie format without a domain name are not
+exported by this option.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* export cookies to this file when closing the handle */
+ curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "/tmp/cookies.txt");
+
+ res = curl_easy_perform(curl);
+
+ /* close the handle, write the cookies! */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_COOKIELIST.3 b/docs/libcurl/opts/CURLOPT_COOKIELIST.3
deleted file mode 100644
index da9ca290a..000000000
--- a/docs/libcurl/opts/CURLOPT_COOKIELIST.3
+++ /dev/null
@@ -1,125 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_COOKIELIST 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_COOKIELIST \- add to or manipulate cookies held in memory
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIELIST,
- char *cookie);
-.SH DESCRIPTION
-Pass a char * to a \fIcookie\fP string.
-
-Such a cookie can be either a single line in Netscape / Mozilla format or just
-regular HTTP-style header (Set-Cookie: ...) format. This option also enables
-the cookie engine. This adds that single cookie to the internal cookie store.
-
-We strongly advice against loading cookies from a HTTP header file, as that is
-an inferior data exchange format.
-
-Exercise caution if you are using this option and multiple transfers may
-occur. If you use the Set-Cookie format and the string does not specify a
-domain, then the cookie is sent for any domain (even after redirects are
-followed) and cannot be modified by a server-set cookie. If a server sets a
-cookie of the same name (or maybe you have imported one) then both are sent on
-future transfers to that server, likely not what you intended. To address
-these issues set a domain in Set-Cookie (doing that includes subdomains) or
-much better: use the Netscape file format.
-
-Additionally, there are commands available that perform actions if you pass in
-these exact strings:
-.IP ALL
-erases all cookies held in memory
-
-.IP SESS
-erases all session cookies held in memory
-
-.IP FLUSH
-writes all known cookies to the file specified by \fICURLOPT_COOKIEJAR(3)\fP
-
-.IP RELOAD
-loads all cookies from the files specified by \fICURLOPT_COOKIEFILE(3)\fP
-
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-/* an inline import of a cookie in Netscape format. */
-
-#define SEP "\\t" /* Tab separates the fields */
-
-char *my_cookie =
- "example.com" /* Hostname */
- SEP "FALSE" /* Include subdomains */
- SEP "/" /* Path */
- SEP "FALSE" /* Secure */
- SEP "0" /* Expiry in epoch time format. 0 == Session */
- SEP "foo" /* Name */
- SEP "bar"; /* Value */
-
-/* my_cookie is imported immediately via CURLOPT_COOKIELIST. */
-curl_easy_setopt(curl, CURLOPT_COOKIELIST, my_cookie);
-
-/* The list of cookies in cookies.txt are not be imported until right
- before a transfer is performed. Cookies in the list that have the same
- hostname, path and name as in my_cookie are skipped. That is because
- libcurl has already imported my_cookie and it's considered a "live"
- cookie. A live cookie is not replaced by one read from a file.
-*/
-curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt"); /* import */
-
-/* Cookies are exported after curl_easy_cleanup is called. The server
- may have added, deleted or modified cookies by then. The cookies that
- were skipped on import are not exported.
-*/
-curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt"); /* export */
-
-curl_easy_perform(curl); /* cookies imported from cookies.txt */
-
-curl_easy_cleanup(curl); /* cookies exported to cookies.txt */
-.fi
-.SH "Cookie file format"
-The cookie file format and general cookie concepts in curl are described
-online here: https://curl.se/docs/http-cookies.html
-.SH AVAILABILITY
-\fBALL\fP was added in 7.14.1
-
-\fBSESS\fP was added in 7.15.4
-
-\fBFLUSH\fP was added in 7.17.1
-
-\fBRELOAD\fP was added in 7.39.0
-.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 CURLINFO_COOKIELIST (3),
-.BR CURLOPT_COOKIE (3),
-.BR CURLOPT_COOKIEFILE (3),
-.BR CURLOPT_COOKIEJAR (3)
diff --git a/docs/libcurl/opts/CURLOPT_COOKIELIST.md b/docs/libcurl/opts/CURLOPT_COOKIELIST.md
new file mode 100644
index 000000000..4c17bd4bc
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_COOKIELIST.md
@@ -0,0 +1,136 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_COOKIELIST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_COOKIELIST (3)
+ - CURLOPT_COOKIE (3)
+ - CURLOPT_COOKIEFILE (3)
+ - CURLOPT_COOKIEJAR (3)
+---
+
+# NAME
+
+CURLOPT_COOKIELIST - add to or manipulate cookies held in memory
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIELIST,
+ char *cookie);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to a *cookie* string.
+
+Such a cookie can be either a single line in Netscape / Mozilla format or just
+regular HTTP-style header (Set-Cookie: ...) format. This option also enables
+the cookie engine. This adds that single cookie to the internal cookie store.
+
+We strongly advice against loading cookies from an HTTP header file, as that
+is an inferior data exchange format.
+
+Exercise caution if you are using this option and multiple transfers may
+occur. If you use the Set-Cookie format and the string does not specify a
+domain, then the cookie is sent for any domain (even after redirects are
+followed) and cannot be modified by a server-set cookie. If a server sets a
+cookie of the same name (or maybe you have imported one) then both are sent on
+future transfers to that server, likely not what you intended. To address
+these issues set a domain in Set-Cookie (doing that includes subdomains) or
+much better: use the Netscape file format.
+
+Additionally, there are commands available that perform actions if you pass in
+these exact strings:
+
+## ALL
+
+erases all cookies held in memory
+
+## SESS
+
+erases all session cookies held in memory
+
+## FLUSH
+
+writes all known cookies to the file specified by CURLOPT_COOKIEJAR(3)
+
+## RELOAD
+
+loads all cookies from the files specified by CURLOPT_COOKIEFILE(3)
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+/* an inline import of a cookie in Netscape format. */
+
+#define SEP "\t" /* Tab separates the fields */
+
+int main(void)
+{
+ char *my_cookie =
+ "example.com" /* Hostname */
+ SEP "FALSE" /* Include subdomains */
+ SEP "/" /* Path */
+ SEP "FALSE" /* Secure */
+ SEP "0" /* Expiry in epoch time format. 0 == Session */
+ SEP "foo" /* Name */
+ SEP "bar"; /* Value */
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* my_cookie is imported immediately via CURLOPT_COOKIELIST. */
+ curl_easy_setopt(curl, CURLOPT_COOKIELIST, my_cookie);
+
+ /* The list of cookies in cookies.txt are not be imported until right
+ before a transfer is performed. Cookies in the list that have the same
+ hostname, path and name as in my_cookie are skipped. That is because
+ libcurl has already imported my_cookie and it's considered a "live"
+ cookie. A live cookie is not replaced by one read from a file.
+ */
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "cookies.txt"); /* import */
+
+ /* Cookies are exported after curl_easy_cleanup is called. The server
+ may have added, deleted or modified cookies by then. The cookies that
+ were skipped on import are not exported.
+ */
+ curl_easy_setopt(curl, CURLOPT_COOKIEJAR, "cookies.txt"); /* export */
+
+ curl_easy_perform(curl); /* cookies imported from cookies.txt */
+
+ curl_easy_cleanup(curl); /* cookies exported to cookies.txt */
+ }
+}
+~~~
+
+# Cookie file format
+
+The cookie file format and general cookie concepts in curl are described
+online here: https://curl.se/docs/http-cookies.html
+
+# AVAILABILITY
+
+**ALL** was added in 7.14.1
+
+**SESS** was added in 7.15.4
+
+**FLUSH** was added in 7.17.1
+
+**RELOAD** was added in 7.39.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_COOKIESESSION.3 b/docs/libcurl/opts/CURLOPT_COOKIESESSION.3
deleted file mode 100644
index 3578b8287..000000000
--- a/docs/libcurl/opts/CURLOPT_COOKIESESSION.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_COOKIESESSION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_COOKIESESSION \- start a new cookie session
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIESESSION, long init);
-.fi
-.SH DESCRIPTION
-Pass a long set to 1 to mark this as a new cookie "session". It forces libcurl
-to ignore all cookies it is about to load that are "session cookies" from the
-previous session. By default, libcurl always loads all cookies, independent if
-they are session cookies or not. Session cookies are cookies without expiry
-date and they are meant to be alive and existing for this "session" only.
-
-A "session" is usually defined in browser land for as long as you have your
-browser up, more or less. libcurl needs the application to use this option to
-tell it when a new session starts, otherwise it assumes everything is still in
-the same session.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* new "session", do not load session cookies */
- curl_easy_setopt(curl, CURLOPT_COOKIESESSION, 1L);
-
- /* get the (non session) cookies from this file */
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_COOKIE (3),
-.BR CURLOPT_COOKIEFILE (3),
-.BR CURLOPT_COOKIEJAR (3)
diff --git a/docs/libcurl/opts/CURLOPT_COOKIESESSION.md b/docs/libcurl/opts/CURLOPT_COOKIESESSION.md
new file mode 100644
index 000000000..6f49f025c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_COOKIESESSION.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_COOKIESESSION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_COOKIE (3)
+ - CURLOPT_COOKIEFILE (3)
+ - CURLOPT_COOKIEJAR (3)
+---
+
+# NAME
+
+CURLOPT_COOKIESESSION - start a new cookie session
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIESESSION, long init);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 1 to mark this as a new cookie "session". It forces libcurl
+to ignore all cookies it is about to load that are "session cookies" from the
+previous session. By default, libcurl always loads all cookies, independent if
+they are session cookies or not. Session cookies are cookies without expiry
+date and they are meant to be alive and existing for this "session" only.
+
+A "session" is usually defined in browser land for as long as you have your
+browser up, more or less. libcurl needs the application to use this option to
+tell it when a new session starts, otherwise it assumes everything is still in
+the same session.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* new "session", do not load session cookies */
+ curl_easy_setopt(curl, CURLOPT_COOKIESESSION, 1L);
+
+ /* get the (non session) cookies from this file */
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3 b/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3
deleted file mode 100644
index 870bb670b..000000000
--- a/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_COPYPOSTFIELDS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_COPYPOSTFIELDS \- have libcurl copy data to POST
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COPYPOSTFIELDS, char *data);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter, which should be the full \fIdata\fP to post in a
-HTTP POST operation. It behaves as the \fICURLOPT_POSTFIELDS(3)\fP option, but
-the original data is instead copied by the library, allowing the application
-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 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
-\fICURLOPT_COPYPOSTFIELDS(3)\fP option is issued.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- char local_buffer[1024]="data to send";
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* size of the data to copy from the buffer and send in the request */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 12L);
-
- /* send data from the local stack */
- curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, local_buffer);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.17.1
-.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_MIMEPOST (3),
-.BR CURLOPT_POSTFIELDS (3),
-.BR CURLOPT_POSTFIELDSIZE (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md b/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md
new file mode 100644
index 000000000..911e08181
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_COPYPOSTFIELDS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MIMEPOST (3)
+ - CURLOPT_POSTFIELDS (3)
+ - CURLOPT_POSTFIELDSIZE (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_COPYPOSTFIELDS - have libcurl copy data to POST
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COPYPOSTFIELDS, char *data);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be the full *data* to post in a
+HTTP POST operation. It behaves as the CURLOPT_POSTFIELDS(3) option, but the
+original data is instead copied by the library, allowing the application to
+overwrite the original data after setting this option.
+
+Because data are copied, care must be taken when using this option in
+conjunction with CURLOPT_POSTFIELDSIZE(3) or
+CURLOPT_POSTFIELDSIZE_LARGE(3): If the size has not been set prior to
+CURLOPT_COPYPOSTFIELDS(3), 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
+CURLOPT_COPYPOSTFIELDS(3), unless another CURLOPT_POSTFIELDS(3) or
+CURLOPT_COPYPOSTFIELDS(3) option is issued.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ char local_buffer[1024]="data to send";
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* size of the data to copy from the buffer and send in the request */
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 12L);
+
+ /* send data from the local stack */
+ curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, local_buffer);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.17.1
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_CRLF.3 b/docs/libcurl/opts/CURLOPT_CRLF.3
deleted file mode 100644
index abcdcefa4..000000000
--- a/docs/libcurl/opts/CURLOPT_CRLF.3
+++ /dev/null
@@ -1,61 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CRLF 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CRLF \- CRLF conversion
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLF, long conv);
-.fi
-.SH DESCRIPTION
-Pass a long. If the value is set to 1 (one), libcurl converts Unix newlines to
-CRLF newlines on transfers. Disable this option again by setting the value to
-0 (zero).
-
-This is a legacy option of questionable use.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/");
- curl_easy_setopt(curl, CURLOPT_CRLF, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-SMTP since 7.40.0, other protocols since they were introduced
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_CONV_FROM_NETWORK_FUNCTION (3),
-.BR CURLOPT_CONV_TO_NETWORK_FUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_CRLF.md b/docs/libcurl/opts/CURLOPT_CRLF.md
new file mode 100644
index 000000000..1766c3312
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CRLF.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CRLF
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONV_FROM_NETWORK_FUNCTION (3)
+ - CURLOPT_CONV_TO_NETWORK_FUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_CRLF - CRLF conversion
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLF, long conv);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If the value is set to 1 (one), libcurl converts Unix newlines to
+CRLF newlines on transfers. Disable this option again by setting the value to
+0 (zero).
+
+This is a legacy option of questionable use.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_CRLF, 1L);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+SMTP since 7.40.0, other protocols since they were introduced
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_CRLFILE.3 b/docs/libcurl/opts/CURLOPT_CRLFILE.3
deleted file mode 100644
index da6d639ea..000000000
--- a/docs/libcurl/opts/CURLOPT_CRLFILE.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CRLFILE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CRLFILE \- Certificate Revocation List file
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLFILE, char *file);
-.fi
-.SH DESCRIPTION
-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 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. Also note that
-\fICURLOPT_CRLFILE(3)\fP implies \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.
-
-A specific error code (\fICURLE_SSL_CRL_BADFILE\fP) is defined with the
-option. It is returned when the SSL exchange fails because the CRL file cannot
-be loaded. A failure in certificate verification due to a revocation
-information found in the CRL does not trigger this specific error.
-
-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/");
- curl_easy_setopt(curl, CURLOPT_CRLFILE, "/etc/certs/crl.pem");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.0
-.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_CRLFILE (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_CRLFILE.md b/docs/libcurl/opts/CURLOPT_CRLFILE.md
new file mode 100644
index 000000000..b800f8ce3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CRLFILE.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CRLFILE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_CRLFILE (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_CRLFILE - Certificate Revocation List file
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLFILE, char *file);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to a null-terminated string naming a *file* 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 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. Also note that
+CURLOPT_CRLFILE(3) implies **CURLSSLOPT_NO_PARTIALCHAIN** (see
+CURLOPT_SSL_OPTIONS(3)) since curl 7.71.0 due to an OpenSSL bug.
+
+This option makes sense only when used in combination with the
+CURLOPT_SSL_VERIFYPEER(3) option.
+
+A specific error code (*CURLE_SSL_CRL_BADFILE*) is defined with the option. It
+is returned when the SSL exchange fails because the CRL file cannot be
+loaded. A failure in certificate verification due to a revocation information
+found in the CRL does not trigger this specific error.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_CRLFILE, "/etc/certs/crl.pem");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_CURLU.3 b/docs/libcurl/opts/CURLOPT_CURLU.3
deleted file mode 100644
index 5b16f2115..000000000
--- a/docs/libcurl/opts/CURLOPT_CURLU.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CURLU 3 "28 Oct 2018" libcurl libcurl
-.SH NAME
-CURLOPT_CURLU \- URL in URL handle format
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CURLU, CURLU *pointer);
-.fi
-.SH DESCRIPTION
-Pass in a pointer to the \fIURL\fP handle to work with. The parameter should
-be a \fICURLU *\fP. Setting \fICURLOPT_CURLU(3)\fP explicitly overrides
-\fICURLOPT_URL(3)\fP.
-
-\fICURLOPT_URL(3)\fP or \fICURLOPT_CURLU(3)\fP \fBmust\fP be set before a
-transfer is started.
-
-libcurl uses this handle and its contents read-only and does not change its
-contents. An application can update the contents of the URL handle after a
-transfer is done and if the same handle is used in a subsequent request the
-updated contents is used.
-.SH DEFAULT
-The default value of this parameter is NULL.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *handle = curl_easy_init();
-CURLU *urlp = curl_url();
-int res = 0;
-if(curl) {
-
- res = curl_url_set(urlp, CURLUPART_URL, "https://example.com", 0);
-
- curl_easy_setopt(handle, CURLOPT_CURLU, urlp);
-
- ret = curl_easy_perform(handle);
-
- curl_url_cleanup(urlp);
- curl_easy_cleanup(handle);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.63.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_url (3),
-.BR curl_url_cleanup (3),
-.BR curl_url_dup (3),
-.BR curl_url_get (3),
-.BR curl_url_set (3),
-.BR curl_url_strerror (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_CURLU.md b/docs/libcurl/opts/CURLOPT_CURLU.md
new file mode 100644
index 000000000..a3eeb5c9b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CURLU.md
@@ -0,0 +1,79 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CURLU
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_URL (3)
+ - curl_url (3)
+ - curl_url_cleanup (3)
+ - curl_url_dup (3)
+ - curl_url_get (3)
+ - curl_url_set (3)
+ - curl_url_strerror (3)
+---
+
+# NAME
+
+CURLOPT_CURLU - URL in URL handle format
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CURLU, CURLU *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass in a pointer to the *URL* handle to work with. The parameter should be a
+*CURLU pointer*. Setting CURLOPT_CURLU(3) explicitly overrides
+CURLOPT_URL(3).
+
+CURLOPT_URL(3) or CURLOPT_CURLU(3) **must** be set before a
+transfer is started.
+
+libcurl uses this handle and its contents read-only and does not change its
+contents. An application can update the contents of the URL handle after a
+transfer is done and if the same handle is used in a subsequent request the
+updated contents is used.
+
+# DEFAULT
+
+The default value of this parameter is NULL.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ CURLU *urlp = curl_url();
+ if(curl) {
+ CURLcode res;
+ CURLUcode ret;
+ ret = curl_url_set(urlp, CURLUPART_URL, "https://example.com", 0);
+
+ curl_easy_setopt(curl, CURLOPT_CURLU, urlp);
+
+ res = curl_easy_perform(curl);
+
+ curl_url_cleanup(urlp);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.63.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3 b/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3
deleted file mode 100644
index 00132854e..000000000
--- a/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.3
+++ /dev/null
@@ -1,117 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_CUSTOMREQUEST 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_CUSTOMREQUEST \- custom request method
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CUSTOMREQUEST, char *method);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter.
-
-When you change the request \fImethod\fP by setting
-\fICURLOPT_CUSTOMREQUEST(3)\fP to something, you do not actually change how
-libcurl behaves or acts in regards to the particular request method, it only
-changes the actual string sent in the request.
-
-Restore to the internal default by setting this to NULL.
-
-This option can be used to specify the request:
-.IP HTTP
-Instead of GET or HEAD when performing HTTP based requests. This is
-particularly useful, for example, for performing an HTTP DELETE request.
-
-For example:
-
-When you tell libcurl to do a HEAD request, but then specify a GET though a
-custom request libcurl still acts as if it sent a HEAD. To switch to a proper
-HEAD use \fICURLOPT_NOBODY(3)\fP, to switch to a proper POST use
-\fICURLOPT_POST(3)\fP or \fICURLOPT_POSTFIELDS(3)\fP and to switch to a proper
-GET use \fICURLOPT_HTTPGET(3)\fP.
-
-Many people have wrongly used this option to replace the entire request with
-their own, including multiple headers and POST contents. While that might work
-in many cases, it might cause libcurl to send invalid requests and it could
-possibly confuse the remote server badly. Use \fICURLOPT_POST(3)\fP and
-\fICURLOPT_POSTFIELDS(3)\fP to set POST data. Use \fICURLOPT_HTTPHEADER(3)\fP
-to replace or extend the set of headers sent by libcurl. Use
-\fICURLOPT_HTTP_VERSION(3)\fP to change HTTP version.
-
-.IP FTP
-Instead of LIST and NLST when performing FTP directory listings.
-.IP IMAP
-Instead of LIST when issuing IMAP based requests.
-.IP POP3
-Instead of LIST and RETR when issuing POP3 based requests.
-
-For example:
-
-When you tell libcurl to use a custom request it behaves like a LIST or RETR
-command was sent where it expects data to be returned by the server. As such
-\fICURLOPT_NOBODY(3)\fP should be used when specifying commands such as
-\fBDELE\fP and \fBNOOP\fP for example.
-.IP SMTP
-Instead of a \fBHELP\fP or \fBVRFY\fP when issuing SMTP based requests.
-
-For example:
-
-Normally a multi line response is returned which can be used, in conjunction
-with \fICURLOPT_MAIL_RCPT(3)\fP, to specify an EXPN request. If the
-\fICURLOPT_NOBODY(3)\fP option is specified then the request can be used to
-issue \fBNOOP\fP and \fBRSET\fP commands.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP, FTP, IMAP, POP3 and SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* DELETE the given path */
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-IMAP is supported since 7.30.0, POP3 since 7.26.0 and SMTP since 7.34.0.
-.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 CURLINFO_EFFECTIVE_METHOD (3),
-.BR CURLOPT_HTTPHEADER (3),
-.BR CURLOPT_NOBODY (3),
-.BR CURLOPT_REQUEST_TARGET (3)
diff --git a/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md b/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md
new file mode 100644
index 000000000..c4d4ec210
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md
@@ -0,0 +1,130 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_CUSTOMREQUEST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_EFFECTIVE_METHOD (3)
+ - CURLOPT_HTTPHEADER (3)
+ - CURLOPT_NOBODY (3)
+ - CURLOPT_REQUEST_TARGET (3)
+---
+
+# NAME
+
+CURLOPT_CUSTOMREQUEST - custom request method
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CUSTOMREQUEST, char *method);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter.
+
+When changing the request *method* by setting CURLOPT_CUSTOMREQUEST(3), you
+do not actually change how libcurl behaves or acts: you only change the actual
+string sent in the request.
+
+libcurl passes on the verbatim string in its request without any filter or
+other safe guards. That includes white space and control characters.
+
+Restore to the internal default by setting this to NULL.
+
+This option can be used to specify the request:
+
+## HTTP
+
+Instead of GET or HEAD when performing HTTP based requests. This is
+particularly useful, for example, for performing an HTTP DELETE request.
+
+For example:
+
+When you tell libcurl to do a HEAD request, but then specify a GET though a
+custom request libcurl still acts as if it sent a HEAD. To switch to a proper
+HEAD use CURLOPT_NOBODY(3), to switch to a proper POST use
+CURLOPT_POST(3) or CURLOPT_POSTFIELDS(3) and to switch to a proper
+GET use CURLOPT_HTTPGET(3).
+
+Many people have wrongly used this option to replace the entire request with
+their own, including multiple headers and POST contents. While that might work
+in many cases, it might cause libcurl to send invalid requests and it could
+possibly confuse the remote server badly. Use CURLOPT_POST(3) and
+CURLOPT_POSTFIELDS(3) to set POST data. Use CURLOPT_HTTPHEADER(3)
+to replace or extend the set of headers sent by libcurl. Use
+CURLOPT_HTTP_VERSION(3) to change HTTP version.
+
+## FTP
+
+Instead of LIST and NLST when performing FTP directory listings.
+
+## IMAP
+
+Instead of LIST when issuing IMAP based requests.
+
+## POP3
+
+Instead of LIST and RETR when issuing POP3 based requests.
+
+For example:
+
+When you tell libcurl to use a custom request it behaves like a LIST or RETR
+command was sent where it expects data to be returned by the server. As such
+CURLOPT_NOBODY(3) should be used when specifying commands such as
+**DELE** and **NOOP** for example.
+
+## SMTP
+
+Instead of a **HELP** or **VRFY** when issuing SMTP based requests.
+
+For example:
+
+Normally a multi line response is returned which can be used, in conjunction
+with CURLOPT_MAIL_RCPT(3), to specify an EXPN request. If the
+CURLOPT_NOBODY(3) option is specified then the request can be used to
+issue **NOOP** and **RSET** commands.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP, FTP, IMAP, POP3 and SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* DELETE the given path */
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+IMAP is supported since 7.30.0, POP3 since 7.26.0 and SMTP since 7.34.0.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_DEBUGDATA.3 b/docs/libcurl/opts/CURLOPT_DEBUGDATA.3
deleted file mode 100644
index b7db29309..000000000
--- a/docs/libcurl/opts/CURLOPT_DEBUGDATA.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DEBUGDATA 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DEBUGDATA \- pointer passed to the debug callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP to whatever you want passed in to your
-\fICURLOPT_DEBUGFUNCTION(3)\fP in the last void * argument. This pointer is
-not used by libcurl, it is only passed to the callback.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-int main(void)
-{
- CURL *curl;
- CURLcode res;
- struct data my_tracedata;
-
- curl = curl_easy_init();
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
-
- curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &my_tracedata);
-
- /* the DEBUGFUNCTION has no effect until we enable VERBOSE */
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- res = curl_easy_perform(curl);
-
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
- return 0;
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_DEBUGDATA.md b/docs/libcurl/opts/CURLOPT_DEBUGDATA.md
new file mode 100644
index 000000000..cac58d99d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DEBUGDATA.md
@@ -0,0 +1,86 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DEBUGDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_DEBUGDATA - pointer passed to the debug callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* to whatever you want passed in to your
+CURLOPT_DEBUGFUNCTION(3) in the last void * argument. This pointer is
+not used by libcurl, it is only passed to the callback.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct data {
+ void *custom;
+};
+
+static int my_trace(CURL *handle, curl_infotype type,
+ char *data, size_t size,
+ void *clientp)
+{
+ struct data *mine = clientp;
+ printf("our ptr: %p\n", mine->custom);
+
+ /* output debug info */
+}
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+ struct data my_tracedata;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
+
+ curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &my_tracedata);
+
+ /* the DEBUGFUNCTION has no effect until we enable VERBOSE */
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3 b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
deleted file mode 100644
index c3a08f14f..000000000
--- a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.3
+++ /dev/null
@@ -1,205 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DEBUGFUNCTION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DEBUGFUNCTION \- debug callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef enum {
- CURLINFO_TEXT = 0,
- CURLINFO_HEADER_IN, /* 1 */
- CURLINFO_HEADER_OUT, /* 2 */
- CURLINFO_DATA_IN, /* 3 */
- CURLINFO_DATA_OUT, /* 4 */
- CURLINFO_SSL_DATA_IN, /* 5 */
- CURLINFO_SSL_DATA_OUT, /* 6 */
- CURLINFO_END
-} curl_infotype;
-
-int debug_callback(CURL *handle,
- curl_infotype type,
- char *data,
- size_t size,
- void *clientp);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGFUNCTION,
- debug_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-\fICURLOPT_DEBUGFUNCTION(3)\fP replaces the standard debug function used when
-\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 is
-not null-terminated, but is exactly of the \fIsize\fP as told by the
-\fIsize\fP argument.
-
-The \fIclientp\fP argument is the pointer set with \fICURLOPT_DEBUGDATA(3)\fP.
-
-Available \fBcurl_infotype\fP values:
-.RS
-.IP CURLINFO_TEXT
-The data is informational text.
-.IP CURLINFO_HEADER_IN
-The data is header (or header-like) data received from the peer.
-.IP CURLINFO_HEADER_OUT
-The data is header (or header-like) data sent to the peer.
-.IP CURLINFO_DATA_IN
-The data is the unprocessed protocol data received from the peer. Even if the
-data is encoded or compressed, it is not not provided decoded nor decompressed
-to this callback. If you need the data in decoded and decompressed form, use
-\fICURLOPT_WRITEFUNCTION(3)\fP.
-.IP CURLINFO_DATA_OUT
-The data is protocol data sent to the peer.
-.IP CURLINFO_SSL_DATA_OUT
-The data is SSL/TLS (binary) data sent to the peer.
-.IP CURLINFO_SSL_DATA_IN
-The data is SSL/TLS (binary) data received from the peer.
-.RE
-
-WARNING: This callback may be called with the curl \fIhandle\fP set to an
-internal handle. (Added in 8.4.0)
-
-If you need to distinguish your curl \fIhandle\fP from internal handles then
-set \fICURLOPT_PRIVATE(3)\fP on your handle.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static
-void dump(const char *text,
- FILE *stream, unsigned char *ptr, size_t size)
-{
- size_t i;
- size_t c;
- unsigned int width=0x10;
-
- fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\\n",
- text, (long)size, (long)size);
-
- for(i=0; i<size; i+= width) {
- fprintf(stream, "%4.4lx: ", (long)i);
-
- /* show hex to the left */
- for(c = 0; c < width; c++) {
- if(i+c < size)
- fprintf(stream, "%02x ", ptr[i+c]);
- else
- fputs(" ", stream);
- }
-
- /* show data on the right */
- for(c = 0; (c < width) && (i+c < size); c++) {
- char x = (ptr[i+c] >= 0x20 && ptr[i+c] < 0x80) ? ptr[i+c] : '.';
- fputc(x, stream);
- }
-
- fputc('\\n', stream); /* newline */
- }
-}
-
-static
-int my_trace(CURL *handle, curl_infotype type,
- char *data, size_t size,
- void *clientp)
-{
- const char *text;
- (void)handle; /* prevent compiler warning */
- (void)clientp;
-
- switch (type) {
- case CURLINFO_TEXT:
- fputs("== Info: ", stderr);
- fwrite(data, size, 1, stderr);
- default: /* in case a new one is introduced to shock us */
- return 0;
-
- case CURLINFO_HEADER_OUT:
- text = "=> Send header";
- break;
- case CURLINFO_DATA_OUT:
- text = "=> Send data";
- break;
- case CURLINFO_SSL_DATA_OUT:
- text = "=> Send SSL data";
- break;
- case CURLINFO_HEADER_IN:
- text = "<= Recv header";
- break;
- case CURLINFO_DATA_IN:
- text = "<= Recv data";
- break;
- case CURLINFO_SSL_DATA_IN:
- text = "<= Recv SSL data";
- break;
- }
-
- dump(text, stderr, (unsigned char *)data, size);
- return 0;
-}
-
-int main(void)
-{
- CURL *curl;
- CURLcode res;
-
- curl = curl_easy_init();
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
-
- /* the DEBUGFUNCTION has no effect until we enable VERBOSE */
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-
- /* example.com is redirected, so we tell libcurl to follow redirection */
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- res = curl_easy_perform(curl);
- /* Check for errors */
- if(res != CURLE_OK)
- fprintf(stderr, "curl_easy_perform() failed: %s\\n",
- curl_easy_strerror(res));
-
- /* always cleanup */
- curl_easy_cleanup(curl);
- }
- return 0;
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR curl_global_trace (3),
-.BR CURLINFO_CONN_ID (3),
-.BR CURLINFO_XFER_ID (3),
-.BR CURLOPT_DEBUGDATA (3),
-.BR CURLOPT_VERBOSE (3)
diff --git a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md
new file mode 100644
index 000000000..1acf963ca
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md
@@ -0,0 +1,216 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DEBUGFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONN_ID (3)
+ - CURLINFO_XFER_ID (3)
+ - CURLOPT_DEBUGDATA (3)
+ - CURLOPT_VERBOSE (3)
+ - curl_global_trace (3)
+---
+
+# NAME
+
+CURLOPT_DEBUGFUNCTION - debug callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+typedef enum {
+ CURLINFO_TEXT = 0,
+ CURLINFO_HEADER_IN, /* 1 */
+ CURLINFO_HEADER_OUT, /* 2 */
+ CURLINFO_DATA_IN, /* 3 */
+ CURLINFO_DATA_OUT, /* 4 */
+ CURLINFO_SSL_DATA_IN, /* 5 */
+ CURLINFO_SSL_DATA_OUT, /* 6 */
+ CURLINFO_END
+} curl_infotype;
+
+int debug_callback(CURL *handle,
+ curl_infotype type,
+ char *data,
+ size_t size,
+ void *clientp);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEBUGFUNCTION,
+ debug_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+CURLOPT_DEBUGFUNCTION(3) replaces the standard debug function used when
+CURLOPT_VERBOSE(3) is in effect. This callback receives debug
+information, as specified in the *type* argument. This function must
+return 0. The *data* pointed to by the char * passed to this function is
+not null-terminated, but is exactly of the *size* as told by the
+*size* argument.
+
+The *clientp* argument is the pointer set with CURLOPT_DEBUGDATA(3).
+
+Available **curl_infotype** values:
+
+## CURLINFO_TEXT
+
+The data is informational text.
+
+## CURLINFO_HEADER_IN
+
+The data is header (or header-like) data received from the peer.
+
+## CURLINFO_HEADER_OUT
+
+The data is header (or header-like) data sent to the peer.
+
+## CURLINFO_DATA_IN
+
+The data is the unprocessed protocol data received from the peer. Even if the
+data is encoded or compressed, it is not not provided decoded nor decompressed
+to this callback. If you need the data in decoded and decompressed form, use
+CURLOPT_WRITEFUNCTION(3).
+
+## CURLINFO_DATA_OUT
+
+The data is protocol data sent to the peer.
+
+## CURLINFO_SSL_DATA_OUT
+
+The data is SSL/TLS (binary) data sent to the peer.
+
+## CURLINFO_SSL_DATA_IN
+
+The data is SSL/TLS (binary) data received from the peer.
+
+WARNING: This callback may be called with the curl *handle* set to an
+internal handle. (Added in 8.4.0)
+
+If you need to distinguish your curl *handle* from internal handles then
+set CURLOPT_PRIVATE(3) on your handle.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+static
+void dump(const char *text,
+ FILE *stream, unsigned char *ptr, size_t size)
+{
+ size_t i;
+ size_t c;
+ unsigned int width = 0x10;
+
+ fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
+ text, (long)size, (long)size);
+
+ for(i = 0; i < size; i += width) {
+ fprintf(stream, "%4.4lx: ", (long)i);
+
+ /* show hex to the left */
+ for(c = 0; c < width; c++) {
+ if(i + c < size)
+ fprintf(stream, "%02x ", ptr[i + c]);
+ else
+ fputs(" ", stream);
+ }
+
+ /* show data on the right */
+ for(c = 0; (c < width) && (i + c < size); c++) {
+ char x = (ptr[i + c] >= 0x20 && ptr[i + c] < 0x80) ? ptr[i + c] : '.';
+ fputc(x, stream);
+ }
+
+ fputc('\n', stream); /* newline */
+ }
+}
+
+static
+int my_trace(CURL *handle, curl_infotype type,
+ char *data, size_t size,
+ void *clientp)
+{
+ const char *text;
+ (void)handle; /* prevent compiler warning */
+ (void)clientp;
+
+ switch(type) {
+ case CURLINFO_TEXT:
+ fputs("== Info: ", stderr);
+ fwrite(data, size, 1, stderr);
+ default: /* in case a new one is introduced to shock us */
+ return 0;
+
+ case CURLINFO_HEADER_OUT:
+ text = "=> Send header";
+ break;
+ case CURLINFO_DATA_OUT:
+ text = "=> Send data";
+ break;
+ case CURLINFO_SSL_DATA_OUT:
+ text = "=> Send SSL data";
+ break;
+ case CURLINFO_HEADER_IN:
+ text = "<= Recv header";
+ break;
+ case CURLINFO_DATA_IN:
+ text = "<= Recv data";
+ break;
+ case CURLINFO_SSL_DATA_IN:
+ text = "<= Recv SSL data";
+ break;
+ }
+
+ dump(text, stderr, (unsigned char *)data, size);
+ return 0;
+}
+
+int main(void)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
+
+ /* the DEBUGFUNCTION has no effect until we enable VERBOSE */
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* example.com is redirected, so we tell libcurl to follow redirection */
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n",
+ curl_easy_strerror(res));
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+ return 0;
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3 b/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3
deleted file mode 100644
index 60d79d1f0..000000000
--- a/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DEFAULT_PROTOCOL 3 "18 Aug 2015" libcurl libcurl
-.SH NAME
-CURLOPT_DEFAULT_PROTOCOL \- default protocol to use if the URL is missing a
-scheme name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEFAULT_PROTOCOL,
- char *protocol);
-.fi
-.SH DESCRIPTION
-This option tells libcurl to use \fIprotocol\fP if the URL is missing a scheme
-name.
-
-Use one of these protocol (scheme) names:
-
-dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3,
-pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
-
-An unknown or unsupported protocol causes error
-\fICURLE_UNSUPPORTED_PROTOCOL\fP when libcurl parses a URL without a
-scheme. Parsing happens when \fIcurl_easy_perform(3)\fP or
-\fIcurl_multi_perform(3)\fP is called. The protocol set supported by libcurl
-vary depending on how it was built. Use \fIcurl_version_info(3)\fP if you need
-a list of protocol names supported by the build of libcurl that you are using.
-
-This option does not change the default proxy protocol (http).
-
-Without this option libcurl would make a guess based on the host, see
-\fICURLOPT_URL(3)\fP for details.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL (make a guess based on the host)
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- /* set a URL without a scheme */
- curl_easy_setopt(curl, CURLOPT_URL, "example.com");
-
- /* set the default protocol (scheme) for schemeless URLs */
- curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.45.0
-.SH RETURN VALUE
-CURLE_OK if the option is supported.
-
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-
-CURLE_UNKNOWN_OPTION if the option is not supported.
-.SH "SEE ALSO"
-.BR CURLINFO_PROTOCOL (3),
-.BR CURLINFO_SCHEME (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.md b/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.md
new file mode 100644
index 000000000..88468f718
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DEFAULT_PROTOCOL.md
@@ -0,0 +1,89 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DEFAULT_PROTOCOL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PROTOCOL (3)
+ - CURLINFO_SCHEME (3)
+ - CURLOPT_URL (3)
+---
+
+# NAME
+
+CURLOPT_DEFAULT_PROTOCOL - default protocol to use if the URL is missing a
+scheme name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DEFAULT_PROTOCOL,
+ char *protocol);
+~~~
+
+# DESCRIPTION
+
+This option tells libcurl to use *protocol* if the URL is missing a scheme
+name.
+
+Use one of these protocol (scheme) names:
+
+dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3,
+pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
+
+An unknown or unsupported protocol causes error
+*CURLE_UNSUPPORTED_PROTOCOL* when libcurl parses a URL without a
+scheme. Parsing happens when curl_easy_perform(3) or
+curl_multi_perform(3) is called. The protocol set supported by libcurl
+vary depending on how it was built. Use curl_version_info(3) if you need
+a list of protocol names supported by the build of libcurl that you are using.
+
+This option does not change the default proxy protocol (http).
+
+Without this option libcurl would make a guess based on the host, see
+CURLOPT_URL(3) for details.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL (make a guess based on the host)
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* set a URL without a scheme */
+ curl_easy_setopt(curl, CURLOPT_URL, "example.com");
+
+ /* set the default protocol (scheme) for schemeless URLs */
+ curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.45.0
+
+# RETURN VALUE
+
+CURLE_OK if the option is supported.
+
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+
+CURLE_UNKNOWN_OPTION if the option is not supported.
diff --git a/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3 b/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3
deleted file mode 100644
index a301cf9a5..000000000
--- a/docs/libcurl/opts/CURLOPT_DIRLISTONLY.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DIRLISTONLY 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DIRLISTONLY \- ask for names only in a directory listing
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DIRLISTONLY, long listonly);
-.fi
-.SH DESCRIPTION
-For FTP and SFTP based URLs a parameter set to 1 tells the library to list the
-names of files in a directory, rather than performing a full directory listing
-that would normally include file sizes, dates etc.
-
-For POP3 a parameter of 1 tells the library to list the email message or
-messages on the POP3 server. This can be used to change the default behavior
-of libcurl, when combined with a URL that contains a message ID, to perform a
-"scan listing" which can then be used to determine the size of an email.
-
-Note: For FTP this causes a NLST command to be sent to the FTP server. Beware
-that some FTP servers list only files in their response to NLST; they might not
-include subdirectories and symbolic links.
-
-Setting this option to 1 also implies a directory listing even if the URL
-does not end with a slash, which otherwise is necessary.
-
-Do not use this option if you also use \fICURLOPT_WILDCARDMATCH(3)\fP as it
-effectively breaks that feature.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-FTP, SFTP and POP3
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/");
-
- /* list only */
- curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was known as CURLOPT_FTPLISTONLY up to 7.16.4. POP3 is supported
-since 7.21.5.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CUSTOMREQUEST (3),
-.BR CURLOPT_WILDCARDMATCH (3)
diff --git a/docs/libcurl/opts/CURLOPT_DIRLISTONLY.md b/docs/libcurl/opts/CURLOPT_DIRLISTONLY.md
new file mode 100644
index 000000000..29635622c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DIRLISTONLY.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DIRLISTONLY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CUSTOMREQUEST (3)
+ - CURLOPT_WILDCARDMATCH (3)
+---
+
+# NAME
+
+CURLOPT_DIRLISTONLY - ask for names only in a directory listing
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DIRLISTONLY, long listonly);
+~~~
+
+# DESCRIPTION
+
+For FTP and SFTP based URLs a parameter set to 1 tells the library to list the
+names of files in a directory, rather than performing a full directory listing
+that would normally include file sizes, dates etc.
+
+For POP3 a parameter of 1 tells the library to list the email message or
+messages on the POP3 server. This can be used to change the default behavior
+of libcurl, when combined with a URL that contains a message ID, to perform a
+"scan listing" which can then be used to determine the size of an email.
+
+Note: For FTP this causes a NLST command to be sent to the FTP server. Beware
+that some FTP servers list only files in their response to NLST; they might
+not include subdirectories and symbolic links.
+
+Setting this option to 1 also implies a directory listing even if the URL
+does not end with a slash, which otherwise is necessary.
+
+Do not use this option if you also use CURLOPT_WILDCARDMATCH(3) as it
+effectively breaks that feature.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+FTP, SFTP and POP3
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/");
+
+ /* list only */
+ curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was known as CURLOPT_FTPLISTONLY up to 7.16.4. POP3 is supported
+since 7.21.5.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3 b/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3
deleted file mode 100644
index e21cbe6b1..000000000
--- a/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DISALLOW_USERNAME_IN_URL 3 "30 May 2018" libcurl libcurl
-.SH NAME
-CURLOPT_DISALLOW_USERNAME_IN_URL \- disallow specifying username in the URL
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DISALLOW_USERNAME_IN_URL,
- long disallow);
-.fi
-.SH DESCRIPTION
-A long parameter set to 1 tells the library to not allow URLs that include a
-username.
-
-This is the equivalent to the \fICURLU_DISALLOW_USER\fP flag for the
-\fIcurl_url_set(3)\fP function.
-.SH DEFAULT
-0 (disabled) - user names are allowed by default.
-.SH PROTOCOLS
-Several
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-
-\fIcurl_easy_perform(3)\fP returns CURLE_LOGIN_DENIED if this option is
-enabled and a URL containing a username is specified.
-.SH "SEE ALSO"
-.BR curl_url_set (3),
-.BR CURLOPT_PROTOCOLS (3),
-.BR CURLOPT_URL (3),
-.BR libcurl-security (3)
diff --git a/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.md b/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.md
new file mode 100644
index 000000000..ddaaace89
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DISALLOW_USERNAME_IN_URL.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DISALLOW_USERNAME_IN_URL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROTOCOLS (3)
+ - CURLOPT_URL (3)
+ - curl_url_set (3)
+ - libcurl-security (3)
+---
+
+# NAME
+
+CURLOPT_DISALLOW_USERNAME_IN_URL - disallow specifying username in the URL
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DISALLOW_USERNAME_IN_URL,
+ long disallow);
+~~~
+
+# DESCRIPTION
+
+A long parameter set to 1 tells the library to not allow URLs that include a
+username.
+
+This is the equivalent to the *CURLU_DISALLOW_USER* flag for the
+curl_url_set(3) function.
+
+# DEFAULT
+
+0 (disabled) - user names are allowed by default.
+
+# PROTOCOLS
+
+Several
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+
+curl_easy_perform(3) returns CURLE_LOGIN_DENIED if this option is
+enabled and a URL containing a username is specified.
diff --git a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3
deleted file mode 100644
index e14eb7407..000000000
--- a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DNS_CACHE_TIMEOUT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DNS_CACHE_TIMEOUT \- life-time for DNS cache entries
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_CACHE_TIMEOUT, long age);
-.fi
-.SH DESCRIPTION
-Pass a long, this sets the timeout in seconds. Name resolve results are kept
-in memory and used for this number of seconds. Set to zero to completely
-disable caching, or set to -1 to make the cached entries remain forever. By
-default, libcurl caches this info for 60 seconds.
-
-We recommend users not to tamper with this option unless strictly necessary.
-If you do, be careful of using large values that can make the cache size grow
-significantly if many different host names are used within that timeout
-period.
-
-The name resolve functions of various libc implementations do not re-read name
-server information unless explicitly told so (for example, by calling
-\fIres_init(3)\fP). This may cause libcurl to keep using the older server even
-if DHCP has updated the server info, and this may look like a DNS cache issue
-to the casual libcurl-app user.
-
-DNS entries have a "TTL" property but libcurl does not use that. This DNS
-cache timeout is entirely speculative that a name resolves to the same address
-for a small amount of time into the future.
-
-Since version 8.1.0, libcurl prunes entries from the DNS cache if it exceeds
-30,000 entries no matter which timeout value is used.
-.SH DEFAULT
-60
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* only reuse addresses for a short time */
- curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 2L);
-
- ret = curl_easy_perform(curl);
-
- /* in this second request, the cache is not be used if more than
- two seconds have passed since the previous name resolve */
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECTTIMEOUT_MS (3),
-.BR CURLOPT_DNS_SERVERS (3),
-.BR CURLOPT_DNS_USE_GLOBAL_CACHE (3),
-.BR CURLOPT_MAXAGE_CONN (3),
-.BR CURLOPT_RESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md
new file mode 100644
index 000000000..0199f525a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md
@@ -0,0 +1,90 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DNS_CACHE_TIMEOUT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT_MS (3)
+ - CURLOPT_DNS_SERVERS (3)
+ - CURLOPT_DNS_USE_GLOBAL_CACHE (3)
+ - CURLOPT_MAXAGE_CONN (3)
+ - CURLOPT_RESOLVE (3)
+---
+
+# NAME
+
+CURLOPT_DNS_CACHE_TIMEOUT - life-time for DNS cache entries
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_CACHE_TIMEOUT, long age);
+~~~
+
+# DESCRIPTION
+
+Pass a long, this sets the timeout in seconds. Name resolve results are kept
+in memory and used for this number of seconds. Set to zero to completely
+disable caching, or set to -1 to make the cached entries remain forever. By
+default, libcurl caches this info for 60 seconds.
+
+We recommend users not to tamper with this option unless strictly necessary.
+If you do, be careful of using large values that can make the cache size grow
+significantly if many different host names are used within that timeout
+period.
+
+The name resolve functions of various libc implementations do not re-read name
+server information unless explicitly told so (for example, by calling
+*res_init(3)*). This may cause libcurl to keep using the older server even
+if DHCP has updated the server info, and this may look like a DNS cache issue
+to the casual libcurl-app user.
+
+DNS entries have a "TTL" property but libcurl does not use that. This DNS
+cache timeout is entirely speculative that a name resolves to the same address
+for a small amount of time into the future.
+
+Since version 8.1.0, libcurl prunes entries from the DNS cache if it exceeds
+30,000 entries no matter which timeout value is used.
+
+# DEFAULT
+
+60
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* only reuse addresses for a short time */
+ curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 2L);
+
+ res = curl_easy_perform(curl);
+
+ /* in this second request, the cache is not be used if more than
+ two seconds have passed since the previous name resolve */
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3 b/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3
deleted file mode 100644
index 4f8d3106e..000000000
--- a/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DNS_INTERFACE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DNS_INTERFACE \- interface to speak DNS over
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_INTERFACE, char *ifname);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter. Set the name of the network interface that the DNS
-resolver should bind to. This must be an interface name (not an address). Set
-this option to NULL to use the default setting (do not bind to a specific
-interface).
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All protocols except file:// - protocols that resolve host names.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_DNS_INTERFACE, "eth0");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.33.0. This option also requires that libcurl was built with a
-resolver backend that supports this operation. The c-ares backend is the only
-such one.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
-or CURLE_NOT_BUILT_IN if support was disabled at compile-time.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_LOCAL_IP4 (3),
-.BR CURLOPT_DNS_LOCAL_IP6 (3),
-.BR CURLOPT_DNS_SERVERS (3),
-.BR CURLOPT_INTERFACE (3)
diff --git a/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md b/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md
new file mode 100644
index 000000000..070bdc5af
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DNS_INTERFACE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_LOCAL_IP4 (3)
+ - CURLOPT_DNS_LOCAL_IP6 (3)
+ - CURLOPT_DNS_SERVERS (3)
+ - CURLOPT_INTERFACE (3)
+---
+
+# NAME
+
+CURLOPT_DNS_INTERFACE - interface to speak DNS over
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_INTERFACE, char *ifname);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter. Set the name of the network interface that
+the DNS resolver should bind to. This must be an interface name (not an
+address). Set this option to NULL to use the default setting (do not bind to a
+specific interface).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All protocols except file:// - protocols that resolve host names.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_DNS_INTERFACE, "eth0");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.33.0. This option also requires that libcurl was built with a
+resolver backend that supports this operation. The c-ares backend is the only
+such one.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
+or CURLE_NOT_BUILT_IN if support was disabled at compile-time.
diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3 b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3
deleted file mode 100644
index 210e37fbf..000000000
--- a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DNS_LOCAL_IP4 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DNS_LOCAL_IP4 \- IPv4 address to bind DNS resolves to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP4, char *address);
-.fi
-.SH DESCRIPTION
-Set the local IPv4 \fIaddress\fP that the resolver should bind to. The
-argument should be of type char * and contain a single numerical IPv4 address
-as a string. Set this option to NULL to use the default setting (do not bind
-to a specific IP address).
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_DNS_LOCAL_IP4, "192.168.0.14");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option requires that libcurl was built with a resolver backend that
-supports this operation. The c-ares backend is the only such one.
-
-Added in 7.33.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
-CURLE_NOT_BUILT_IN if support was disabled at compile-time, or
-CURLE_BAD_FUNCTION_ARGUMENT when given a bad address.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_INTERFACE (3),
-.BR CURLOPT_DNS_LOCAL_IP6 (3),
-.BR CURLOPT_DNS_SERVERS (3)
diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md
new file mode 100644
index 000000000..69af83b6b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DNS_LOCAL_IP4
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_INTERFACE (3)
+ - CURLOPT_DNS_LOCAL_IP6 (3)
+ - CURLOPT_DNS_SERVERS (3)
+---
+
+# NAME
+
+CURLOPT_DNS_LOCAL_IP4 - IPv4 address to bind DNS resolves to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP4, char *address);
+~~~
+
+# DESCRIPTION
+
+Set the local IPv4 *address* that the resolver should bind to. The argument
+should be of type char * and contain a single numerical IPv4 address as a
+string. Set this option to NULL to use the default setting (do not bind to a
+specific IP address).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_DNS_LOCAL_IP4, "192.168.0.14");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option requires that libcurl was built with a resolver backend that
+supports this operation. The c-ares backend is the only such one.
+
+Added in 7.33.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
+CURLE_NOT_BUILT_IN if support was disabled at compile-time, or
+CURLE_BAD_FUNCTION_ARGUMENT when given a bad address.
diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3 b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3
deleted file mode 100644
index 4f993998b..000000000
--- a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DNS_LOCAL_IP6 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DNS_LOCAL_IP6 \- IPv6 address to bind DNS resolves to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP6, char *address);
-.fi
-.SH DESCRIPTION
-Set the local IPv6 \fIaddress\fP that the resolver should bind to. The
-argument should be of type char * and contain a single IPv6 address as a
-string. Set this option to NULL to use the default setting (do not bind to a
-specific IP address).
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_DNS_LOCAL_IP6, "fe80::a9ff:fe46:b619");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option requires that libcurl was built with a resolver backend that
-supports this operation. The c-ares backend is the only such one.
-
-Added in 7.33.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
-CURLE_NOT_BUILT_IN if support was disabled at compile-time, or
-CURLE_BAD_FUNCTION_ARGUMENT when given a bad address.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_INTERFACE (3),
-.BR CURLOPT_DNS_LOCAL_IP4 (3),
-.BR CURLOPT_DNS_SERVERS (3)
diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md
new file mode 100644
index 000000000..fb04ee899
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DNS_LOCAL_IP6
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_INTERFACE (3)
+ - CURLOPT_DNS_LOCAL_IP4 (3)
+ - CURLOPT_DNS_SERVERS (3)
+---
+
+# NAME
+
+CURLOPT_DNS_LOCAL_IP6 - IPv6 address to bind DNS resolves to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP6, char *address);
+~~~
+
+# DESCRIPTION
+
+Set the local IPv6 *address* that the resolver should bind to. The argument
+should be of type char * and contain a single IPv6 address as a string. Set
+this option to NULL to use the default setting (do not bind to a specific IP
+address).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_DNS_LOCAL_IP6, "fe80::a9ff:fe46:b619");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option requires that libcurl was built with a resolver backend that
+supports this operation. The c-ares backend is the only such one.
+
+Added in 7.33.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
+CURLE_NOT_BUILT_IN if support was disabled at compile-time, or
+CURLE_BAD_FUNCTION_ARGUMENT when given a bad address.
diff --git a/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3 b/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3
deleted file mode 100644
index 53f7319a9..000000000
--- a/docs/libcurl/opts/CURLOPT_DNS_SERVERS.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DNS_SERVERS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DNS_SERVERS \- DNS servers to use
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_SERVERS, char *servers);
-.fi
-.SH DESCRIPTION
-Pass a char * that is the list of DNS servers to be used instead of the system
-default. The format of the dns servers option is:
-
-host[:port][,host[:port]]...
-
-For example:
-
-192.168.1.100,192.168.1.101,3.4.5.6
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL - use system default
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_DNS_SERVERS, "192.168.1.100:53,192.168.1.101");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option requires that libcurl was built with a resolver backend that
-supports this operation. The c-ares backend is the only such one.
-
-Added in 7.24.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
-CURLE_NOT_BUILT_IN if support was disabled at compile-time,
-CURLE_BAD_FUNCTION_ARGUMENT when given an invalid server list, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_CACHE_TIMEOUT (3),
-.BR CURLOPT_DNS_LOCAL_IP4 (3),
-.BR CURLOPT_DNS_LOCAL_IP6 (3)
diff --git a/docs/libcurl/opts/CURLOPT_DNS_SERVERS.md b/docs/libcurl/opts/CURLOPT_DNS_SERVERS.md
new file mode 100644
index 000000000..998257c79
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DNS_SERVERS.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DNS_SERVERS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_CACHE_TIMEOUT (3)
+ - CURLOPT_DNS_LOCAL_IP4 (3)
+ - CURLOPT_DNS_LOCAL_IP6 (3)
+---
+
+# NAME
+
+CURLOPT_DNS_SERVERS - DNS servers to use
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_SERVERS, char *servers);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer that is the list of DNS servers to be used instead of the
+system default. The format of the dns servers option is:
+
+host[:port][,host[:port]]...
+
+For example:
+
+192.168.1.100,192.168.1.101,3.4.5.6
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL - use system default
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_DNS_SERVERS,
+ "192.168.1.100:53,192.168.1.101");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option requires that libcurl was built with a resolver backend that
+supports this operation. The c-ares backend is the only such one.
+
+Added in 7.24.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not,
+CURLE_NOT_BUILT_IN if support was disabled at compile-time,
+CURLE_BAD_FUNCTION_ARGUMENT when given an invalid server list, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3 b/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3
deleted file mode 100644
index ebf0b9aab..000000000
--- a/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DNS_SHUFFLE_ADDRESSES 3 "3 March 2018" libcurl libcurl
-.SH NAME
-CURLOPT_DNS_SHUFFLE_ADDRESSES \- shuffle IP addresses for hostname
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_SHUFFLE_ADDRESSES, long onoff);
-.fi
-.SH DESCRIPTION
-Pass a long set to 1 to enable this option.
-
-When a name is resolved and more than one IP address is returned, this
-function shuffles the order of all returned addresses so that they are used in
-a random order. This is similar to the ordering behavior of the legacy
-gethostbyname function which is no longer used on most platforms.
-
-Addresses are not reshuffled if name resolution is completed using the DNS
-cache. \fICURLOPT_DNS_CACHE_TIMEOUT(3)\fP can be used together with this
-option to reduce DNS cache timeout or disable caching entirely if frequent
-reshuffling is needed.
-
-Since the addresses returned are randomly reordered, the order is not in
-accordance with RFC 3484 or any other deterministic order that may be
-generated by the system's name resolution implementation. This may have
-performance impacts and may cause IPv4 to be used before IPv6 or vice versa.
-.SH DEFAULT
-0 (disabled)
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_DNS_SHUFFLE_ADDRESSES, 1L);
-
- curl_easy_perform(curl);
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.60.0
-.SH RETURN VALUE
-CURLE_OK or an error such as CURLE_UNKNOWN_OPTION.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_CACHE_TIMEOUT (3),
-.BR CURLOPT_IPRESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.md b/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.md
new file mode 100644
index 000000000..f15abc9c7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DNS_SHUFFLE_ADDRESSES.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DNS_SHUFFLE_ADDRESSES
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_CACHE_TIMEOUT (3)
+ - CURLOPT_IPRESOLVE (3)
+---
+
+# NAME
+
+CURLOPT_DNS_SHUFFLE_ADDRESSES - shuffle IP addresses for hostname
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_SHUFFLE_ADDRESSES, long onoff);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 1 to enable this option.
+
+When a name is resolved and more than one IP address is returned, this
+function shuffles the order of all returned addresses so that they are used in
+a random order. This is similar to the ordering behavior of the legacy
+gethostbyname function which is no longer used on most platforms.
+
+Addresses are not reshuffled if name resolution is completed using the DNS
+cache. CURLOPT_DNS_CACHE_TIMEOUT(3) can be used together with this
+option to reduce DNS cache timeout or disable caching entirely if frequent
+reshuffling is needed.
+
+Since the addresses returned are randomly reordered, the order is not in
+accordance with RFC 3484 or any other deterministic order that may be
+generated by the system's name resolution implementation. This may have
+performance impacts and may cause IPv4 to be used before IPv6 or vice versa.
+
+# DEFAULT
+
+0 (disabled)
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_DNS_SHUFFLE_ADDRESSES, 1L);
+
+ curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.60.0
+
+# RETURN VALUE
+
+CURLE_OK or an error such as CURLE_UNKNOWN_OPTION.
diff --git a/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3 b/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3
deleted file mode 100644
index 3de886119..000000000
--- a/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DNS_USE_GLOBAL_CACHE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_DNS_USE_GLOBAL_CACHE \- global DNS cache
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_USE_GLOBAL_CACHE,
- long enable);
-.fi
-.SH DESCRIPTION
-Has no function since 7.62.0. Do not use!
-
-Pass a long. If the \fIenable\fP value is 1, it tells curl to use a global DNS
-cache that survives between easy handle creations and deletions. This is not
-thread-safe and this uses a global variable.
-
-See \fICURLOPT_SHARE(3)\fP and \fIcurl_share_init(3)\fP for the correct way to
-share DNS cache between transfers.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* switch off the use of a global, thread unsafe, cache */
- curl_easy_setopt(curl, CURLOPT_DNS_USE_GLOBAL_CACHE, 0L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Deprecated since 7.11.1. Function removed in 7.62.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_CACHE_TIMEOUT (3),
-.BR CURLOPT_SHARE (3)
diff --git a/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md b/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md
new file mode 100644
index 000000000..dfbc22916
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DNS_USE_GLOBAL_CACHE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_CACHE_TIMEOUT (3)
+ - CURLOPT_SHARE (3)
+---
+
+# NAME
+
+CURLOPT_DNS_USE_GLOBAL_CACHE - global DNS cache
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_USE_GLOBAL_CACHE,
+ long enable);
+~~~
+
+# DESCRIPTION
+
+Has no function since 7.62.0. Do not use!
+
+Pass a long. If the *enable* value is 1, it tells curl to use a global DNS
+cache that survives between easy handle creations and deletions. This is not
+thread-safe and this uses a global variable.
+
+See CURLOPT_SHARE(3) and curl_share_init(3) for the correct way to
+share DNS cache between transfers.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* switch off the use of a global, thread unsafe, cache */
+ curl_easy_setopt(curl, CURLOPT_DNS_USE_GLOBAL_CACHE, 0L);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+
+~~~
+
+# AVAILABILITY
+
+Deprecated since 7.11.1. Function removed in 7.62.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.3 b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.3
deleted file mode 100644
index fa49d38f2..000000000
--- a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DOH_SSL_VERIFYHOST 3 "11 Feb 2021" libcurl libcurl
-.SH NAME
-CURLOPT_DOH_SSL_VERIFYHOST \- verify the host name in the DoH SSL certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_SSL_VERIFYHOST,
- long verify);
-.fi
-.SH DESCRIPTION
-Pass a long set to 2L as asking curl to \fIverify\fP the DoH (DNS-over-HTTPS)
-server's certificate name fields against the host name.
-
-This option is the DoH equivalent of \fICURLOPT_SSL_VERIFYHOST(3)\fP and
-only affects requests to the DoH server.
-
-When \fICURLOPT_DOH_SSL_VERIFYHOST(3)\fP is 2, the SSL certificate provided by
-the DoH server must indicate that the server name is the same as the server
-name to which you meant to connect to, or the connection fails.
-
-Curl considers the DoH server the intended one when the Common Name field or a
-Subject Alternate Name field in the certificate matches the host name in the
-DoH URL to which you told Curl to connect.
-
-When the \fIverify\fP value is set to 1L it is treated the same as 2L. However
-for consistency with the other \fIVERIFYHOST\fP options we suggest use 2 and
-not 1.
-
-When the \fIverify\fP value is set to 0L, the connection succeeds regardless of
-the names used in the certificate. Use that ability with caution!
-
-See also \fICURLOPT_DOH_SSL_VERIFYPEER(3)\fP to verify the digital signature
-of the DoH server certificate.
-.SH DEFAULT
-2
-.SH PROTOCOLS
-DoH
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_DOH_URL, "https://cloudflare-dns.com/dns-query");
-
- /* Disable host name verification of the DoH server */
- curl_easy_setopt(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.76.0
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DOH_SSL_VERIFYPEER (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.md b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.md
new file mode 100644
index 000000000..051e6be53
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.md
@@ -0,0 +1,90 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DOH_SSL_VERIFYHOST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DOH_SSL_VERIFYPEER (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_DOH_SSL_VERIFYHOST - verify the hostname in the DoH SSL certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_SSL_VERIFYHOST,
+ long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 2L as asking curl to *verify* the DoH (DNS-over-HTTPS)
+server's certificate name fields against the hostname.
+
+This option is the DoH equivalent of CURLOPT_SSL_VERIFYHOST(3) and
+only affects requests to the DoH server.
+
+When CURLOPT_DOH_SSL_VERIFYHOST(3) is 2, the SSL certificate provided by
+the DoH server must indicate that the server name is the same as the server
+name to which you meant to connect to, or the connection fails.
+
+Curl considers the DoH server the intended one when the Common Name field or a
+Subject Alternate Name field in the certificate matches the hostname in the
+DoH URL to which you told Curl to connect.
+
+When the *verify* value is set to 1L it is treated the same as 2L. However
+for consistency with the other *VERIFYHOST* options we suggest use 2 and
+not 1.
+
+When the *verify* value is set to 0L, the connection succeeds regardless of
+the names used in the certificate. Use that ability with caution!
+
+See also CURLOPT_DOH_SSL_VERIFYPEER(3) to verify the digital signature
+of the DoH server certificate.
+
+# DEFAULT
+
+2
+
+# PROTOCOLS
+
+DoH
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_DOH_URL,
+ "https://cloudflare-dns.com/dns-query");
+
+ /* Disable host name verification of the DoH server */
+ curl_easy_setopt(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.76.0
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3 b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3
deleted file mode 100644
index 0e2f5172a..000000000
--- a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.3
+++ /dev/null
@@ -1,101 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DOH_SSL_VERIFYPEER 3 "11 Feb 2021" libcurl libcurl
-.SH NAME
-CURLOPT_DOH_SSL_VERIFYPEER \- verify the DoH SSL certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_SSL_VERIFYPEER,
- long verify);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter set to 1L to enable or 0L to disable.
-
-This option tells curl to verify the authenticity of the DoH (DNS-over-HTTPS)
-server's certificate. A value of 1 means curl verifies; 0 (zero) means it
-does not.
-
-This option is the DoH equivalent of \fICURLOPT_SSL_VERIFYPEER(3)\fP and
-only affects requests to the DoH server.
-
-When negotiating a TLS or SSL connection, the server sends a certificate
-indicating its identity. Curl verifies whether the certificate is authentic,
-i.e. that you can trust that the server is who the certificate says it is.
-This trust is based on a chain of digital signatures, rooted in certification
-authority (CA) certificates you supply. curl uses a default bundle of CA
-certificates (the path for that is determined at build time) and you can
-specify alternate certificates with the \fICURLOPT_CAINFO(3)\fP option
-or the \fICURLOPT_CAPATH(3)\fP option.
-
-When \fICURLOPT_DOH_SSL_VERIFYPEER(3)\fP is enabled, and the verification
-fails to prove that the certificate is authentic, the connection fails. When
-the option is zero, the peer certificate verification succeeds regardless.
-
-Authenticating the certificate is not enough to be sure about the server. You
-typically also want to ensure that the server is the server you mean to be
-talking to. Use \fICURLOPT_DOH_SSL_VERIFYHOST(3)\fP for that. The check
-that the host name in the certificate is valid for the host name you are
-connecting to is done independently of the
-\fICURLOPT_DOH_SSL_VERIFYPEER(3)\fP option.
-
-WARNING: disabling verification of the certificate allows bad guys to
-man-in-the-middle the communication without you knowing it. Disabling
-verification makes the communication insecure. Just having encryption on a
-transfer is not enough as you cannot be sure that you are communicating with
-the correct end-point.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-DoH
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_DOH_URL, "https://cloudflare-dns.com/dns-query");
-
- /* Disable certificate verification of the DoH server */
- curl_easy_setopt(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.76.0
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CAINFO (3),
-.BR CURLOPT_CAPATH (3),
-.BR CURLOPT_DOH_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.md b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.md
new file mode 100644
index 000000000..e2a5a5e69
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYPEER.md
@@ -0,0 +1,102 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DOH_SSL_VERIFYPEER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_CAPATH (3)
+ - CURLOPT_DOH_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_DOH_SSL_VERIFYPEER - verify the DoH SSL certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_SSL_VERIFYPEER,
+ long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter set to 1L to enable or 0L to disable.
+
+This option tells curl to verify the authenticity of the DoH (DNS-over-HTTPS)
+server's certificate. A value of 1 means curl verifies; 0 (zero) means it
+does not.
+
+This option is the DoH equivalent of CURLOPT_SSL_VERIFYPEER(3) and
+only affects requests to the DoH server.
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. Curl verifies whether the certificate is authentic,
+i.e. that you can trust that the server is who the certificate says it is.
+This trust is based on a chain of digital signatures, rooted in certification
+authority (CA) certificates you supply. curl uses a default bundle of CA
+certificates (the path for that is determined at build time) and you can
+specify alternate certificates with the CURLOPT_CAINFO(3) option or the
+CURLOPT_CAPATH(3) option.
+
+When CURLOPT_DOH_SSL_VERIFYPEER(3) is enabled, and the verification fails to
+prove that the certificate is authentic, the connection fails. When the option
+is zero, the peer certificate verification succeeds regardless.
+
+Authenticating the certificate is not enough to be sure about the server. You
+typically also want to ensure that the server is the server you mean to be
+talking to. Use CURLOPT_DOH_SSL_VERIFYHOST(3) for that. The check that the
+hostname in the certificate is valid for the hostname you are connecting to
+is done independently of the CURLOPT_DOH_SSL_VERIFYPEER(3) option.
+
+WARNING: disabling verification of the certificate allows bad guys to
+man-in-the-middle the communication without you knowing it. Disabling
+verification makes the communication insecure. Just having encryption on a
+transfer is not enough as you cannot be sure that you are communicating with
+the correct end-point.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+DoH
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_DOH_URL,
+ "https://cloudflare-dns.com/dns-query");
+
+ /* Disable certificate verification of the DoH server */
+ curl_easy_setopt(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.76.0
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.3 b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.3
deleted file mode 100644
index acf8bcb39..000000000
--- a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DOH_SSL_VERIFYSTATUS 3 "11 Feb 2021" libcurl libcurl
-.SH NAME
-CURLOPT_DOH_SSL_VERIFYSTATUS \- verify the DoH SSL certificate's status
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_SSL_VERIFYSTATUS,
- long verify);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter set to 1 to enable or 0 to disable.
-
-This option determines whether libcurl verifies the status of the DoH
-(DNS-over-HTTPS) server cert using the "Certificate Status Request" TLS
-extension (aka. OCSP stapling).
-
-This option is the DoH equivalent of \fICURLOPT_SSL_VERIFYSTATUS(3)\fP and
-only affects requests to the DoH server.
-
-If this option is enabled and the server does not support the TLS extension,
-the verification fails.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-DoH
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_DOH_URL, "https://cloudflare-dns.com/dns-query");
-
- /* Ask for OCSP stapling when verifying the DoH server */
- curl_easy_setopt(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.76.0. This option is currently only supported by the OpenSSL, and
-GnuTLS TLS backends.
-.SH RETURN VALUE
-Returns CURLE_OK if OCSP stapling is supported by the SSL backend, otherwise
-returns CURLE_NOT_BUILT_IN.
-.SH "SEE ALSO"
-.BR CURLOPT_DOH_SSL_VERIFYHOST (3),
-.BR CURLOPT_DOH_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYSTATUS (3)
diff --git a/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.md b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.md
new file mode 100644
index 000000000..19489986b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYSTATUS.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DOH_SSL_VERIFYSTATUS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DOH_SSL_VERIFYHOST (3)
+ - CURLOPT_DOH_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYSTATUS (3)
+---
+
+# NAME
+
+CURLOPT_DOH_SSL_VERIFYSTATUS - verify the DoH SSL certificate's status
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_SSL_VERIFYSTATUS,
+ long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter set to 1 to enable or 0 to disable.
+
+This option determines whether libcurl verifies the status of the DoH
+(DNS-over-HTTPS) server cert using the "Certificate Status Request" TLS
+extension (aka. OCSP stapling).
+
+This option is the DoH equivalent of CURLOPT_SSL_VERIFYSTATUS(3) and
+only affects requests to the DoH server.
+
+If this option is enabled and the server does not support the TLS extension,
+the verification fails.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+DoH
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_DOH_URL,
+ "https://cloudflare-dns.com/dns-query");
+
+ /* Ask for OCSP stapling when verifying the DoH server */
+ curl_easy_setopt(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.76.0. This option is currently only supported by the OpenSSL, and
+GnuTLS TLS backends.
+
+# RETURN VALUE
+
+Returns CURLE_OK if OCSP stapling is supported by the SSL backend, otherwise
+returns CURLE_NOT_BUILT_IN.
diff --git a/docs/libcurl/opts/CURLOPT_DOH_URL.3 b/docs/libcurl/opts/CURLOPT_DOH_URL.3
deleted file mode 100644
index cfe4a574d..000000000
--- a/docs/libcurl/opts/CURLOPT_DOH_URL.3
+++ /dev/null
@@ -1,92 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_DOH_URL 3 "18 Jun 2018" libcurl libcurl
-.SH NAME
-CURLOPT_DOH_URL \- provide the DNS-over-HTTPS URL
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_URL, char *URL);
-.fi
-.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 null-terminated string which
-must be URL-encoded in the following format: "https://host:port/path". It MUST
-specify an HTTPS URL.
-
-libcurl does not validate the syntax or use this variable until the transfer
-is issued. Even if you set a crazy value here, \fIcurl_easy_setopt(3)\fP still
-returns \fICURLE_OK\fP.
-
-curl sends POST requests to the given DNS-over-HTTPS URL.
-
-To find the DoH server itself, which might be specified using a name, libcurl
-uses the default name lookup function. You can bootstrap that by providing the
-address for the DoH server with \fICURLOPT_RESOLVE(3)\fP.
-
-Disable DoH use again by setting this option to NULL.
-.SH "INHERIT OPTIONS"
-DoH lookups use SSL and some SSL settings from your transfer are inherited,
-like \fICURLOPT_SSL_CTX_FUNCTION(3)\fP.
-
-The hostname and peer certificate verification settings are not inherited but
-can be controlled separately via \fICURLOPT_DOH_SSL_VERIFYHOST(3)\fP and
-\fICURLOPT_DOH_SSL_VERIFYPEER(3)\fP.
-
-A set \fICURLOPT_OPENSOCKETFUNCTION(3)\fP callback is not inherited.
-.SH "KNOWN BUGS"
-Even when DoH is set to be used with this option, there are still some name
-resolves that are performed without it, using the default name resolver
-mechanism. This includes name resolves done for \fICURLOPT_INTERFACE(3)\fP,
-\fICURLOPT_FTPPORT(3)\fP, a proxy type set to \fBCURLPROXY_SOCKS4\fP or
-\fBCURLPROXY_SOCKS5\fP and probably some more.
-.SH DEFAULT
-NULL - there is no default DoH URL. If this option is not set, libcurl uses
-the default name resolver.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_DOH_URL, "https://dns.example.com");
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.62.0
-.SH RETURN VALUE
-Returns CURLE_OK on success or CURLE_OUT_OF_MEMORY if there was insufficient
-heap space.
-
-Note that \fIcurl_easy_setopt(3)\fP does immediately parse the given string so
-when given a bad DoH URL, libcurl might not detect the problem until it later
-tries to resolve a name with it.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_CACHE_TIMEOUT (3),
-.BR CURLOPT_RESOLVE (3),
-.BR CURLOPT_VERBOSE (3)
diff --git a/docs/libcurl/opts/CURLOPT_DOH_URL.md b/docs/libcurl/opts/CURLOPT_DOH_URL.md
new file mode 100644
index 000000000..a2e46b4c0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_DOH_URL.md
@@ -0,0 +1,96 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_DOH_URL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_CACHE_TIMEOUT (3)
+ - CURLOPT_RESOLVE (3)
+ - CURLOPT_VERBOSE (3)
+---
+
+# NAME
+
+CURLOPT_DOH_URL - provide the DNS-over-HTTPS URL
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_URL, char *URL);
+~~~
+
+# DESCRIPTION
+
+Pass in a pointer to a *URL* for the DoH server to use for name resolving. The
+parameter should be a char pointer to a null-terminated string which must be a
+valid and correct HTTPS URL.
+
+libcurl does not validate the syntax or use this variable until the transfer
+is issued. Even if you set a crazy value here, curl_easy_setopt(3) still
+returns *CURLE_OK*.
+
+curl sends POST requests to the given DNS-over-HTTPS URL.
+
+To find the DoH server itself, which might be specified using a name, libcurl
+uses the default name lookup function. You can bootstrap that by providing the
+address for the DoH server with CURLOPT_RESOLVE(3).
+
+Disable DoH use again by setting this option to NULL.
+
+# INHERIT OPTIONS
+
+DoH lookups use SSL and some SSL settings from your transfer are inherited,
+like CURLOPT_SSL_CTX_FUNCTION(3).
+
+The hostname and peer certificate verification settings are not inherited but
+can be controlled separately via CURLOPT_DOH_SSL_VERIFYHOST(3) and
+CURLOPT_DOH_SSL_VERIFYPEER(3).
+
+A set CURLOPT_OPENSOCKETFUNCTION(3) callback is not inherited.
+
+# KNOWN BUGS
+
+Even when DoH is set to be used with this option, there are still some name
+resolves that are performed without it, using the default name resolver
+mechanism. This includes name resolves done for CURLOPT_INTERFACE(3),
+CURLOPT_FTPPORT(3), a proxy type set to **CURLPROXY_SOCKS4** or
+**CURLPROXY_SOCKS5** and probably some more.
+
+# DEFAULT
+
+NULL - there is no default DoH URL. If this option is not set, libcurl uses
+the default name resolver.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_DOH_URL, "https://dns.example.com");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0
+
+# RETURN VALUE
+
+Returns CURLE_OK on success or CURLE_OUT_OF_MEMORY if there was insufficient
+heap space.
+
+Note that curl_easy_setopt(3) does immediately parse the given string so
+when given a bad DoH URL, libcurl might not detect the problem until it later
+tries to resolve a name with it.
diff --git a/docs/libcurl/opts/CURLOPT_EGDSOCKET.3 b/docs/libcurl/opts/CURLOPT_EGDSOCKET.3
deleted file mode 100644
index f36469b2b..000000000
--- a/docs/libcurl/opts/CURLOPT_EGDSOCKET.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_EGDSOCKET 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_EGDSOCKET \- EGD socket path
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_EGDSOCKET, char *path);
-.fi
-.SH DESCRIPTION
-Deprecated option. It serves no purpose anymore.
-
-Pass a char * to the null-terminated path name to the Entropy Gathering Daemon
-socket. It is used to seed the random engine for TLS.
-
-The application does not have to keep the string around after setting this
-option.
-.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) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_EGDSOCKET, "/var/egd.socket");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If built with TLS enabled. Only the OpenSSL backend uses this, and only with
-OpenSSL versions before 1.1.0.
-
-This option was deprecated in 7.84.0.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_RANDOM_FILE (3)
diff --git a/docs/libcurl/opts/CURLOPT_EGDSOCKET.md b/docs/libcurl/opts/CURLOPT_EGDSOCKET.md
new file mode 100644
index 000000000..a472f5ea5
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_EGDSOCKET.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_EGDSOCKET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_RANDOM_FILE (3)
+---
+
+# NAME
+
+CURLOPT_EGDSOCKET - EGD socket path
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_EGDSOCKET, char *path);
+~~~
+
+# DESCRIPTION
+
+Deprecated option. It serves no purpose anymore.
+
+Pass a char pointer to the null-terminated path name to the Entropy Gathering
+Daemon socket. It is used to seed the random engine for TLS.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_EGDSOCKET, "/var/egd.socket");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built with TLS enabled. Only the OpenSSL backend uses this, and only with
+OpenSSL versions before 1.1.0.
+
+This option was deprecated in 7.84.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3 b/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3
deleted file mode 100644
index 136a11c3f..000000000
--- a/docs/libcurl/opts/CURLOPT_ERRORBUFFER.3
+++ /dev/null
@@ -1,99 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ERRORBUFFER 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_ERRORBUFFER \- error buffer for error messages
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ERRORBUFFER, char *buf);
-.fi
-.SH DESCRIPTION
-Pass a char * to a buffer that libcurl may use to store human readable error
-messages on failures or problems. This may be more helpful than just the
-return code from \fIcurl_easy_perform(3)\fP and related functions. The buffer
-must be at least \fBCURL_ERROR_SIZE\fP bytes big.
-
-You must keep the associated buffer available until libcurl no longer needs
-it. Failing to do so might cause odd behavior or even crashes. libcurl might
-need it until you call \fIcurl_easy_cleanup(3)\fP or you set the same option
-again to use a different pointer.
-
-Do not rely on the contents of the buffer unless an error code was returned.
-Since 7.60.0 libcurl initializes the contents of the error buffer to an empty
-string before performing the transfer. For earlier versions if an error code
-was returned but there was no error detail then the buffer was untouched.
-
-Consider \fICURLOPT_VERBOSE(3)\fP and \fICURLOPT_DEBUGFUNCTION(3)\fP to better
-debug and trace why errors happen.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- CURLcode res;
- char errbuf[CURL_ERROR_SIZE];
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* provide a buffer to store errors in */
- curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
-
- /* set the error buffer as empty before performing a request */
- errbuf[0] = 0;
-
- /* perform the request */
- res = curl_easy_perform(curl);
-
- /* if the request did not complete correctly, show the error
- information. if no detailed error information was written to errbuf
- show the more generic information from curl_easy_strerror instead.
- */
- if(res != CURLE_OK) {
- size_t len = strlen(errbuf);
- fprintf(stderr, "\\nlibcurl: (%d) ", res);
- if(len)
- fprintf(stderr, "%s%s", errbuf,
- ((errbuf[len - 1] != '\\n') ? "\\n" : ""));
- else
- fprintf(stderr, "%s\\n", curl_easy_strerror(res));
- }
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR curl_easy_strerror (3),
-.BR curl_multi_strerror (3),
-.BR curl_share_strerror (3),
-.BR curl_url_strerror (3),
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_VERBOSE (3)
diff --git a/docs/libcurl/opts/CURLOPT_ERRORBUFFER.md b/docs/libcurl/opts/CURLOPT_ERRORBUFFER.md
new file mode 100644
index 000000000..ed5d361ef
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ERRORBUFFER.md
@@ -0,0 +1,101 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ERRORBUFFER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_VERBOSE (3)
+ - curl_easy_strerror (3)
+ - curl_multi_strerror (3)
+ - curl_share_strerror (3)
+ - curl_url_strerror (3)
+---
+
+# NAME
+
+CURLOPT_ERRORBUFFER - error buffer for error messages
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ERRORBUFFER, char *buf);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to a buffer that libcurl may use to store human readable
+error messages on failures or problems. This may be more helpful than just the
+return code from curl_easy_perform(3) and related functions. The buffer must
+be at least **CURL_ERROR_SIZE** bytes big.
+
+You must keep the associated buffer available until libcurl no longer needs
+it. Failing to do so might cause odd behavior or even crashes. libcurl might
+need it until you call curl_easy_cleanup(3) or you set the same option
+again to use a different pointer.
+
+Do not rely on the contents of the buffer unless an error code was returned.
+Since 7.60.0 libcurl initializes the contents of the error buffer to an empty
+string before performing the transfer. For earlier versions if an error code
+was returned but there was no error detail then the buffer was untouched.
+
+Consider CURLOPT_VERBOSE(3) and CURLOPT_DEBUGFUNCTION(3) to better
+debug and trace why errors happen.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+#include <string.h> /* for strlen() */
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ char errbuf[CURL_ERROR_SIZE];
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* provide a buffer to store errors in */
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
+
+ /* set the error buffer as empty before performing a request */
+ errbuf[0] = 0;
+
+ /* perform the request */
+ res = curl_easy_perform(curl);
+
+ /* if the request did not complete correctly, show the error
+ information. if no detailed error information was written to errbuf
+ show the more generic information from curl_easy_strerror instead.
+ */
+ if(res != CURLE_OK) {
+ size_t len = strlen(errbuf);
+ fprintf(stderr, "\nlibcurl: (%d) ", res);
+ if(len)
+ fprintf(stderr, "%s%s", errbuf,
+ ((errbuf[len - 1] != '\n') ? "\n" : ""));
+ else
+ fprintf(stderr, "%s\n", curl_easy_strerror(res));
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3
deleted file mode 100644
index 7aea1c2ed..000000000
--- a/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_EXPECT_100_TIMEOUT_MS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_EXPECT_100_TIMEOUT_MS \- timeout for Expect: 100-continue response
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_EXPECT_100_TIMEOUT_MS,
- long milliseconds);
-.SH DESCRIPTION
-Pass a long to tell libcurl the number of \fImilliseconds\fP to wait for a
-server response with the HTTP status 100 (Continue), 417 (Expectation Failed)
-or similar after sending an HTTP request containing an Expect: 100-continue
-header. If this times out before a response is received, the request body is
-sent anyway.
-.SH DEFAULT
-1000 milliseconds
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* wait 3 seconds for 100-continue */
- curl_easy_setopt(curl, CURLOPT_EXPECT_100_TIMEOUT_MS, 3000L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.36.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPPOST (3),
-.BR CURLOPT_POST (3)
diff --git a/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.md b/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.md
new file mode 100644
index 000000000..9458cfc63
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_EXPECT_100_TIMEOUT_MS.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_EXPECT_100_TIMEOUT_MS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPPOST (3)
+ - CURLOPT_POST (3)
+---
+
+# NAME
+
+CURLOPT_EXPECT_100_TIMEOUT_MS - timeout for Expect: 100-continue response
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_EXPECT_100_TIMEOUT_MS,
+ long milliseconds);
+~~~
+
+# DESCRIPTION
+
+Pass a long to tell libcurl the number of *milliseconds* to wait for a
+server response with the HTTP status 100 (Continue), 417 (Expectation Failed)
+or similar after sending an HTTP request containing an Expect: 100-continue
+header. If this times out before a response is received, the request body is
+sent anyway.
+
+# DEFAULT
+
+1000 milliseconds
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* wait 3 seconds for 100-continue */
+ curl_easy_setopt(curl, CURLOPT_EXPECT_100_TIMEOUT_MS, 3000L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.36.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FAILONERROR.3 b/docs/libcurl/opts/CURLOPT_FAILONERROR.3
deleted file mode 100644
index c62250352..000000000
--- a/docs/libcurl/opts/CURLOPT_FAILONERROR.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FAILONERROR 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FAILONERROR \- request failure on HTTP response >= 400
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FAILONERROR, long fail);
-.fi
-.SH DESCRIPTION
-A long parameter set to 1 tells the library to fail the request if the HTTP
-code returned is equal to or larger than 400. The default action would be to
-return the page normally, ignoring that code.
-
-This method is not fail-safe and there are occasions where non-successful
-response codes slip through, especially when authentication is involved
-(response codes 401 and 407).
-
-You might get some amounts of headers transferred before this situation is
-detected, like when a "100-continue" is received as a response to a POST/PUT
-and a 401 or 407 is received immediately afterwards.
-
-When this option is used and an error is detected, it causes the connection to
-get closed and \fICURLE_HTTP_RETURNED_ERROR\fP is returned.
-.SH DEFAULT
-0, do not fail on error
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
- ret = curl_easy_perform(curl);
- if(ret == CURLE_HTTP_RETURNED_ERROR) {
- /* an HTTP response error problem */
- }
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_RESPONSE_CODE (3),
-.BR CURLOPT_HTTP200ALIASES (3),
-.BR CURLOPT_KEEP_SENDING_ON_ERROR (3)
diff --git a/docs/libcurl/opts/CURLOPT_FAILONERROR.md b/docs/libcurl/opts/CURLOPT_FAILONERROR.md
new file mode 100644
index 000000000..7ea5cedc6
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FAILONERROR.md
@@ -0,0 +1,74 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FAILONERROR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RESPONSE_CODE (3)
+ - CURLOPT_HTTP200ALIASES (3)
+ - CURLOPT_KEEP_SENDING_ON_ERROR (3)
+---
+
+# NAME
+
+CURLOPT_FAILONERROR - request failure on HTTP response >= 400
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FAILONERROR, long fail);
+~~~
+
+# DESCRIPTION
+
+A long parameter set to 1 tells the library to fail the request if the HTTP
+code returned is equal to or larger than 400. The default action would be to
+return the page normally, ignoring that code.
+
+This method is not fail-safe and there are occasions where non-successful
+response codes slip through, especially when authentication is involved
+(response codes 401 and 407).
+
+You might get some amounts of headers transferred before this situation is
+detected, like when a "100-continue" is received as a response to a POST/PUT
+and a 401 or 407 is received immediately afterwards.
+
+When this option is used and an error is detected, it causes the connection to
+get closed and *CURLE_HTTP_RETURNED_ERROR* is returned.
+
+# DEFAULT
+
+0, do not fail on error
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
+ ret = curl_easy_perform(curl);
+ if(ret == CURLE_HTTP_RETURNED_ERROR) {
+ /* an HTTP response error problem */
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FILETIME.3 b/docs/libcurl/opts/CURLOPT_FILETIME.3
deleted file mode 100644
index 05f484a2f..000000000
--- a/docs/libcurl/opts/CURLOPT_FILETIME.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FILETIME 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FILETIME \- get the modification time of the remote resource
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FILETIME, long gettime);
-.fi
-.SH DESCRIPTION
-Pass a long. If it is 1, libcurl attempts to get the modification time of the
-remote document in this operation. This requires that the remote server sends
-the time or replies to a time querying command. The \fIcurl_easy_getinfo(3)\fP
-function with the \fICURLINFO_FILETIME(3)\fP argument can be used after a
-transfer to extract the received time (if any).
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP(S), FTP(S), SFTP, FILE, SMB(S)
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, url);
- /* Ask for filetime */
- curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
- res = curl_easy_perform(curl);
- if(CURLE_OK == res) {
- res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
- if((CURLE_OK == res) && (filetime >= 0)) {
- time_t file_time = (time_t)filetime;
- printf("filetime %s: %s", filename, ctime(&file_time));
- }
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always, for SFTP since 7.49.0
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR curl_easy_getinfo (3),
-.BR CURLINFO_FILETIME (3)
diff --git a/docs/libcurl/opts/CURLOPT_FILETIME.md b/docs/libcurl/opts/CURLOPT_FILETIME.md
new file mode 100644
index 000000000..013449105
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FILETIME.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FILETIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_FILETIME (3)
+ - curl_easy_getinfo (3)
+---
+
+# NAME
+
+CURLOPT_FILETIME - get the modification time of the remote resource
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FILETIME, long gettime);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If it is 1, libcurl attempts to get the modification time of the
+remote document in this operation. This requires that the remote server sends
+the time or replies to a time querying command. The curl_easy_getinfo(3)
+function with the CURLINFO_FILETIME(3) argument can be used after a
+transfer to extract the received time (if any).
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP(S), FTP(S), SFTP, FILE, SMB(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/path.html");
+ /* Ask for filetime */
+ curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
+ res = curl_easy_perform(curl);
+ if(CURLE_OK == res) {
+ long filetime;
+ res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
+ if((CURLE_OK == res) && (filetime >= 0)) {
+ time_t file_time = (time_t)filetime;
+ printf("filetime: %s", ctime(&file_time));
+ }
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always, for SFTP since 7.49.0
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3 b/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3
deleted file mode 100644
index e8d9feaa5..000000000
--- a/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FNMATCH_DATA 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FNMATCH_DATA \- pointer passed to the fnmatch callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FNMATCH_DATA,
- void *pointer);
-.SH DESCRIPTION
-Pass a pointer that is untouched by libcurl and passed as the ptr argument to
-the \fICURLOPT_FNMATCH_FUNCTION(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-static int my_fnmatch(void *clientp,
- const char *pattern, const char *string)
-{
- struct local_stuff *data = (struct local_stuff *)clientp;
- if(string_match(pattern, string))
- return CURL_FNMATCHFUNC_MATCH;
- else
- return CURL_FNMATCHFUNC_NOMATCH;
-}
-
-{
- struct local_stuff local_data;
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.example.com/file*");
- curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L);
- curl_easy_setopt(curl, CURLOPT_FNMATCH_FUNCTION, my_fnmatch);
- curl_easy_setopt(curl, CURLOPT_FNMATCH_DATA, &local_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FNMATCH_FUNCTION (3),
-.BR CURLOPT_WILDCARDMATCH (3)
diff --git a/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.md b/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.md
new file mode 100644
index 000000000..48b60723a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FNMATCH_DATA.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FNMATCH_DATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FNMATCH_FUNCTION (3)
+ - CURLOPT_WILDCARDMATCH (3)
+---
+
+# NAME
+
+CURLOPT_FNMATCH_DATA - pointer passed to the fnmatch callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FNMATCH_DATA,
+ void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer that is untouched by libcurl and passed as the ptr argument to
+the CURLOPT_FNMATCH_FUNCTION(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+extern int string_match(const char *s1, const char *s2);
+
+struct local_stuff {
+ void *custom;
+};
+
+static int my_fnmatch(void *clientp,
+ const char *pattern, const char *string)
+{
+ struct local_stuff *my = clientp;
+ printf("my ptr: %p\n", my->custom);
+
+ if(string_match(pattern, string))
+ return CURL_FNMATCHFUNC_MATCH;
+ else
+ return CURL_FNMATCHFUNC_NOMATCH;
+}
+
+int main(void)
+{
+ struct local_stuff local_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.example.com/file*");
+ curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L);
+ curl_easy_setopt(curl, CURLOPT_FNMATCH_FUNCTION, my_fnmatch);
+ curl_easy_setopt(curl, CURLOPT_FNMATCH_DATA, &local_data);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3
deleted file mode 100644
index 43466b3ec..000000000
--- a/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FNMATCH_FUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FNMATCH_FUNCTION \- wildcard match callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int fnmatch_callback(void *ptr,
- const char *pattern,
- const char *string);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FNMATCH_FUNCTION,
- fnmatch_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback is used for wildcard matching.
-
-Return \fICURL_FNMATCHFUNC_MATCH\fP if pattern matches the string,
-\fICURL_FNMATCHFUNC_NOMATCH\fP if not or \fICURL_FNMATCHFUNC_FAIL\fP if an
-error occurred.
-.SH DEFAULT
-NULL == an internal function for wildcard matching.
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-static int my_fnmatch(void *clientp,
- const char *pattern, const char *string)
-{
- struct local_stuff *data = (struct local_stuff *)clientp;
- if(string_match(pattern, string))
- return CURL_FNMATCHFUNC_MATCH;
- else
- return CURL_FNMATCHFUNC_NOMATCH;
-}
-
-{
- struct local_stuff local_data;
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.example.com/file*");
- curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L);
- curl_easy_setopt(curl, CURLOPT_FNMATCH_FUNCTION, my_fnmatch);
- curl_easy_setopt(curl, CURLOPT_FNMATCH_DATA, &local_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_FNMATCH_DATA (3),
-.BR CURLOPT_WILDCARDMATCH (3)
diff --git a/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.md b/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.md
new file mode 100644
index 000000000..8ed13bfe6
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FNMATCH_FUNCTION.md
@@ -0,0 +1,88 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FNMATCH_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_FNMATCH_DATA (3)
+ - CURLOPT_WILDCARDMATCH (3)
+---
+
+# NAME
+
+CURLOPT_FNMATCH_FUNCTION - wildcard match callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int fnmatch_callback(void *ptr,
+ const char *pattern,
+ const char *string);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FNMATCH_FUNCTION,
+ fnmatch_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback is used for wildcard matching.
+
+Return *CURL_FNMATCHFUNC_MATCH* if pattern matches the string,
+*CURL_FNMATCHFUNC_NOMATCH* if not or *CURL_FNMATCHFUNC_FAIL* if an
+error occurred.
+
+# DEFAULT
+
+NULL == an internal function for wildcard matching.
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+extern int string_match(const char *s1, const char *s2);
+
+struct local_stuff {
+ void *custom;
+};
+static int my_fnmatch(void *clientp,
+ const char *pattern, const char *string)
+{
+ struct local_stuff *data = clientp;
+ printf("my pointer: %p\n", data->custom);
+ if(string_match(pattern, string))
+ return CURL_FNMATCHFUNC_MATCH;
+ else
+ return CURL_FNMATCHFUNC_NOMATCH;
+}
+
+int main(void)
+{
+ struct local_stuff local_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.example.com/file*");
+ curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L);
+ curl_easy_setopt(curl, CURLOPT_FNMATCH_FUNCTION, my_fnmatch);
+ curl_easy_setopt(curl, CURLOPT_FNMATCH_DATA, &local_data);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3 b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3
deleted file mode 100644
index f86e9655a..000000000
--- a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.3
+++ /dev/null
@@ -1,90 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FOLLOWLOCATION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FOLLOWLOCATION \- follow HTTP 3xx redirects
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long enable);
-.fi
-.SH DESCRIPTION
-A long parameter set to 1 tells the library to follow any Location: header
-redirects that a HTTP server sends in a 30x response. The Location: header can
-specify a relative or an absolute URL to follow.
-
-libcurl issues another request for the new URL and follows subsequent new
-Location: redirects all the way until no more such headers are returned or the
-maximum limit is reached. \fICURLOPT_MAXREDIRS(3)\fP is used to limit the
-number of redirects libcurl follows.
-
-libcurl restricts what protocols it automatically follow redirects to. The
-accepted target protocols are set with \fICURLOPT_REDIR_PROTOCOLS(3)\fP. By
-default libcurl allows HTTP, HTTPS, FTP and FTPS on redirects.
-
-When following a redirect, the specific 30x response code also dictates which
-request method libcurl uses in the subsequent request: For 301, 302 and 303
-responses libcurl switches method from POST to GET unless
-\fICURLOPT_POSTREDIR(3)\fP instructs libcurl otherwise. All other redirect
-response codes make libcurl use the same method again.
-
-For users who think the existing location following is too naive, too simple
-or just lacks features, it is easy to instead implement your own redirect
-follow logic with the use of \fIcurl_easy_getinfo(3)\fP's
-\fICURLINFO_REDIRECT_URL(3)\fP option instead of using
-\fICURLOPT_FOLLOWLOCATION(3)\fP.
-.SH NOTE
-Since libcurl changes method or not based on the specific HTTP response code,
-setting \fICURLOPT_CUSTOMREQUEST(3)\fP while following redirects may change
-what libcurl would otherwise do and if not that carefully may even make it
-misbehave since \fICURLOPT_CUSTOMREQUEST(3)\fP overrides the method libcurl
-would otherwise select internally.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* example.com is redirected, so we tell libcurl to follow redirection */
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_REDIRECT_COUNT (3),
-.BR CURLINFO_REDIRECT_URL (3),
-.BR CURLOPT_POSTREDIR (3),
-.BR CURLOPT_PROTOCOLS (3),
-.BR CURLOPT_REDIR_PROTOCOLS (3)
diff --git a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md
new file mode 100644
index 000000000..9309dff21
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md
@@ -0,0 +1,93 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FOLLOWLOCATION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_COUNT (3)
+ - CURLINFO_REDIRECT_URL (3)
+ - CURLOPT_POSTREDIR (3)
+ - CURLOPT_PROTOCOLS (3)
+ - CURLOPT_REDIR_PROTOCOLS (3)
+---
+
+# NAME
+
+CURLOPT_FOLLOWLOCATION - follow HTTP 3xx redirects
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FOLLOWLOCATION, long enable);
+~~~
+
+# DESCRIPTION
+
+A long parameter set to 1 tells the library to follow any Location: header
+redirects that an HTTP server sends in a 30x response. The Location: header
+can specify a relative or an absolute URL to follow.
+
+libcurl issues another request for the new URL and follows subsequent new
+Location: redirects all the way until no more such headers are returned or the
+maximum limit is reached. CURLOPT_MAXREDIRS(3) is used to limit the
+number of redirects libcurl follows.
+
+libcurl restricts what protocols it automatically follow redirects to. The
+accepted target protocols are set with CURLOPT_REDIR_PROTOCOLS(3). By
+default libcurl allows HTTP, HTTPS, FTP and FTPS on redirects.
+
+When following a redirect, the specific 30x response code also dictates which
+request method libcurl uses in the subsequent request: For 301, 302 and 303
+responses libcurl switches method from POST to GET unless
+CURLOPT_POSTREDIR(3) instructs libcurl otherwise. All other redirect
+response codes make libcurl use the same method again.
+
+For users who think the existing location following is too naive, too simple
+or just lacks features, it is easy to instead implement your own redirect
+follow logic with the use of curl_easy_getinfo(3)'s
+CURLINFO_REDIRECT_URL(3) option instead of using
+CURLOPT_FOLLOWLOCATION(3).
+
+# NOTE
+
+Since libcurl changes method or not based on the specific HTTP response code,
+setting CURLOPT_CUSTOMREQUEST(3) while following redirects may change
+what libcurl would otherwise do and if not that carefully may even make it
+misbehave since CURLOPT_CUSTOMREQUEST(3) overrides the method libcurl
+would otherwise select internally.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* example.com is redirected, so we tell libcurl to follow redirection */
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3 b/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3
deleted file mode 100644
index aa2948295..000000000
--- a/docs/libcurl/opts/CURLOPT_FORBID_REUSE.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FORBID_REUSE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FORBID_REUSE \- make connection get closed at once after use
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FORBID_REUSE, long close);
-.fi
-.SH DESCRIPTION
-Pass a long. Set \fIclose\fP to 1 to make libcurl explicitly close the
-connection when done with the transfer. Normally, libcurl keeps all
-connections alive when done with one transfer in case a succeeding one follows
-that can reuse them. This option should be used with caution and only if you
-understand what it does as it can seriously impact performance.
-
-Set to 0 to have libcurl keep the connection open for possible later reuse
-(default behavior).
-.SH DEFAULT
-0
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-{
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1L);
- curl_easy_perform(curl);
-
- /* this second transfer may not reuse the same connection */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_FRESH_CONNECT (3),
-.BR CURLOPT_MAXCONNECTS (3),
-.BR CURLOPT_MAXLIFETIME_CONN (3)
diff --git a/docs/libcurl/opts/CURLOPT_FORBID_REUSE.md b/docs/libcurl/opts/CURLOPT_FORBID_REUSE.md
new file mode 100644
index 000000000..0e8a20607
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FORBID_REUSE.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FORBID_REUSE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FRESH_CONNECT (3)
+ - CURLOPT_MAXCONNECTS (3)
+ - CURLOPT_MAXLIFETIME_CONN (3)
+---
+
+# NAME
+
+CURLOPT_FORBID_REUSE - make connection get closed at once after use
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FORBID_REUSE, long close);
+~~~
+
+# DESCRIPTION
+
+Pass a long. Set *close* to 1 to make libcurl explicitly close the
+connection when done with the transfer. Normally, libcurl keeps all
+connections alive when done with one transfer in case a succeeding one follows
+that can reuse them. This option should be used with caution and only if you
+understand what it does as it can seriously impact performance.
+
+Set to 0 to have libcurl keep the connection open for possible later reuse
+(default behavior).
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1L);
+ curl_easy_perform(curl);
+
+ /* this second transfer may not reuse the same connection */
+ curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3 b/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3
deleted file mode 100644
index f9e53ab62..000000000
--- a/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FRESH_CONNECT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FRESH_CONNECT \- force a new connection to be used
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FRESH_CONNECT, long fresh);
-.fi
-.SH DESCRIPTION
-Pass a long. Set to 1 to make the next transfer use a new (fresh) connection
-by force instead of trying to reuse an existing one. This option should be
-used with caution and only if you understand what it does as it may impact
-performance negatively.
-
-Related functionality is \fICURLOPT_FORBID_REUSE(3)\fP which makes sure the
-connection is closed after use so that it cannot be reused.
-
-Set \fIfresh\fP to 0 to have libcurl attempt reusing an existing connection
-(default behavior).
-.SH DEFAULT
-0
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-{
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
- /* this transfer must use a new connection, not reuse an existing */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_FORBID_REUSE (3),
-.BR CURLOPT_MAXAGE_CONN (3),
-.BR CURLOPT_MAXLIFETIME_CONN (3)
diff --git a/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.md b/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.md
new file mode 100644
index 000000000..ccb85270d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FRESH_CONNECT.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FRESH_CONNECT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FORBID_REUSE (3)
+ - CURLOPT_MAXAGE_CONN (3)
+ - CURLOPT_MAXLIFETIME_CONN (3)
+---
+
+# NAME
+
+CURLOPT_FRESH_CONNECT - force a new connection to be used
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FRESH_CONNECT, long fresh);
+~~~
+
+# DESCRIPTION
+
+Pass a long. Set to 1 to make the next transfer use a new (fresh) connection
+by force instead of trying to reuse an existing one. This option should be
+used with caution and only if you understand what it does as it may impact
+performance negatively.
+
+Related functionality is CURLOPT_FORBID_REUSE(3) which makes sure the
+connection is closed after use so that it cannot be reused.
+
+Set *fresh* to 0 to have libcurl attempt reusing an existing connection
+(default behavior).
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L);
+ /* this transfer must use a new connection, not reuse an existing */
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_FTPPORT.3 b/docs/libcurl/opts/CURLOPT_FTPPORT.3
deleted file mode 100644
index 9dff88526..000000000
--- a/docs/libcurl/opts/CURLOPT_FTPPORT.3
+++ /dev/null
@@ -1,96 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTPPORT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTPPORT \- make FTP transfer active
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPPORT, char *spec);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter. It specifies that the
-FTP transfer should be made actively and the given string is used to get the
-IP address to use for the FTP PORT instruction.
-
-The PORT instruction tells the remote server to do a TCP connect to our
-specified IP address. The string may be a plain IP address, a host name, a
-network interface name (under Unix) or just a '-' symbol to let the library
-use your system's default IP address. Default FTP operations are passive, and
-does not use the PORT command.
-
-The address can be followed by a ':' to specify a port, optionally followed by
-a '-' to specify a port range. If the port specified is 0, the operating
-system picks a free port. If a range is provided and all ports in the range
-are not available, libcurl reports CURLE_FTP_PORT_FAILED for the
-handle. Invalid port/range settings are ignored. IPv6 addresses followed by a
-port or port range have to be in brackets. IPv6 addresses without port/range
-specifier can be in brackets.
-
-Examples with specified ports:
-
-.nf
- eth0:0
- 192.168.1.2:32000-33000
- curl.se:32123
- [::1]:1234-4567
-.fi
-
-We strongly advise against specifying the address with a name, as it causes
-libcurl to do a blocking name resolve call to retrieve the IP address. That
-name resolve operation does \fBnot\fP use DNS-over-HTTPS even if
-\fICURLOPT_DOH_URL(3)\fP is set.
-
-Using anything else than "-" for this option should typically only be done if
-you have special knowledge and confirmation that it works.
-
-You disable PORT again and go back to using the passive version by setting
-this option to NULL.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/old-server/file.txt");
- curl_easy_setopt(curl, CURLOPT_FTPPORT, "-");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Port range support was added in 7.19.5
-.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_FTP_USE_EPRT (3),
-.BR CURLOPT_FTP_USE_EPSV (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTPPORT.md b/docs/libcurl/opts/CURLOPT_FTPPORT.md
new file mode 100644
index 000000000..8e8710b07
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTPPORT.md
@@ -0,0 +1,99 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTPPORT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTP_USE_EPRT (3)
+ - CURLOPT_FTP_USE_EPSV (3)
+---
+
+# NAME
+
+CURLOPT_FTPPORT - make FTP transfer active
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPPORT, char *spec);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. It specifies that the
+FTP transfer should be made actively and the given string is used to get the
+IP address to use for the FTP PORT instruction.
+
+The PORT instruction tells the remote server to do a TCP connect to our
+specified IP address. The string may be a plain IP address, a hostname, a
+network interface name (under Unix) or just a '-' symbol to let the library
+use your system's default IP address. Default FTP operations are passive, and
+does not use the PORT command.
+
+The address can be followed by a ':' to specify a port, optionally followed by
+a '-' to specify a port range. If the port specified is 0, the operating
+system picks a free port. If a range is provided and all ports in the range
+are not available, libcurl reports CURLE_FTP_PORT_FAILED for the
+handle. Invalid port/range settings are ignored. IPv6 addresses followed by a
+port or port range have to be in brackets. IPv6 addresses without port/range
+specifier can be in brackets.
+
+Examples with specified ports:
+
+~~~c
+ eth0:0
+ 192.168.1.2:32000-33000
+ curl.se:32123
+ [::1]:1234-4567
+~~~
+
+We strongly advise against specifying the address with a name, as it causes
+libcurl to do a blocking name resolve call to retrieve the IP address. That
+name resolve operation does **not** use DNS-over-HTTPS even if
+CURLOPT_DOH_URL(3) is set.
+
+Using anything else than "-" for this option should typically only be done if
+you have special knowledge and confirmation that it works.
+
+You disable PORT again and go back to using the passive version by setting
+this option to NULL.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "ftp://example.com/old-server/file.txt");
+ curl_easy_setopt(curl, CURLOPT_FTPPORT, "-");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Port range support was added in 7.19.5
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3 b/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3
deleted file mode 100644
index 35a233840..000000000
--- a/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTPSSLAUTH 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTPSSLAUTH \- order in which to attempt TLS vs SSL
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPSSLAUTH, long order);
-.fi
-.SH DESCRIPTION
-Pass a long using one of the values from below, to alter how libcurl issues
-\&"AUTH TLS" or "AUTH SSL" when FTP over SSL is activated. This is only
-interesting if \fICURLOPT_USE_SSL(3)\fP is also set.
-
-Possible \fIorder\fP values:
-.IP CURLFTPAUTH_DEFAULT
-Allow libcurl to decide.
-.IP CURLFTPAUTH_SSL
-Try "AUTH SSL" first, and only if that fails try "AUTH TLS".
-.IP CURLFTPAUTH_TLS
-Try "AUTH TLS" first, and only if that fails try "AUTH SSL".
-.SH DEFAULT
-CURLFTPAUTH_DEFAULT
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
- curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
- /* funny server, ask for SSL before TLS */
- curl_easy_setopt(curl, CURLOPT_FTPSSLAUTH, (long)CURLFTPAUTH_SSL);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.12.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_USE_SSL (3),
-.BR CURLOPT_FTP_SSL_CCC (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md b/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md
new file mode 100644
index 000000000..a6ddf2f7a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTPSSLAUTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTP_SSL_CCC (3)
+ - CURLOPT_USE_SSL (3)
+---
+
+# NAME
+
+CURLOPT_FTPSSLAUTH - order in which to attempt TLS vs SSL
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPSSLAUTH, long order);
+~~~
+
+# DESCRIPTION
+
+Pass a long using one of the values from below, to alter how libcurl issues
+"AUTH TLS" or "AUTH SSL" when FTP over SSL is activated. This is only
+interesting if CURLOPT_USE_SSL(3) is also set.
+
+Possible *order* values:
+
+## CURLFTPAUTH_DEFAULT
+
+Allow libcurl to decide.
+
+## CURLFTPAUTH_SSL
+
+Try "AUTH SSL" first, and only if that fails try "AUTH TLS".
+
+## CURLFTPAUTH_TLS
+
+Try "AUTH TLS" first, and only if that fails try "AUTH SSL".
+
+# DEFAULT
+
+CURLFTPAUTH_DEFAULT
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
+ curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
+ /* funny server, ask for SSL before TLS */
+ curl_easy_setopt(curl, CURLOPT_FTPSSLAUTH, (long)CURLFTPAUTH_SSL);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.12.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3 b/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3
deleted file mode 100644
index 545689d6a..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_ACCOUNT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_ACCOUNT \- account info for FTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_ACCOUNT, char *account);
-.fi
-.SH DESCRIPTION
-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.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
-
- curl_easy_setopt(curl, CURLOPT_FTP_ACCOUNT, "human-resources");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.13.0
-.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_PASSWORD (3),
-.BR CURLOPT_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md b/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md
new file mode 100644
index 000000000..f8941953b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_ACCOUNT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_FTP_ACCOUNT - account info for FTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_ACCOUNT, char *account);
+~~~
+
+# DESCRIPTION
+
+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.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
+
+ curl_easy_setopt(curl, CURLOPT_FTP_ACCOUNT, "human-resources");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.13.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3 b/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3
deleted file mode 100644
index a0c684afd..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_ALTERNATIVE_TO_USER 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_ALTERNATIVE_TO_USER \- command to use instead of USER with FTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_ALTERNATIVE_TO_USER,
- char *cmd);
-.SH DESCRIPTION
-Pass a char * as parameter, pointing to a string which is used to authenticate
-if the usual FTP "USER user" and "PASS password" negotiation fails. This is
-currently only known to be required when connecting to Tumbleweed's Secure
-Transport FTPS server using client certificates for authentication.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
-
- curl_easy_setopt(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, "two users");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.5
-.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_FTP_ACCOUNT (3),
-.BR CURLOPT_FTP_SKIP_PASV_IP (3),
-.BR CURLOPT_SERVER_RESPONSE_TIMEOUT (3),
-.BR CURLOPT_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md b/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md
new file mode 100644
index 000000000..70f451d84
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_ALTERNATIVE_TO_USER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTP_ACCOUNT (3)
+ - CURLOPT_FTP_SKIP_PASV_IP (3)
+ - CURLOPT_SERVER_RESPONSE_TIMEOUT (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_FTP_ALTERNATIVE_TO_USER - command to use instead of USER with FTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_ALTERNATIVE_TO_USER,
+ char *cmd);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, pointing to a string which is used to
+authenticate if the usual FTP "USER user" and "PASS password" negotiation
+fails. This is currently only known to be required when connecting to
+Tumbleweed's Secure Transport FTPS server using client certificates for
+authentication.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, "two users");
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.5
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3 b/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3
deleted file mode 100644
index 1693eecb2..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.3
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_CREATE_MISSING_DIRS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_CREATE_MISSING_DIRS \- create missing directories for FTP and SFTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef enum {
- CURLFTP_CREATE_DIR_NONE,
- CURLFTP_CREATE_DIR,
- CURLFTP_CREATE_DIR_RETRY
-} curl_ftpcreatedir;
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_CREATE_MISSING_DIRS,
- long create);
-.SH DESCRIPTION
-Pass a long telling libcurl to \fIcreate\fP the dir. If the value is
-\fICURLFTP_CREATE_DIR\fP (1), libcurl may create any remote directory that it
-fails to "move" into.
-
-For FTP requests, that means a CWD command fails. CWD being the command that
-changes working directory.
-
-For SFTP requests, libcurl may create the remote directory if it cannot obtain
-a handle to the target-location. The creation fails if a file of the same name
-as the directory to create already exists or lack of permissions prevents
-creation.
-
-Setting \fIcreate\fP to \fICURLFTP_CREATE_DIR_RETRY\fP (2), tells libcurl to
-retry the CWD command again if the subsequent \fBMKD\fP command fails. This is
-especially useful if you are doing many simultaneous connections against the
-same server and they all have this option enabled, as then CWD may first fail
-but then another connection does \fBMKD\fP before this connection and thus
-\fBMKD\fP fails but trying CWD works!
-.SH DEFAULT
-CURLFTP_CREATE_DIR_NONE (0)
-.SH PROTOCOLS
-FTP and SFTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/non-existing/new.txt");
- curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
- (long)CURLFTP_CREATE_DIR_RETRY);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.7. SFTP support added in 7.16.3. The retry option was added in
-7.19.4.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if the
-create value is not.
-.SH "SEE ALSO"
-.BR CURLOPT_FTP_FILEMETHOD (3),
-.BR CURLOPT_FTP_USE_EPSV (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md b/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md
new file mode 100644
index 000000000..07b6f68fd
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md
@@ -0,0 +1,88 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_CREATE_MISSING_DIRS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTP_FILEMETHOD (3)
+ - CURLOPT_FTP_USE_EPSV (3)
+---
+
+# NAME
+
+CURLOPT_FTP_CREATE_MISSING_DIRS - create missing directories for FTP and SFTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+typedef enum {
+ CURLFTP_CREATE_DIR_NONE,
+ CURLFTP_CREATE_DIR,
+ CURLFTP_CREATE_DIR_RETRY
+} curl_ftpcreatedir;
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_CREATE_MISSING_DIRS,
+ long create);
+~~~
+
+# DESCRIPTION
+
+Pass a long telling libcurl to *create* the dir. If the value is
+*CURLFTP_CREATE_DIR* (1), libcurl may create any remote directory that it
+fails to "move" into.
+
+For FTP requests, that means a CWD command fails. CWD being the command that
+changes working directory.
+
+For SFTP requests, libcurl may create the remote directory if it cannot obtain
+a handle to the target-location. The creation fails if a file of the same name
+as the directory to create already exists or lack of permissions prevents
+creation.
+
+Setting *create* to *CURLFTP_CREATE_DIR_RETRY* (2), tells libcurl to
+retry the CWD command again if the subsequent **MKD** command fails. This is
+especially useful if you are doing many simultaneous connections against the
+same server and they all have this option enabled, as then CWD may first fail
+but then another connection does **MKD** before this connection and thus
+**MKD** fails but trying CWD works!
+
+# DEFAULT
+
+CURLFTP_CREATE_DIR_NONE (0)
+
+# PROTOCOLS
+
+FTP and SFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "ftp://example.com/non-existing/new.txt");
+ curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
+ (long)CURLFTP_CREATE_DIR_RETRY);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.7. SFTP support added in 7.16.3. The retry option was added in
+7.19.4.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if the
+create value is not.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3 b/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3
deleted file mode 100644
index 14f0842f7..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_FILEMETHOD 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_FILEMETHOD \- select directory traversing method for FTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_FILEMETHOD,
- long method);
-.SH DESCRIPTION
-Pass a long telling libcurl which \fImethod\fP to use to reach a file on a
-FTP(S) server.
-
-This option exists because some server implementations are not compliant to
-what the standards say should work.
-
-The argument should be one of the following alternatives:
-.IP CURLFTPMETHOD_MULTICWD
-libcurl does a single CWD operation for each path part in the given URL. For
-deep hierarchies this means many commands. This is how RFC 1738 says it should
-be done. This is the default but the slowest behavior.
-.IP CURLFTPMETHOD_NOCWD
-libcurl makes no CWD at all. libcurl does SIZE, RETR, STOR etc and gives a
-full path to the server for all these commands. This is the fastest behavior
-since it skips having to change directories.
-.IP CURLFTPMETHOD_SINGLECWD
-libcurl does one CWD with the full target directory and then operates on the
-file \&"normally" (like in the multicwd case). This is somewhat more standards
-compliant than 'nocwd' but without the full penalty of 'multicwd'.
-.SH DEFAULT
-CURLFTPMETHOD_MULTICWD
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/1/2/3/4/new.txt");
- curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD,
- (long)CURLFTPMETHOD_SINGLECWD);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DIRLISTONLY (3),
-.BR CURLOPT_FTP_SKIP_PASV_IP (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md b/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md
new file mode 100644
index 000000000..34b55d659
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md
@@ -0,0 +1,86 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_FILEMETHOD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DIRLISTONLY (3)
+ - CURLOPT_FTP_SKIP_PASV_IP (3)
+---
+
+# NAME
+
+CURLOPT_FTP_FILEMETHOD - select directory traversing method for FTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_FILEMETHOD,
+ long method);
+~~~
+
+# DESCRIPTION
+
+Pass a long telling libcurl which *method* to use to reach a file on a
+FTP(S) server.
+
+This option exists because some server implementations are not compliant to
+what the standards say should work.
+
+The argument should be one of the following alternatives:
+
+## CURLFTPMETHOD_MULTICWD
+
+libcurl does a single CWD operation for each path part in the given URL. For
+deep hierarchies this means many commands. This is how RFC 1738 says it should
+be done. This is the default but the slowest behavior.
+
+## CURLFTPMETHOD_NOCWD
+
+libcurl makes no CWD at all. libcurl does SIZE, RETR, STOR etc and gives a
+full path to the server for all these commands. This is the fastest behavior
+since it skips having to change directories.
+
+## CURLFTPMETHOD_SINGLECWD
+
+libcurl does one CWD with the full target directory and then operates on the
+file &"normally" (like in the multicwd case). This is somewhat more standards
+compliant than 'nocwd' but without the full penalty of 'multicwd'.
+
+# DEFAULT
+
+CURLFTPMETHOD_MULTICWD
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/1/2/3/4/new.txt");
+ curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD,
+ (long)CURLFTPMETHOD_SINGLECWD);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3 b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
deleted file mode 100644
index 829b39b12..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_SKIP_PASV_IP 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_SKIP_PASV_IP \- ignore the IP address in the PASV response
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SKIP_PASV_IP, long skip);
-.fi
-.SH DESCRIPTION
-Pass a long. If \fIskip\fP is set to 1, it instructs libcurl to not use the IP
-address the server suggests in its 227-response to libcurl's PASV command when
-libcurl connects the data connection. Instead libcurl reuses the same IP
-address it already uses for the control connection. It still uses the port
-number from the 227-response.
-
-This option allows libcurl to work around broken server installations or funny
-network setups that due to NATs, firewalls or incompetence report the wrong IP
-address. Setting this option also reduces the risk for various sorts of client
-abuse by malicious servers.
-
-This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
-.SH DEFAULT
-1 since 7.74.0, was 0 before then.
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
-
- /* please ignore the IP in the PASV response */
- curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, 1L);
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.14.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FTPPORT (3),
-.BR CURLOPT_FTP_USE_EPRT (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md
new file mode 100644
index 000000000..bea622ac7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_SKIP_PASV_IP
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTPPORT (3)
+ - CURLOPT_FTP_USE_EPRT (3)
+---
+
+# NAME
+
+CURLOPT_FTP_SKIP_PASV_IP - ignore the IP address in the PASV response
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SKIP_PASV_IP, long skip);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If *skip* is set to 1, it instructs libcurl to not use the IP
+address the server suggests in its 227-response to libcurl's PASV command when
+libcurl connects the data connection. Instead libcurl reuses the same IP
+address it already uses for the control connection. It still uses the port
+number from the 227-response.
+
+This option allows libcurl to work around broken server installations or funny
+network setups that due to NATs, firewalls or incompetence report the wrong IP
+address. Setting this option also reduces the risk for various sorts of client
+abuse by malicious servers.
+
+This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
+
+# DEFAULT
+
+1 since 7.74.0, was 0 before then.
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
+
+ /* please ignore the IP in the PASV response */
+ curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, 1L);
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.14.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3 b/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3
deleted file mode 100644
index c47b89842..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_SSL_CCC 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_SSL_CCC \- switch off SSL again with FTP after auth
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SSL_CCC,
- long how);
-.fi
-.SH DESCRIPTION
-If enabled, this option makes libcurl use CCC (Clear Command Channel). It
-shuts down the SSL/TLS layer after authenticating. The rest of the control
-channel communication remains unencrypted. This allows NAT routers to follow
-the FTP transaction. Pass a long using one of the values below
-.IP CURLFTPSSL_CCC_NONE
-do not attempt to use CCC.
-.IP CURLFTPSSL_CCC_PASSIVE
-Do not initiate the shutdown, but wait for the server to do it. Do not send a
-reply.
-.IP CURLFTPSSL_CCC_ACTIVE
-Initiate the shutdown and wait for a reply.
-.SH DEFAULT
-CURLFTPSSL_CCC_NONE
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
- curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
- /* go back to clear-text FTP after authenticating */
- curl_easy_setopt(curl, CURLOPT_FTP_SSL_CCC, (long)CURLFTPSSL_CCC_ACTIVE);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FTPSSLAUTH (3),
-.BR CURLOPT_PROTOCOLS_STR (3),
-.BR CURLOPT_USE_SSL (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md b/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md
new file mode 100644
index 000000000..71947c36e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_SSL_CCC
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTPSSLAUTH (3)
+ - CURLOPT_PROTOCOLS_STR (3)
+ - CURLOPT_USE_SSL (3)
+---
+
+# NAME
+
+CURLOPT_FTP_SSL_CCC - switch off SSL again with FTP after auth
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_SSL_CCC,
+ long how);
+~~~
+
+# DESCRIPTION
+
+If enabled, this option makes libcurl use CCC (Clear Command Channel). It
+shuts down the SSL/TLS layer after authenticating. The rest of the control
+channel communication remains unencrypted. This allows NAT routers to follow
+the FTP transaction. Pass a long using one of the values below
+
+## CURLFTPSSL_CCC_NONE
+
+do not attempt to use CCC.
+
+## CURLFTPSSL_CCC_PASSIVE
+
+Do not initiate the shutdown, but wait for the server to do it. Do not send a
+reply.
+
+## CURLFTPSSL_CCC_ACTIVE
+
+Initiate the shutdown and wait for a reply.
+
+# DEFAULT
+
+CURLFTPSSL_CCC_NONE
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
+ curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
+ /* go back to clear-text FTP after authenticating */
+ curl_easy_setopt(curl, CURLOPT_FTP_SSL_CCC, (long)CURLFTPSSL_CCC_ACTIVE);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3 b/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3
deleted file mode 100644
index 9753043db..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_USE_EPRT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_USE_EPRT \- use EPRT for FTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPRT, long enabled);
-.fi
-.SH DESCRIPTION
-Pass a long. If the value is 1, it tells curl to use the EPRT command when
-doing active FTP downloads (which is enabled by
-\fICURLOPT_FTPPORT(3)\fP). Using EPRT means that libcurl first attempts to use
-EPRT before using PORT, but if you pass zero to this option, it avoids using
-EPRT, only plain PORT.
-
-The EPRT command is a slightly newer addition to the FTP protocol than PORT
-and is the preferred command to use since it enables IPv6 to be used. Very old
-FTP servers might not support it, which is why libcurl has a fallback
-mechanism. Sometimes that fallback is not enough and then this option might
-come handy.
-
-If the server is an IPv6 host, this option has no effect as EPRT is necessary
-then.
-.SH DEFAULT
-.SH PROTOCOLS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
-
- /* contact us back, aka "active" FTP */
- curl_easy_setopt(curl, CURLOPT_FTPPORT, "-");
-
- /* FTP the way the neanderthals did it */
- curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.5
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_FTP_USE_EPSV (3),
-.BR CURLOPT_FTPPORT (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md b/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md
new file mode 100644
index 000000000..644f51aa9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_USE_EPRT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTPPORT (3)
+ - CURLOPT_FTP_USE_EPSV (3)
+---
+
+# NAME
+
+CURLOPT_FTP_USE_EPRT - use EPRT for FTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPRT, long enabled);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If the value is 1, it tells curl to use the EPRT command when
+doing active FTP downloads (which is enabled by
+CURLOPT_FTPPORT(3)). Using EPRT means that libcurl first attempts to use
+EPRT before using PORT, but if you pass zero to this option, it avoids using
+EPRT, only plain PORT.
+
+The EPRT command is a slightly newer addition to the FTP protocol than PORT
+and is the preferred command to use since it enables IPv6 to be used. Old FTP
+servers might not support it, which is why libcurl has a fallback mechanism.
+Sometimes that fallback is not enough and then this option might come handy.
+
+If the server is an IPv6 host, this option has no effect as EPRT is necessary
+then.
+
+# DEFAULT
+
+# PROTOCOLS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
+
+ /* contact us back, aka "active" FTP */
+ curl_easy_setopt(curl, CURLOPT_FTPPORT, "-");
+
+ /* FTP the way the neanderthals did it */
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.5
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3 b/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3
deleted file mode 100644
index 8c49874a2..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_USE_EPSV 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_USE_EPSV \- use EPSV for FTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPSV, long epsv);
-.fi
-.SH DESCRIPTION
-Pass \fIepsv\fP as a long. If the value is 1, it tells curl to use the EPSV
-command when doing passive FTP downloads (which it does by default). Using
-EPSV means that libcurl first attempts to use the EPSV command before using
-PASV. If you pass zero to this option, it does not use EPSV, only plain PASV.
-
-The EPSV command is a slightly newer addition to the FTP protocol than PASV
-and is the preferred command to use since it enables IPv6 to be used. Very old
-FTP servers might not support it, which is why libcurl has a fallback
-mechanism. Sometimes that fallback is not enough and then this option might
-come handy.
-
-If the server is an IPv6 host, this option has no effect.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/old-server/file.txt");
-
- /* let's shut off this modern feature */
- curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with FTP
-.SH RETURN VALUE
-Returns CURLE_OK if FTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FTP_USE_EPRT (3),
-.BR CURLOPT_FTPPORT (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md b/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md
new file mode 100644
index 000000000..985ca8ba3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_USE_EPSV
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTPPORT (3)
+ - CURLOPT_FTP_USE_EPRT (3)
+---
+
+# NAME
+
+CURLOPT_FTP_USE_EPSV - use EPSV for FTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_EPSV, long epsv);
+~~~
+
+# DESCRIPTION
+
+Pass *epsv* as a long. If the value is 1, it tells curl to use the EPSV
+command when doing passive FTP downloads (which it does by default). Using
+EPSV means that libcurl first attempts to use the EPSV command before using
+PASV. If you pass zero to this option, it does not use EPSV, only plain PASV.
+
+The EPSV command is a slightly newer addition to the FTP protocol than PASV
+and is the preferred command to use since it enables IPv6 to be used. Old FTP
+servers might not support it, which is why libcurl has a fallback mechanism.
+Sometimes that fallback is not enough and then this option might come handy.
+
+If the server is an IPv6 host, this option has no effect.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "ftp://example.com/old-server/file.txt");
+
+ /* let's shut off this modern feature */
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with FTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if FTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3 b/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3
deleted file mode 100644
index 634250754..000000000
--- a/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_FTP_USE_PRET 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_FTP_USE_PRET \- use PRET for FTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_PRET, long enable);
-.fi
-.SH DESCRIPTION
-Pass a long. If the value is 1, it tells curl to send a PRET command before
-PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard
-command for directory listings as well as up and downloads in PASV mode. Has
-no effect when using the active FTP transfers mode.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/old-server/file.txt");
-
- /* a drftpd server, do it! */
- curl_easy_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FTP_USE_EPRT (3),
-.BR CURLOPT_FTP_USE_EPSV (3)
diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md b/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md
new file mode 100644
index 000000000..f81ca4cf0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_FTP_USE_PRET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTP_USE_EPRT (3)
+ - CURLOPT_FTP_USE_EPSV (3)
+---
+
+# NAME
+
+CURLOPT_FTP_USE_PRET - use PRET for FTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_USE_PRET, long enable);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If the value is 1, it tells curl to send a PRET command before
+PASV (and EPSV). Certain FTP servers, mainly drftpd, require this non-standard
+command for directory listings as well as up and downloads in PASV mode. Has
+no effect when using the active FTP transfers mode.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "ftp://example.com/old-server/file.txt");
+
+ /* a drftpd server, do it! */
+ curl_easy_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3 b/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3
deleted file mode 100644
index 055e316c8..000000000
--- a/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_GSSAPI_DELEGATION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_GSSAPI_DELEGATION \- allowed GSS-API delegation
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_GSSAPI_DELEGATION, long level);
-.fi
-.SH DESCRIPTION
-Set the long parameter \fIlevel\fP to \fBCURLGSSAPI_DELEGATION_FLAG\fP to
-allow unconditional GSSAPI credential delegation. The delegation is disabled
-by default since 7.21.7. Set the parameter to
-\fBCURLGSSAPI_DELEGATION_POLICY_FLAG\fP to delegate only if the OK-AS-DELEGATE
-flag is set in the service ticket in case this feature is supported by the
-GSS-API implementation and the definition of \fIGSS_C_DELEG_POLICY_FLAG\fP was
-available at compile-time.
-.SH DEFAULT
-CURLGSSAPI_DELEGATION_NONE
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* delegate if okayed by policy */
- curl_easy_setopt(curl, CURLOPT_GSSAPI_DELEGATION,
- (long)CURLGSSAPI_DELEGATION_POLICY_FLAG);
- ret = curl_easy_perform(curl);
-}
-.fi
-
-.SH AVAILABILITY
-Added in 7.22.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPAUTH (3),
-.BR CURLOPT_PROXYAUTH (3)
diff --git a/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md b/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md
new file mode 100644
index 000000000..01c1d5062
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_GSSAPI_DELEGATION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPAUTH (3)
+ - CURLOPT_PROXYAUTH (3)
+---
+
+# NAME
+
+CURLOPT_GSSAPI_DELEGATION - allowed GSS-API delegation
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_GSSAPI_DELEGATION, long level);
+~~~
+
+# DESCRIPTION
+
+Set the long parameter *level* to **CURLGSSAPI_DELEGATION_FLAG** to allow
+unconditional GSSAPI credential delegation. The delegation is disabled by
+default since 7.21.7. Set the parameter to
+**CURLGSSAPI_DELEGATION_POLICY_FLAG** to delegate only if the OK-AS-DELEGATE
+flag is set in the service ticket in case this feature is supported by the
+GSS-API implementation and the definition of *GSS_C_DELEG_POLICY_FLAG* was
+available at compile-time.
+
+# DEFAULT
+
+CURLGSSAPI_DELEGATION_NONE
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* delegate if okayed by policy */
+ curl_easy_setopt(curl, CURLOPT_GSSAPI_DELEGATION,
+ (long)CURLGSSAPI_DELEGATION_POLICY_FLAG);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.22.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3
deleted file mode 100644
index 2057fbe5c..000000000
--- a/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 3 "1 Feb 2018" libcurl libcurl
-.SH NAME
-CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS \- head start for IPv6 for happy eyeballs
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
- long timeout);
-.fi
-.SH DESCRIPTION
-Happy eyeballs is an algorithm that attempts to connect to both IPv4 and IPv6
-addresses for dual-stack hosts, preferring IPv6 first for \fItimeout\fP
-milliseconds. If the IPv6 address cannot be connected to within that time then
-a connection attempt is made to the IPv4 address in parallel. The first
-connection to be established is the one that is used.
-
-The range of suggested useful values for \fItimeout\fP is limited. Happy
-Eyeballs RFC 6555 says "It is RECOMMENDED that connection attempts be paced
-150-250 ms apart to balance human factors against network load." libcurl
-currently defaults to 200 ms. Firefox and Chrome currently default to 300 ms.
-.SH DEFAULT
-CURL_HET_DEFAULT (currently defined as 200L)
-.SH PROTOCOLS
-All except FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, 300L);
-
- curl_easy_perform(curl);
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.59.0
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH SEE ALSO
-.BR CURLOPT_CONNECTTIMEOUT_MS "(3), "
-.BR CURLOPT_TIMEOUT "(3), " CURLOPT_LOW_SPEED_LIMIT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md b/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md
new file mode 100644
index 000000000..23299c736
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT_MS (3)
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS - head start for IPv6 for happy eyeballs
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
+ long timeout);
+~~~
+
+# DESCRIPTION
+
+Happy eyeballs is an algorithm that attempts to connect to both IPv4 and IPv6
+addresses for dual-stack hosts, preferring IPv6 first for *timeout*
+milliseconds. If the IPv6 address cannot be connected to within that time then
+a connection attempt is made to the IPv4 address in parallel. The first
+connection to be established is the one that is used.
+
+The range of suggested useful values for *timeout* is limited. Happy
+Eyeballs RFC 6555 says "It is RECOMMENDED that connection attempts be paced
+150-250 ms apart to balance human factors against network load." libcurl
+currently defaults to 200 ms. Firefox and Chrome currently default to 300 ms.
+
+# DEFAULT
+
+CURL_HET_DEFAULT (currently defined as 200L)
+
+# PROTOCOLS
+
+All except FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, 300L);
+
+ curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.59.0
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3 b/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3
deleted file mode 100644
index dab0a1f09..000000000
--- a/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HAPROXYPROTOCOL 3 "5 Feb 2018" libcurl libcurl
-.SH NAME
-CURLOPT_HAPROXYPROTOCOL \- send HAProxy PROXY protocol v1 header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPROXYPROTOCOL,
- long haproxy_protocol);
-.fi
-.SH DESCRIPTION
-A long parameter set to 1 tells the library to send an HAProxy PROXY
-protocol v1 header at beginning of the connection. The default action is not to
-send this header.
-
-This option is primarily useful when sending test requests to a service that
-expects this header.
-
-Most applications do not need this option.
-.SH DEFAULT
-0, do not send any HAProxy PROXY protocol header
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP. Added in 7.60.0.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
-.SH SEE ALSO
-.BR CURLOPT_PROXY "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md b/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md
new file mode 100644
index 000000000..51eb2656c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HAPROXYPROTOCOL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+---
+
+# NAME
+
+CURLOPT_HAPROXYPROTOCOL - send HAProxy PROXY protocol v1 header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPROXYPROTOCOL,
+ long haproxy_protocol);
+~~~
+
+# DESCRIPTION
+
+A long parameter set to 1 tells the library to send an HAProxy PROXY
+protocol v1 header at beginning of the connection. The default action is not to
+send this header.
+
+This option is primarily useful when sending test requests to a service that
+expects this header.
+
+Most applications do not need this option.
+
+# DEFAULT
+
+0, do not send any HAProxy PROXY protocol header
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP. Added in 7.60.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.3 b/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.3
deleted file mode 100644
index 04d8621f5..000000000
--- a/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HAPROXY_CLIENT_IP 3 "8 May 2023" libcurl libcurl
-.SH NAME
-CURLOPT_HAPROXY_CLIENT_IP \- set HAProxy PROXY protocol client IP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPROXY_CLIENT_IP,
- char *client_ip);
-.fi
-.SH DESCRIPTION
-When this parameter is set to a valid IPv4 or IPv6 numerical address, the
-library sends this address as client address in the HAProxy PROXY protocol v1
-header at beginning of the connection.
-
-This option is an alternative to \fICURLOPT_HAPROXYPROTOCOL(3)\fP as that one
-cannot use a specified address.
-.SH DEFAULT
-NULL, no HAProxy header is sent
-.SH PROTOCOLS
-HTTP, HAProxy PROTOCOL
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_HAPROXY_CLIENT_IP, "1.1.1.1");
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP. Added in 8.2.0.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
-.SH SEE ALSO
-.BR CURLOPT_PROXY "(3), "
-.BR CURLOPT_HAPROXYPROTOCOL "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md b/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md
new file mode 100644
index 000000000..ac0da3a1c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HAPROXY_CLIENT_IP
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HAPROXYPROTOCOL (3)
+ - CURLOPT_PROXY (3)
+---
+
+# NAME
+
+CURLOPT_HAPROXY_CLIENT_IP - set HAProxy PROXY protocol client IP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HAPROXY_CLIENT_IP,
+ char *client_ip);
+~~~
+
+# DESCRIPTION
+
+When this parameter is set to a valid IPv4 or IPv6 numerical address, the
+library sends this address as client address in the HAProxy PROXY protocol v1
+header at beginning of the connection.
+
+This option is an alternative to CURLOPT_HAPROXYPROTOCOL(3) as that one
+cannot use a specified address.
+
+# DEFAULT
+
+NULL, no HAProxy header is sent
+
+# PROTOCOLS
+
+HTTP, HAProxy PROTOCOL
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HAPROXY_CLIENT_IP, "1.1.1.1");
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP. Added in 8.2.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HEADER.3 b/docs/libcurl/opts/CURLOPT_HEADER.3
deleted file mode 100644
index 7decc88aa..000000000
--- a/docs/libcurl/opts/CURLOPT_HEADER.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HEADER 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HEADER \- pass headers to the data stream
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADER, long onoff);
-.fi
-.SH DESCRIPTION
-Pass the long value \fIonoff\fP set to 1 to ask libcurl to include the headers
-in the write callback (\fICURLOPT_WRITEFUNCTION(3)\fP). This option is
-relevant for protocols that actually have headers or other meta-data (like
-HTTP and FTP).
-
-When asking to get the headers passed to the same callback as the body, it is
-not possible to accurately separate them again without detailed knowledge
-about the protocol in use.
-
-Further: the \fICURLOPT_WRITEFUNCTION(3)\fP callback is limited to only ever
-get a maximum of \fICURL_MAX_WRITE_SIZE\fP bytes passed to it (16KB), while a
-header can be longer and the \fICURLOPT_HEADERFUNCTION(3)\fP supports getting
-called with headers up to \fICURL_MAX_HTTP_HEADER\fP bytes big (100KB).
-
-It is often better to use \fICURLOPT_HEADERFUNCTION(3)\fP to get the header
-data separately.
-
-While named confusingly similar, \fICURLOPT_HTTPHEADER(3)\fP is used to set
-custom HTTP headers!
-.SH DEFAULT
-0
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Provided in all libcurl versions.
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_HEADERFUNCTION (3),
-.BR CURLOPT_HTTPHEADER (3)
diff --git a/docs/libcurl/opts/CURLOPT_HEADER.md b/docs/libcurl/opts/CURLOPT_HEADER.md
new file mode 100644
index 000000000..d5e272ac5
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HEADER.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HEADER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERFUNCTION (3)
+ - CURLOPT_HTTPHEADER (3)
+---
+
+# NAME
+
+CURLOPT_HEADER - pass headers to the data stream
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADER, long onoff);
+~~~
+
+# DESCRIPTION
+
+Pass the long value *onoff* set to 1 to ask libcurl to include the headers
+in the write callback (CURLOPT_WRITEFUNCTION(3)). This option is
+relevant for protocols that actually have headers or other meta-data (like
+HTTP and FTP).
+
+When asking to get the headers passed to the same callback as the body, it is
+not possible to accurately separate them again without detailed knowledge
+about the protocol in use.
+
+Further: the CURLOPT_WRITEFUNCTION(3) callback is limited to only ever
+get a maximum of *CURL_MAX_WRITE_SIZE* bytes passed to it (16KB), while a
+header can be longer and the CURLOPT_HEADERFUNCTION(3) supports getting
+called with headers up to *CURL_MAX_HTTP_HEADER* bytes big (100KB).
+
+It is often better to use CURLOPT_HEADERFUNCTION(3) to get the header
+data separately.
+
+While named confusingly similar, CURLOPT_HTTPHEADER(3) is used to set
+custom HTTP headers!
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Provided in all libcurl versions.
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_HEADERDATA.3 b/docs/libcurl/opts/CURLOPT_HEADERDATA.3
deleted file mode 100644
index e040a6998..000000000
--- a/docs/libcurl/opts/CURLOPT_HEADERDATA.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HEADERDATA 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HEADERDATA \- pointer to pass to header callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP to be used to write the header part of the received data
-to.
-
-If \fICURLOPT_WRITEFUNCTION(3)\fP or \fICURLOPT_HEADERFUNCTION(3)\fP is used,
-\fIpointer\fP is passed in to the respective callback.
-
-If neither of those options are set, \fIpointer\fP must be a valid FILE * and
-it is used by a plain fwrite() to write headers to.
-
-If you are using libcurl as a win32 DLL, you \fBMUST\fP use a
-\fICURLOPT_WRITEFUNCTION(3)\fP or \fICURLOPT_HEADERFUNCTION(3)\fP if you set
-this option or you might experience crashes.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-struct my_info {
- int shoesize;
- char *secret;
-};
-
-static size_t header_callback(char *buffer, size_t size,
- size_t nitems, void *userdata)
-{
- struct my_info *i = (struct my_info *)userdata;
-
- /* now this callback can access the my_info struct */
-
- return nitems * size;
-}
-
-CURL *curl = curl_easy_init();
-if(curl) {
- struct my_info my = { 10, "the cookies are in the cupboard" };
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
-
- /* pass in custom data to the callback */
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, &my);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR curl_easy_header (3),
-.BR CURLOPT_HEADERFUNCTION (3),
-.BR CURLOPT_WRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HEADERDATA.md b/docs/libcurl/opts/CURLOPT_HEADERDATA.md
new file mode 100644
index 000000000..7f056361f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HEADERDATA.md
@@ -0,0 +1,89 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HEADERDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERFUNCTION (3)
+ - CURLOPT_WRITEFUNCTION (3)
+ - curl_easy_header (3)
+---
+
+# NAME
+
+CURLOPT_HEADERDATA - pointer to pass to header callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* to be used to write the header part of the received data
+to.
+
+If CURLOPT_WRITEFUNCTION(3) or CURLOPT_HEADERFUNCTION(3) is used,
+*pointer* is passed in to the respective callback.
+
+If neither of those options are set, *pointer* must be a valid FILE * and
+it is used by a plain fwrite() to write headers to.
+
+If you are using libcurl as a win32 DLL, you **MUST** use a
+CURLOPT_WRITEFUNCTION(3) or CURLOPT_HEADERFUNCTION(3) if you set
+this option or you might experience crashes.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct my_info {
+ int shoesize;
+ char *secret;
+};
+
+static size_t header_callback(char *buffer, size_t size,
+ size_t nitems, void *userdata)
+{
+ struct my_info *i = userdata;
+ printf("shoe size: %d\n", i->shoesize);
+ /* now this callback can access the my_info struct */
+
+ return nitems * size;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct my_info my = { 10, "the cookies are in the cupboard" };
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
+
+ /* pass in custom data to the callback */
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, &my);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3
deleted file mode 100644
index 0b5ac28c1..000000000
--- a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.3
+++ /dev/null
@@ -1,129 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HEADERFUNCTION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HEADERFUNCTION \- callback that receives header data
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-size_t header_callback(char *buffer,
- size_t size,
- size_t nitems,
- void *userdata);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERFUNCTION,
- header_callback);
-.fi
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets invoked by libcurl as soon as it has received
-header data. The header callback is called once for each header and only
-complete header lines are passed on to the callback. Parsing headers is easy
-to do using this callback. \fIbuffer\fP points to the delivered data, and the
-size of that data is \fInitems\fP; \fIsize\fP is always 1. The provide header
-line is not null-terminated!
-
-The pointer named \fIuserdata\fP is the one you set with the
-\fICURLOPT_HEADERDATA(3)\fP option.
-
-Your callback should return the number of bytes actually taken care of. If
-that amount differs from the amount passed to your callback function, it
-signals an error condition to the library. This causes the transfer to get
-aborted and the libcurl function used returns \fICURLE_WRITE_ERROR\fP.
-
-You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
-
-A complete HTTP header that is passed to this function can be up to
-\fICURL_MAX_HTTP_HEADER\fP (100K) bytes and includes the final line terminator.
-
-If this option is not set, or if it is set to NULL, but
-\fICURLOPT_HEADERDATA(3)\fP is set to anything but NULL, the function used to
-accept response data is used instead. That is the function specified with
-\fICURLOPT_WRITEFUNCTION(3)\fP, or if it is not specified or NULL - the
-default, stream-writing function.
-
-It's important to note that the callback is invoked for the headers of all
-responses received after initiating a request and not just the final
-response. This includes all responses which occur during authentication
-negotiation. If you need to operate on only the headers from the final
-response, you need to collect headers in the callback yourself and use HTTP
-status lines, for example, to delimit response boundaries.
-
-For an HTTP transfer, the status line and the blank line preceding the response
-body are both included as headers and passed to this function.
-
-When a server sends a chunked encoded transfer, it may contain a trailer. That
-trailer is identical to an HTTP header and if such a trailer is received it is
-passed to the application using this callback as well. There are several ways
-to detect it being a trailer and not an ordinary header: 1) it comes after the
-response-body. 2) it comes after the final header line (CR LF) 3) a Trailer:
-header among the regular response-headers mention what header(s) to expect in
-the trailer.
-
-For non-HTTP protocols like FTP, POP3, IMAP and SMTP this function gets called
-with the server responses to the commands that libcurl sends.
-
-A more convenient way to get HTTP headers might be to use
-\fIcurl_easy_header(3)\fP.
-.SH LIMITATIONS
-libcurl does not unfold HTTP "folded headers" (deprecated since RFC 7230). A
-folded header is a header that continues on a subsequent line and starts with
-a whitespace. Such folds are passed to the header callback as separate ones,
-although strictly they are just continuations of the previous lines.
-.SH DEFAULT
-Nothing.
-.SH PROTOCOLS
-Used for all protocols with headers or meta-data concept: HTTP, FTP, POP3,
-IMAP, SMTP and more.
-.SH EXAMPLE
-.nf
-static size_t header_callback(char *buffer, size_t size,
- size_t nitems, void *userdata)
-{
- /* received header is nitems * size long in 'buffer' NOT ZERO TERMINATED */
- /* 'userdata' is set with CURLOPT_HEADERDATA */
- return nitems * size;
-}
-
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR curl_easy_header (3),
-.BR CURLOPT_HEADERDATA (3),
-.BR CURLOPT_WRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md
new file mode 100644
index 000000000..eb14cdd6f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md
@@ -0,0 +1,132 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HEADERFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERDATA (3)
+ - CURLOPT_WRITEFUNCTION (3)
+ - curl_easy_header (3)
+---
+
+# NAME
+
+CURLOPT_HEADERFUNCTION - callback that receives header data
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+size_t header_callback(char *buffer,
+ size_t size,
+ size_t nitems,
+ void *userdata);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADERFUNCTION,
+ header_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets invoked by libcurl as soon as it has received
+header data. The header callback is called once for each header and only
+complete header lines are passed on to the callback. Parsing headers is easy
+to do using this callback. *buffer* points to the delivered data, and the
+size of that data is *nitems*; *size* is always 1. The provide header
+line is not null-terminated!
+
+The pointer named *userdata* is the one you set with the
+CURLOPT_HEADERDATA(3) option.
+
+Your callback should return the number of bytes actually taken care of. If
+that amount differs from the amount passed to your callback function, it
+signals an error condition to the library. This causes the transfer to get
+aborted and the libcurl function used returns *CURLE_WRITE_ERROR*.
+
+You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
+
+A complete HTTP header that is passed to this function can be up to
+*CURL_MAX_HTTP_HEADER* (100K) bytes and includes the final line terminator.
+
+If this option is not set, or if it is set to NULL, but
+CURLOPT_HEADERDATA(3) is set to anything but NULL, the function used to
+accept response data is used instead. That is the function specified with
+CURLOPT_WRITEFUNCTION(3), or if it is not specified or NULL - the
+default, stream-writing function.
+
+It is important to note that the callback is invoked for the headers of all
+responses received after initiating a request and not just the final
+response. This includes all responses which occur during authentication
+negotiation. If you need to operate on only the headers from the final
+response, you need to collect headers in the callback yourself and use HTTP
+status lines, for example, to delimit response boundaries.
+
+For an HTTP transfer, the status line and the blank line preceding the response
+body are both included as headers and passed to this function.
+
+When a server sends a chunked encoded transfer, it may contain a trailer. That
+trailer is identical to an HTTP header and if such a trailer is received it is
+passed to the application using this callback as well. There are several ways
+to detect it being a trailer and not an ordinary header: 1) it comes after the
+response-body. 2) it comes after the final header line (CR LF) 3) a Trailer:
+header among the regular response-headers mention what header(s) to expect in
+the trailer.
+
+For non-HTTP protocols like FTP, POP3, IMAP and SMTP this function gets called
+with the server responses to the commands that libcurl sends.
+
+A more convenient way to get HTTP headers might be to use
+curl_easy_header(3).
+
+# LIMITATIONS
+
+libcurl does not unfold HTTP "folded headers" (deprecated since RFC 7230). A
+folded header is a header that continues on a subsequent line and starts with
+a whitespace. Such folds are passed to the header callback as separate ones,
+although strictly they are just continuations of the previous lines.
+
+# DEFAULT
+
+Nothing.
+
+# PROTOCOLS
+
+Used for all protocols with headers or meta-data concept: HTTP, FTP, POP3,
+IMAP, SMTP and more.
+
+# EXAMPLE
+
+~~~c
+static size_t header_callback(char *buffer, size_t size,
+ size_t nitems, void *userdata)
+{
+ /* received header is nitems * size long in 'buffer' NOT ZERO TERMINATED */
+ /* 'userdata' is set with CURLOPT_HEADERDATA */
+ return nitems * size;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_HEADEROPT.3 b/docs/libcurl/opts/CURLOPT_HEADEROPT.3
deleted file mode 100644
index 085938f60..000000000
--- a/docs/libcurl/opts/CURLOPT_HEADEROPT.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HEADEROPT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HEADEROPT \- send HTTP headers to both proxy and host or separately
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADEROPT, long bitmask);
-.fi
-.SH DESCRIPTION
-Pass a long that is a bitmask of options of how to deal with headers. The two
-mutually exclusive options are:
-
-\fBCURLHEADER_UNIFIED\fP - the headers specified in
-\fICURLOPT_HTTPHEADER(3)\fP are used in requests both to servers and
-proxies. With this option enabled, \fICURLOPT_PROXYHEADER(3)\fP does not have
-any effect.
-
-\fBCURLHEADER_SEPARATE\fP - makes \fICURLOPT_HTTPHEADER(3)\fP headers only get
-sent to a server and not to a proxy. Proxy headers must be set with
-\fICURLOPT_PROXYHEADER(3)\fP to get used. Note that if a non-CONNECT request
-is sent to a proxy, libcurl sends both server headers and proxy headers. When
-doing CONNECT, libcurl sends \fICURLOPT_PROXYHEADER(3)\fP headers only to the
-proxy and then \fICURLOPT_HTTPHEADER(3)\fP headers only to the server.
-.SH DEFAULT
-CURLHEADER_SEPARATE (changed in 7.42.1, used CURLHEADER_UNIFIED before then)
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- struct curl_slist *list;
- list = curl_slist_append(NULL, "Shoesize: 10");
- list = curl_slist_append(list, "Accept:");
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
-
- /* HTTPS over a proxy makes a separate CONNECT to the proxy, so tell
- libcurl to not send the custom headers to the proxy. Keep them
- separate! */
- curl_easy_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
- ret = curl_easy_perform(curl);
- curl_slist_free_all(list);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.37.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPHEADER (3),
-.BR CURLOPT_PROXYHEADER (3)
diff --git a/docs/libcurl/opts/CURLOPT_HEADEROPT.md b/docs/libcurl/opts/CURLOPT_HEADEROPT.md
new file mode 100644
index 000000000..bb3bcf41c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HEADEROPT.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HEADEROPT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPHEADER (3)
+ - CURLOPT_PROXYHEADER (3)
+---
+
+# NAME
+
+CURLOPT_HEADEROPT - send HTTP headers to both proxy and host or separately
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HEADEROPT, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long that is a bitmask of options of how to deal with headers. The two
+mutually exclusive options are:
+
+**CURLHEADER_UNIFIED** - the headers specified in
+CURLOPT_HTTPHEADER(3) are used in requests both to servers and
+proxies. With this option enabled, CURLOPT_PROXYHEADER(3) does not have
+any effect.
+
+**CURLHEADER_SEPARATE** - makes CURLOPT_HTTPHEADER(3) headers only get
+sent to a server and not to a proxy. Proxy headers must be set with
+CURLOPT_PROXYHEADER(3) to get used. Note that if a non-CONNECT request
+is sent to a proxy, libcurl sends both server headers and proxy headers. When
+doing CONNECT, libcurl sends CURLOPT_PROXYHEADER(3) headers only to the
+proxy and then CURLOPT_HTTPHEADER(3) headers only to the server.
+
+# DEFAULT
+
+CURLHEADER_SEPARATE (changed in 7.42.1, used CURLHEADER_UNIFIED before then)
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ struct curl_slist *list;
+ list = curl_slist_append(NULL, "Shoesize: 10");
+ list = curl_slist_append(list, "Accept:");
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ /* HTTPS over a proxy makes a separate CONNECT to the proxy, so tell
+ libcurl to not send the custom headers to the proxy. Keep them
+ separate! */
+ curl_easy_setopt(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
+ ret = curl_easy_perform(curl);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.37.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HSTS.3 b/docs/libcurl/opts/CURLOPT_HSTS.3
deleted file mode 100644
index 6c3a39576..000000000
--- a/docs/libcurl/opts/CURLOPT_HSTS.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HSTS 3 "5 Feb 2019" libcurl libcurl
-.SH NAME
-CURLOPT_HSTS \- HSTS cache file name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTS, char *filename);
-.fi
-.SH DESCRIPTION
-Make the \fIfilename\fP point to a file name to load an existing HSTS cache
-from, and to store the cache in when the easy handle is closed. Setting a file
-name with this option also enables HSTS for this handle (the equivalent of
-setting \fICURLHSTS_ENABLE\fP with \fICURLOPT_HSTS_CTRL(3)\fP).
-
-If the given file does not exist or contains no HSTS entries at startup, the
-HSTS cache simply starts empty. Setting the file name to NULL or "" only
-enables HSTS without reading from or writing to any file.
-
-If this option is set multiple times, libcurl loads cache entries from each
-given file but only stores the last used name for later writing.
-.SH "FILE FORMAT"
-The HSTS cache is saved to and loaded from a text file with one entry per
-physical line. Each line in the file has the following format:
-
-[host] [stamp]
-
-[host] is the domain name for the entry and the name is dot-prefixed if it is
-an entry valid for all subdomains to the name as well or only for the exact
-name.
-
-[stamp] is the time (in UTC) when the entry expires and it uses the format
-\&"YYYYMMDD HH:MM:SS".
-
-Lines starting with "#" are treated as comments and are ignored. There is
-currently no length or size limit.
-.SH DEFAULT
-NULL, no file name
-.SH PROTOCOLS
-HTTPS and HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_HSTS, "/home/user/.hsts-cache");
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.74.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ALTSVC (3),
-.BR CURLOPT_HSTS_CTRL (3),
-.BR CURLOPT_RESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_HSTS.md b/docs/libcurl/opts/CURLOPT_HSTS.md
new file mode 100644
index 000000000..83379f270
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HSTS.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HSTS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ALTSVC (3)
+ - CURLOPT_HSTS_CTRL (3)
+ - CURLOPT_RESOLVE (3)
+---
+
+# NAME
+
+CURLOPT_HSTS - HSTS cache file name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTS, char *filename);
+~~~
+
+# DESCRIPTION
+
+Make the *filename* point to a filename to load an existing HSTS cache
+from, and to store the cache in when the easy handle is closed. Setting a file
+name with this option also enables HSTS for this handle (the equivalent of
+setting *CURLHSTS_ENABLE* with CURLOPT_HSTS_CTRL(3)).
+
+If the given file does not exist or contains no HSTS entries at startup, the
+HSTS cache simply starts empty. Setting the filename to NULL or "" only
+enables HSTS without reading from or writing to any file.
+
+If this option is set multiple times, libcurl loads cache entries from each
+given file but only stores the last used name for later writing.
+
+# FILE FORMAT
+
+The HSTS cache is saved to and loaded from a text file with one entry per
+physical line. Each line in the file has the following format:
+
+[host] [stamp]
+
+[host] is the domain name for the entry and the name is dot-prefixed if it is
+an entry valid for all subdomains to the name as well or only for the exact
+name.
+
+[stamp] is the time (in UTC) when the entry expires and it uses the format
+"YYYYMMDD HH:MM:SS".
+
+Lines starting with "#" are treated as comments and are ignored. There is
+currently no length or size limit.
+
+# DEFAULT
+
+NULL, no file name
+
+# PROTOCOLS
+
+HTTPS and HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_HSTS, "/home/user/.hsts-cache");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.74.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3 b/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3
deleted file mode 100644
index 26bead41d..000000000
--- a/docs/libcurl/opts/CURLOPT_HSTSREADDATA.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HSTSREADDATA 3 "14 Sep 2020" libcurl libcurl
-.SH NAME
-CURLOPT_HSTSREADDATA \- pointer passed to the HSTS read callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Data \fIpointer\fP to pass to the HSTS read function. If you use the
-\fICURLOPT_HSTSREADFUNCTION(3)\fP option, this is the pointer you get as input
-in the 3rd argument to the callback.
-
-This option does not enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
-do that.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-This feature is only used for HTTP(S) transfer.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-struct MyData this;
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
-
- /* pass pointer that gets passed in to the
- CURLOPT_HSTSREADFUNCTION callback */
- curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &this);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.74.0
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_HSTS (3),
-.BR CURLOPT_HSTSREADFUNCTION (3),
-.BR CURLOPT_HSTSWRITEDATA (3),
-.BR CURLOPT_HSTSWRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADDATA.md b/docs/libcurl/opts/CURLOPT_HSTSREADDATA.md
new file mode 100644
index 000000000..8fbb888d3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HSTSREADDATA.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HSTSREADDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HSTS (3)
+ - CURLOPT_HSTSREADFUNCTION (3)
+ - CURLOPT_HSTSWRITEDATA (3)
+ - CURLOPT_HSTSWRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_HSTSREADDATA - pointer passed to the HSTS read callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Data *pointer* to pass to the HSTS read function. If you use the
+CURLOPT_HSTSREADFUNCTION(3) option, this is the pointer you get as input
+in the 3rd argument to the callback.
+
+This option does not enable HSTS, you need to use CURLOPT_HSTS_CTRL(3) to
+do that.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+This feature is only used for HTTP(S) transfer.
+
+# EXAMPLE
+
+~~~c
+struct MyData {
+ void *custom;
+};
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ struct MyData this;
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
+
+ /* pass pointer that gets passed in to the
+ CURLOPT_HSTSREADFUNCTION callback */
+ curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &this);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.74.0
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3
deleted file mode 100644
index 3dc9244f7..000000000
--- a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3
+++ /dev/null
@@ -1,90 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HSTSREADFUNCTION 3 "14 Sep 2020" libcurl libcurl
-.SH NAME
-CURLOPT_HSTSREADFUNCTION \- read callback for HSTS hosts
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-struct curl_hstsentry {
- char *name;
- size_t namelen;
- unsigned int includeSubDomains:1;
- char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
-};
-
-CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *clientp);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADFUNCTION, hstsread);
-.fi
-.SH DESCRIPTION
-Pass a pointer to your callback function, as the prototype shows above.
-
-This callback function gets called by libcurl repeatedly when it populates the
-in-memory HSTS cache.
-
-Set the \fIclientp\fP argument with the \fICURLOPT_HSTSREADDATA(3)\fP option
-or it is NULL.
-
-When this callback is invoked, the \fIsts\fP pointer points to a populated
-struct: Copy the host name to \fIname\fP (no longer than \fInamelen\fP
-bytes). Make it null-terminated. Set \fIincludeSubDomains\fP to TRUE or
-FALSE. Set \fIexpire\fP to a date stamp or a zero length string for *forever*
-(wrong date stamp format might cause the name to not get accepted)
-
-The callback should return \fICURLSTS_OK\fP if it returns a name and is
-prepared to be called again (for another host) or \fICURLSTS_DONE\fP if it has
-no entry to return. It can also return \fICURLSTS_FAIL\fP to signal
-error. Returning \fICURLSTS_FAIL\fP stops the transfer from being performed
-and make \fICURLE_ABORTED_BY_CALLBACK\fP get returned.
-
-This option does not enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
-do that.
-.SH DEFAULT
-NULL - no callback.
-.SH PROTOCOLS
-This feature is only used for HTTP(S) transfer.
-.SH EXAMPLE
-.nf
-{
- /* set HSTS read callback */
- curl_easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hstsread);
-
- /* pass in suitable argument to the callback */
- curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &hstspreload[0]);
-
- result = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.74.0
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_HSTS (3),
-.BR CURLOPT_HSTS_CTRL (3),
-.BR CURLOPT_HSTSREADDATA (3),
-.BR CURLOPT_HSTSWRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md
new file mode 100644
index 000000000..cc221638c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md
@@ -0,0 +1,106 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HSTSREADFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HSTS (3)
+ - CURLOPT_HSTSREADDATA (3)
+ - CURLOPT_HSTSWRITEFUNCTION (3)
+ - CURLOPT_HSTS_CTRL (3)
+---
+
+# NAME
+
+CURLOPT_HSTSREADFUNCTION - read callback for HSTS hosts
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+struct curl_hstsentry {
+ char *name;
+ size_t namelen;
+ unsigned int includeSubDomains:1;
+ char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
+};
+
+CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *clientp);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADFUNCTION, hstsread);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, as the prototype shows above.
+
+This callback function gets called by libcurl repeatedly when it populates the
+in-memory HSTS cache.
+
+Set the *clientp* argument with the CURLOPT_HSTSREADDATA(3) option
+or it is NULL.
+
+When this callback is invoked, the *sts* pointer points to a populated
+struct: Copy the hostname to *name* (no longer than *namelen*
+bytes). Make it null-terminated. Set *includeSubDomains* to TRUE or
+FALSE. Set *expire* to a date stamp or a zero length string for *forever*
+(wrong date stamp format might cause the name to not get accepted)
+
+The callback should return *CURLSTS_OK* if it returns a name and is
+prepared to be called again (for another host) or *CURLSTS_DONE* if it has
+no entry to return. It can also return *CURLSTS_FAIL* to signal
+error. Returning *CURLSTS_FAIL* stops the transfer from being performed
+and make *CURLE_ABORTED_BY_CALLBACK* get returned.
+
+This option does not enable HSTS, you need to use CURLOPT_HSTS_CTRL(3) to
+do that.
+
+# DEFAULT
+
+NULL - no callback.
+
+# PROTOCOLS
+
+This feature is only used for HTTP(S) transfer.
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static CURLSTScode hsts_cb(CURL *easy, struct curl_hstsentry *sts,
+ void *clientp)
+{
+ /* populate the struct as documented */
+ return CURLSTS_OK;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct priv my_stuff;
+ CURLcode res;
+
+ /* set HSTS read callback */
+ curl_easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hsts_cb);
+
+ /* pass in suitable argument to the callback */
+ curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &my_stuff);
+
+ res = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.74.0
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3 b/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3
deleted file mode 100644
index aba5cb2cc..000000000
--- a/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HSTSWRITEDATA 3 "14 Sep 2020" libcurl libcurl
-.SH NAME
-CURLOPT_HSTSWRITEDATA \- pointer passed to the HSTS write callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Data \fIpointer\fP to pass to the HSTS write function. If you use the
-\fICURLOPT_HSTSWRITEFUNCTION(3)\fP option, this is the pointer you get as
-input in the fourth argument to the callback.
-
-This option does not enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
-do that.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-This feature is only used for HTTP(S) transfer.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-struct MyData this;
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
-
- /* pass pointer that gets passed in to the
- CURLOPT_HSTSWRITEFUNCTION callback */
- curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &this);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.74.0
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_HSTS (3),
-.BR CURLOPT_HSTSREADDATA (3),
-.BR CURLOPT_HSTSREADFUNCTION (3),
-.BR CURLOPT_HSTSWRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.md b/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.md
new file mode 100644
index 000000000..b4486d7a3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HSTSWRITEDATA.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HSTSWRITEDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HSTS (3)
+ - CURLOPT_HSTSREADDATA (3)
+ - CURLOPT_HSTSREADFUNCTION (3)
+ - CURLOPT_HSTSWRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_HSTSWRITEDATA - pointer passed to the HSTS write callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Data *pointer* to pass to the HSTS write function. If you use the
+CURLOPT_HSTSWRITEFUNCTION(3) option, this is the pointer you get as
+input in the fourth argument to the callback.
+
+This option does not enable HSTS, you need to use CURLOPT_HSTS_CTRL(3) to
+do that.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+This feature is only used for HTTP(S) transfer.
+
+# EXAMPLE
+
+~~~c
+struct MyData {
+ void *custom;
+};
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ struct MyData this;
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
+
+ /* pass pointer that gets passed in to the
+ CURLOPT_HSTSWRITEFUNCTION callback */
+ curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &this);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.74.0
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3
deleted file mode 100644
index f7b44faf7..000000000
--- a/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HSTSWRITEFUNCTION 3 "14 Sep 2020" libcurl libcurl
-.SH NAME
-CURLOPT_HSTSWRITEFUNCTION \- write callback for HSTS hosts
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-struct curl_hstsentry {
- char *name;
- size_t namelen;
- unsigned int includeSubDomains:1;
- char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
-};
-
-struct curl_index {
- size_t index; /* the provided entry's "index" or count */
- size_t total; /* total number of entries to save */
-};
-
-CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *sts,
- struct curl_index *count, void *clientp);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
-.fi
-.SH DESCRIPTION
-Pass a pointer to your callback function, as the prototype shows above.
-
-This callback function gets called by libcurl repeatedly to allow the
-application to store the in-memory HSTS cache when libcurl is about to discard
-it.
-
-Set the \fIclientp\fP argument with the \fICURLOPT_HSTSWRITEDATA(3)\fP option
-or it is NULL.
-When the callback is invoked, the \fIsts\fP pointer points to a populated
-struct: Read the host name to 'name' (it is \fInamelen\fP bytes long and null
-terminated. The \fIincludeSubDomains\fP field is non-zero if the entry matches
-subdomains. The \fIexpire\fP string is a date stamp null-terminated string
-using the syntax YYYYMMDD HH:MM:SS.
-
-The callback should return \fICURLSTS_OK\fP if it succeeded and is prepared to
-be called again (for another host) or \fICURLSTS_DONE\fP if there is nothing
-more to do. It can also return \fICURLSTS_FAIL\fP to signal error.
-
-This option does not enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
-do that.
-.SH DEFAULT
-NULL - no callback.
-.SH PROTOCOLS
-This feature is only used for HTTP(S) transfer.
-.SH EXAMPLE
-.nf
-{
- /* set HSTS read callback */
- curl_easy_setopt(curl, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
-
- /* pass in suitable argument to the callback */
- curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &hstspreload[0]);
-
- result = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.74.0
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_HSTS (3),
-.BR CURLOPT_HSTS_CTRL (3),
-.BR CURLOPT_HSTSWRITEDATA (3),
-.BR CURLOPT_HSTSWRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md b/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md
new file mode 100644
index 000000000..ede35218c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md
@@ -0,0 +1,110 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HSTSWRITEFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HSTS (3)
+ - CURLOPT_HSTSWRITEDATA (3)
+ - CURLOPT_HSTSWRITEFUNCTION (3)
+ - CURLOPT_HSTS_CTRL (3)
+---
+
+# NAME
+
+CURLOPT_HSTSWRITEFUNCTION - write callback for HSTS hosts
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+struct curl_hstsentry {
+ char *name;
+ size_t namelen;
+ unsigned int includeSubDomains:1;
+ char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
+};
+
+struct curl_index {
+ size_t index; /* the provided entry's "index" or count */
+ size_t total; /* total number of entries to save */
+};
+
+CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *sts,
+ struct curl_index *count, void *clientp);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, as the prototype shows above.
+
+This callback function gets called by libcurl repeatedly to allow the
+application to store the in-memory HSTS cache when libcurl is about to discard
+it.
+
+Set the *clientp* argument with the CURLOPT_HSTSWRITEDATA(3) option
+or it is NULL.
+When the callback is invoked, the *sts* pointer points to a populated
+struct: Read the hostname to 'name' (it is *namelen* bytes long and null
+terminated. The *includeSubDomains* field is non-zero if the entry matches
+subdomains. The *expire* string is a date stamp null-terminated string
+using the syntax YYYYMMDD HH:MM:SS.
+
+The callback should return *CURLSTS_OK* if it succeeded and is prepared to
+be called again (for another host) or *CURLSTS_DONE* if there is nothing
+more to do. It can also return *CURLSTS_FAIL* to signal error.
+
+This option does not enable HSTS, you need to use CURLOPT_HSTS_CTRL(3) to
+do that.
+
+# DEFAULT
+
+NULL - no callback.
+
+# PROTOCOLS
+
+This feature is only used for HTTP(S) transfer.
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static CURLSTScode hswr_cb(CURL *easy, struct curl_hstsentry *sts,
+ struct curl_index *count, void *clientp)
+{
+ /* save the passed in HSTS data somewhere */
+ return CURLSTS_OK;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct priv my_stuff;
+ CURLcode res;
+
+ /* set HSTS read callback */
+ curl_easy_setopt(curl, CURLOPT_HSTSWRITEFUNCTION, hswr_cb);
+
+ /* pass in suitable argument to the callback */
+ curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &my_stuff);
+
+ res = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.74.0
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3 b/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3
deleted file mode 100644
index ebf336e5f..000000000
--- a/docs/libcurl/opts/CURLOPT_HSTS_CTRL.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HSTS_CTRL 3 "4 Sep 2020" libcurl libcurl
-.SH NAME
-CURLOPT_HSTS_CTRL \- control HSTS behavior
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-#define CURLHSTS_ENABLE (1<<0)
-#define CURLHSTS_READONLYFILE (1<<1)
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTS_CTRL, long bitmask);
-.fi
-.SH DESCRIPTION
-HSTS (HTTP Strict Transport Security) means that an HTTPS server can instruct
-the client to not contact it again over clear-text HTTP for a certain period
-into the future. libcurl then automatically redirects HTTP attempts to such
-hosts to instead use HTTPS. This is done by libcurl retaining this knowledge
-in an in-memory cache.
-
-Populate the long \fIbitmask\fP with the correct set of features to instruct
-libcurl how to handle HSTS for the transfers using this handle.
-.SH BITS
-.IP "CURLHSTS_ENABLE"
-Enable the in-memory HSTS cache for this handle.
-.IP "CURLHSTS_READONLYFILE"
-Make the HSTS file (if specified) read-only - makes libcurl not save the cache
-to the file when closing the handle.
-.SH DEFAULT
-0. HSTS is disabled by default.
-.SH PROTOCOLS
-HTTPS and HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, (long)CURLHSTS_ENABLE);
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.74.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ALTSVC (3),
-.BR CURLOPT_CONNECT_TO (3),
-.BR CURLOPT_HSTS (3),
-.BR CURLOPT_RESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_HSTS_CTRL.md b/docs/libcurl/opts/CURLOPT_HSTS_CTRL.md
new file mode 100644
index 000000000..d60e58f0f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HSTS_CTRL.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HSTS_CTRL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ALTSVC (3)
+ - CURLOPT_CONNECT_TO (3)
+ - CURLOPT_HSTS (3)
+ - CURLOPT_RESOLVE (3)
+---
+
+# NAME
+
+CURLOPT_HSTS_CTRL - control HSTS behavior
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+#define CURLHSTS_ENABLE (1<<0)
+#define CURLHSTS_READONLYFILE (1<<1)
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTS_CTRL, long bitmask);
+~~~
+
+# DESCRIPTION
+
+HSTS (HTTP Strict Transport Security) means that an HTTPS server can instruct
+the client to not contact it again over clear-text HTTP for a certain period
+into the future. libcurl then automatically redirects HTTP attempts to such
+hosts to instead use HTTPS. This is done by libcurl retaining this knowledge
+in an in-memory cache.
+
+Populate the long *bitmask* with the correct set of features to instruct
+libcurl how to handle HSTS for the transfers using this handle.
+
+# BITS
+
+## CURLHSTS_ENABLE
+
+Enable the in-memory HSTS cache for this handle.
+
+## CURLHSTS_READONLYFILE
+
+Make the HSTS file (if specified) read-only - makes libcurl not save the cache
+to the file when closing the handle.
+
+# DEFAULT
+
+0. HSTS is disabled by default.
+
+# PROTOCOLS
+
+HTTPS and HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, (long)CURLHSTS_ENABLE);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.74.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3 b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3
deleted file mode 100644
index da1cc7928..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTP09_ALLOWED 3 "17 Dec 2018" libcurl libcurl
-.SH NAME
-CURLOPT_HTTP09_ALLOWED \- allow HTTP/0.9 response
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP09_ALLOWED, long allowed);
-.fi
-.SH DESCRIPTION
-Pass the long argument \fIallowed\fP set to 1L to allow HTTP/0.9 responses.
-
-An HTTP/0.9 response is a server response entirely without headers and only a
-body. You can connect to lots of random TCP services and still get a response
-that curl might consider to be HTTP/0.9!
-.SH DEFAULT
-curl allowed HTTP/0.9 responses by default before 7.66.0
-
-Since 7.66.0, libcurl requires this option set to 1L to allow HTTP/0.9
-responses.
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_HTTP09_ALLOWED, 1L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Option added in 7.64.0, present along with HTTP.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTP_VERSION (3),
-.BR CURLOPT_SSLVERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md
new file mode 100644
index 000000000..d3594926f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTP09_ALLOWED
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTP_VERSION (3)
+ - CURLOPT_SSLVERSION (3)
+---
+
+# NAME
+
+CURLOPT_HTTP09_ALLOWED - allow HTTP/0.9 response
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP09_ALLOWED, long allowed);
+~~~
+
+# DESCRIPTION
+
+Pass the long argument *allowed* set to 1L to allow HTTP/0.9 responses.
+
+An HTTP/0.9 response is a server response entirely without headers and only a
+body. You can connect to lots of random TCP services and still get a response
+that curl might consider to be HTTP/0.9!
+
+# DEFAULT
+
+curl allowed HTTP/0.9 responses by default before 7.66.0
+
+Since 7.66.0, libcurl requires this option set to 1L to allow HTTP/0.9
+responses.
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HTTP09_ALLOWED, 1L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Option added in 7.64.0, present along with HTTP.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3 b/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3
deleted file mode 100644
index 86554fcf7..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTP200ALIASES 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTP200ALIASES \- alternative matches for HTTP 200 OK
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP200ALIASES,
- struct curl_slist *aliases);
-.SH DESCRIPTION
-Pass a pointer to a linked list of \fIaliases\fP to be treated as valid HTTP
-200 responses. Some servers respond with a custom header response line. For
-example, SHOUTcast servers respond with "ICY 200 OK". Also some old Icecast
-1.3.x servers respond like that for certain user agent headers or in absence
-of such. By including this string in your list of aliases, the response gets
-treated as a valid HTTP header line such as "HTTP/1.0 200 OK".
-
-The linked list should be a fully valid list of struct curl_slist structs, and
-be properly filled in. Use \fIcurl_slist_append(3)\fP to create the list and
-\fIcurl_slist_free_all(3)\fP to clean up an entire list.
-
-The alias itself is not parsed for any version strings. The protocol is
-assumed to match HTTP 1.0 when an alias match.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- struct curl_slist *list;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- list = curl_slist_append(NULL, "ICY 200 OK");
- list = curl_slist_append(list, "WEIRDO 99 FINE");
-
- curl_easy_setopt(curl, CURLOPT_HTTP200ALIASES, list);
- curl_easy_perform(curl);
- curl_slist_free_all(list); /* free the list again */
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.3
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTP09_ALLOWED (3),
-.BR CURLOPT_HTTP_VERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.md b/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.md
new file mode 100644
index 000000000..b48faf603
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTP200ALIASES.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTP200ALIASES
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTP09_ALLOWED (3)
+ - CURLOPT_HTTP_VERSION (3)
+---
+
+# NAME
+
+CURLOPT_HTTP200ALIASES - alternative matches for HTTP 200 OK
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP200ALIASES,
+ struct curl_slist *aliases);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of *aliases* to be treated as valid HTTP 200
+responses. Some servers respond with a custom header response line. For
+example, SHOUTcast servers respond with "ICY 200 OK". Also some old Icecast
+1.3.x servers respond like that for certain user agent headers or in absence
+of such. By including this string in your list of aliases, the response gets
+treated as a valid HTTP header line such as "HTTP/1.0 200 OK".
+
+The linked list should be a fully valid list of struct curl_slist structs, and
+be properly filled in. Use curl_slist_append(3) to create the list and
+curl_slist_free_all(3) to clean up an entire list.
+
+The alias itself is not parsed for any version strings. The protocol is
+assumed to match HTTP 1.0 when an alias match.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct curl_slist *list;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ list = curl_slist_append(NULL, "ICY 200 OK");
+ list = curl_slist_append(list, "WEIRDO 99 FINE");
+
+ curl_easy_setopt(curl, CURLOPT_HTTP200ALIASES, list);
+ curl_easy_perform(curl);
+ curl_slist_free_all(list); /* free the list again */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.3
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTPAUTH.3 b/docs/libcurl/opts/CURLOPT_HTTPAUTH.3
deleted file mode 100644
index f91c548f5..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTPAUTH.3
+++ /dev/null
@@ -1,140 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTPAUTH 3 "2 Aug 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTPAUTH \- HTTP server authentication methods to try
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPAUTH, long bitmask);
-.SH DESCRIPTION
-Pass a long as parameter, which is set to a bitmask, to tell libcurl which
-authentication method(s) you want it to use speaking to the remote server.
-
-The available bits are listed below. If more than one bit is set, libcurl
-first queries the host to see which authentication methods it supports and
-then picks the best one you allow it to use. For some methods, this induces an
-extra network round-trip. Set the actual name and password with the
-\fICURLOPT_USERPWD(3)\fP option or with the \fICURLOPT_USERNAME(3)\fP and the
-\fICURLOPT_PASSWORD(3)\fP options.
-
-For authentication with a proxy, see \fICURLOPT_PROXYAUTH(3)\fP.
-
-.IP CURLAUTH_BASIC
-HTTP Basic authentication. This is the default choice, and the only method
-that is in wide-spread use and supported virtually everywhere. This sends
-the user name and password over the network in plain text, easily captured by
-others.
-.IP CURLAUTH_DIGEST
-HTTP Digest authentication. Digest authentication is defined in RFC 2617 and
-is a more secure way to do authentication over public networks than the
-regular old-fashioned Basic method.
-.IP CURLAUTH_DIGEST_IE
-HTTP Digest authentication with an IE flavor. Digest authentication is
-defined in RFC 2617 and is a more secure way to do authentication over public
-networks than the regular old-fashioned Basic method. The IE flavor is simply
-that libcurl uses a special "quirk" that IE is known to have used before
-version 7 and that some servers require the client to use.
-.IP CURLAUTH_BEARER
-HTTP Bearer token authentication, used primarily in OAuth 2.0 protocol.
-
-You can set the Bearer token to use with \fICURLOPT_XOAUTH2_BEARER(3)\fP.
-.IP CURLAUTH_NEGOTIATE
-HTTP Negotiate (SPNEGO) authentication. Negotiate authentication is defined
-in RFC 4559 and is the most secure way to perform authentication over HTTP.
-
-You need to build libcurl with a suitable GSS-API library or SSPI on Windows
-for this to work.
-.IP CURLAUTH_NTLM
-HTTP NTLM authentication. A proprietary protocol invented and used by
-Microsoft. It uses a challenge-response and hash concept similar to Digest, to
-prevent the password from being eavesdropped.
-
-You need to build libcurl with either OpenSSL or GnuTLS support for this
-option to work, or build libcurl on Windows with SSPI support.
-.IP CURLAUTH_NTLM_WB
-NTLM delegating to winbind helper. Authentication is performed by a separate
-binary application that is executed when needed. The name of the application
-is specified at compile time but is typically \fB/usr/bin/ntlm_auth\fP.
-
-Note that libcurl forks when necessary to run the winbind application and kill
-it when complete, calling \fBwaitpid()\fP to await its exit when done. On
-POSIX operating systems, killing the process causes a SIGCHLD signal to be
-raised (regardless of whether \fICURLOPT_NOSIGNAL(3)\fP is set), which must be
-handled intelligently by the application. In particular, the application must
-not unconditionally call wait() in its SIGCHLD signal handler to avoid being
-subject to a race condition. This behavior is subject to change in future
-versions of libcurl.
-.IP CURLAUTH_ANY
-This is a convenience macro that sets all bits and thus makes libcurl pick any
-it finds suitable. libcurl automatically selects the one it finds most secure.
-.IP CURLAUTH_ANYSAFE
-This is a convenience macro that sets all bits except Basic and thus makes
-libcurl pick any it finds suitable. libcurl automatically selects the one it
-finds most secure.
-.IP CURLAUTH_ONLY
-This is a meta symbol. OR this value together with a single specific auth
-value to force libcurl to probe for unrestricted auth and if not, only that
-single auth algorithm is acceptable.
-.IP CURLAUTH_AWS_SIGV4
-provides AWS V4 signature authentication on HTTPS header
-see \fICURLOPT_AWS_SIGV4(3)\fP.
-.SH DEFAULT
-CURLAUTH_BASIC
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* allow whatever auth the server speaks */
- curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
- curl_easy_setopt(curl, CURLOPT_USERPWD, "james:bond");
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Option Added in 7.10.6.
-
-CURLAUTH_DIGEST_IE was added in 7.19.3
-
-CURLAUTH_ONLY was added in 7.21.3
-
-CURLAUTH_NTLM_WB was added in 7.22.0
-
-CURLAUTH_BEARER was added in 7.61.0
-
-CURLAUTH_AWS_SIGV4 was added in 7.74.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_NOT_BUILT_IN if the bitmask specified no supported authentication
-methods.
-.SH "SEE ALSO"
-.BR CURLOPT_PASSWORD (3),
-.BR CURLOPT_PROXYAUTH (3),
-.BR CURLOPT_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTPAUTH.md b/docs/libcurl/opts/CURLOPT_HTTPAUTH.md
new file mode 100644
index 000000000..ca92f5eb0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTPAUTH.md
@@ -0,0 +1,163 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTPAUTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_PROXYAUTH (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_HTTPAUTH - HTTP server authentication methods to try
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPAUTH, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter, which is set to a bitmask, to tell libcurl which
+authentication method(s) you want it to use speaking to the remote server.
+
+The available bits are listed below. If more than one bit is set, libcurl
+first queries the host to see which authentication methods it supports and
+then picks the best one you allow it to use. For some methods, this induces an
+extra network round-trip. Set the actual name and password with the
+CURLOPT_USERPWD(3) option or with the CURLOPT_USERNAME(3) and the
+CURLOPT_PASSWORD(3) options.
+
+For authentication with a proxy, see CURLOPT_PROXYAUTH(3).
+
+## CURLAUTH_BASIC
+
+HTTP Basic authentication. This is the default choice, and the only method
+that is in wide-spread use and supported virtually everywhere. This sends
+the user name and password over the network in plain text, easily captured by
+others.
+
+## CURLAUTH_DIGEST
+
+HTTP Digest authentication. Digest authentication is defined in RFC 2617 and
+is a more secure way to do authentication over public networks than the
+regular old-fashioned Basic method.
+
+## CURLAUTH_DIGEST_IE
+
+HTTP Digest authentication with an IE flavor. Digest authentication is defined
+in RFC 2617 and is a more secure way to do authentication over public networks
+than the regular old-fashioned Basic method. The IE flavor is simply that
+libcurl uses a special "quirk" that IE is known to have used before version 7
+and that some servers require the client to use.
+
+## CURLAUTH_BEARER
+
+HTTP Bearer token authentication, used primarily in OAuth 2.0 protocol.
+
+You can set the Bearer token to use with CURLOPT_XOAUTH2_BEARER(3).
+
+## CURLAUTH_NEGOTIATE
+
+HTTP Negotiate (SPNEGO) authentication. Negotiate authentication is defined
+in RFC 4559 and is the most secure way to perform authentication over HTTP.
+
+You need to build libcurl with a suitable GSS-API library or SSPI on Windows
+for this to work.
+
+## CURLAUTH_NTLM
+
+HTTP NTLM authentication. A proprietary protocol invented and used by
+Microsoft. It uses a challenge-response and hash concept similar to Digest, to
+prevent the password from being eavesdropped.
+
+You need to build libcurl with either OpenSSL or GnuTLS support for this
+option to work, or build libcurl on Windows with SSPI support.
+
+## CURLAUTH_NTLM_WB
+
+NTLM delegating to winbind helper. Authentication is performed by a separate
+binary application that is executed when needed. The name of the application
+is specified at compile time but is typically **/usr/bin/ntlm_auth**.
+
+Note that libcurl forks when necessary to run the winbind application and kill
+it when complete, calling **waitpid()** to await its exit when done. On POSIX
+operating systems, killing the process causes a SIGCHLD signal to be raised
+(regardless of whether CURLOPT_NOSIGNAL(3) is set), which must be handled
+intelligently by the application. In particular, the application must not
+unconditionally call wait() in its SIGCHLD signal handler to avoid being
+subject to a race condition. This behavior is subject to change in future
+versions of libcurl.
+
+## CURLAUTH_ANY
+
+This is a convenience macro that sets all bits and thus makes libcurl pick any
+it finds suitable. libcurl automatically selects the one it finds most secure.
+
+## CURLAUTH_ANYSAFE
+
+This is a convenience macro that sets all bits except Basic and thus makes
+libcurl pick any it finds suitable. libcurl automatically selects the one it
+finds most secure.
+
+## CURLAUTH_ONLY
+
+This is a meta symbol. OR this value together with a single specific auth
+value to force libcurl to probe for unrestricted auth and if not, only that
+single auth algorithm is acceptable.
+
+## CURLAUTH_AWS_SIGV4
+
+provides AWS V4 signature authentication on HTTPS header
+see CURLOPT_AWS_SIGV4(3).
+
+# DEFAULT
+
+CURLAUTH_BASIC
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* allow whatever auth the server speaks */
+ curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
+ curl_easy_setopt(curl, CURLOPT_USERPWD, "james:bond");
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Option Added in 7.10.6.
+
+CURLAUTH_DIGEST_IE was added in 7.19.3
+
+CURLAUTH_ONLY was added in 7.21.3
+
+CURLAUTH_NTLM_WB was added in 7.22.0
+
+CURLAUTH_BEARER was added in 7.61.0
+
+CURLAUTH_AWS_SIGV4 was added in 7.74.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_NOT_BUILT_IN if the bitmask specified no supported authentication
+methods.
diff --git a/docs/libcurl/opts/CURLOPT_HTTPGET.3 b/docs/libcurl/opts/CURLOPT_HTTPGET.3
deleted file mode 100644
index 25c3bd734..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTPGET.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTPGET 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTPGET \- ask for an HTTP GET request
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPGET, long useget);
-.fi
-.SH DESCRIPTION
-Pass a long. If \fIuseget\fP is 1, this forces the HTTP request to get back to
-using GET. Usable if a POST, HEAD, PUT, etc has been used previously using the
-same curl \fIhandle\fP.
-
-When setting \fICURLOPT_HTTPGET(3)\fP to 1, libcurl automatically sets
-\fICURLOPT_NOBODY(3)\fP to 0 and \fICURLOPT_UPLOAD(3)\fP to 0.
-
-Setting this option to zero has no effect. Applications need to explicitly
-select which HTTP request method to use, they cannot deselect a method. To
-reset a handle to default method, consider \fIcurl_easy_reset(3)\fP.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* use a GET to fetch this */
- curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_easy_reset (3),
-.BR CURLOPT_NOBODY (3),
-.BR CURLOPT_POST (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTPGET.md b/docs/libcurl/opts/CURLOPT_HTTPGET.md
new file mode 100644
index 000000000..d8b024d8e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTPGET.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTPGET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_NOBODY (3)
+ - CURLOPT_POST (3)
+ - CURLOPT_UPLOAD (3)
+ - curl_easy_reset (3)
+---
+
+# NAME
+
+CURLOPT_HTTPGET - ask for an HTTP GET request
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPGET, long useget);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If *useget* is 1, this forces the HTTP request to get back to
+using GET. Usable if a POST, HEAD, PUT, etc has been used previously using the
+same curl *handle*.
+
+When setting CURLOPT_HTTPGET(3) to 1, libcurl automatically sets
+CURLOPT_NOBODY(3) to 0 and CURLOPT_UPLOAD(3) to 0.
+
+Setting this option to zero has no effect. Applications need to explicitly
+select which HTTP request method to use, they cannot deselect a method. To
+reset a handle to default method, consider curl_easy_reset(3).
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* use a GET to fetch this */
+ curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3 b/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
deleted file mode 100644
index 05b028572..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3
+++ /dev/null
@@ -1,165 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTPHEADER 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTPHEADER \- set of HTTP headers
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPHEADER,
- struct curl_slist *headers);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a linked list of HTTP headers to pass to the server and/or
-proxy in your HTTP request. The same list can be used for both host and proxy
-requests!
-
-When used within an IMAP or SMTP request to upload a MIME mail, the given
-header list establishes the document-level MIME headers to prepend to the
-uploaded document described by \fICURLOPT_MIMEPOST(3)\fP. This does not affect
-raw mail uploads.
-
-The linked list should be a fully valid list of \fBstruct curl_slist\fP
-structs properly filled in. Use \fIcurl_slist_append(3)\fP to create the list
-and \fIcurl_slist_free_all(3)\fP to clean up an entire list. If you add a
-header that is otherwise generated and used by libcurl internally, your added
-header is used instead. If you add a header with no content as in 'Accept:'
-(no data on the right side of the colon), the internally used header is
-disabled/removed. With this option you can add new headers, replace internal
-headers and remove internal headers. To add a header with no content (nothing
-to the right side of the colon), use the form 'name;' (note the ending
-semicolon).
-
-The headers included in the linked list \fBmust not\fP be CRLF-terminated,
-because libcurl adds CRLF after each header item itself. Failure to comply
-with this might result in strange behavior.
-
-The first line in an HTTP request (containing the method, usually a GET or
-POST) is not a header and cannot be replaced using this option. Only the lines
-following the request-line are headers. Adding this method line in this list
-of headers only causes your request to send an invalid header. Use
-\fICURLOPT_CUSTOMREQUEST(3)\fP to change the method.
-
-When this option is passed to \fIcurl_easy_setopt(3)\fP, libcurl does not copy
-the entire list so you \fBmust\fP keep it around until you no longer use this
-\fIhandle\fP for a transfer before you call \fIcurl_slist_free_all(3)\fP on
-the list.
-
-Pass a NULL to this option to reset back to no custom headers.
-
-The most commonly replaced HTTP headers have "shortcuts" in the options
-\fICURLOPT_COOKIE(3)\fP, \fICURLOPT_USERAGENT(3)\fP and
-\fICURLOPT_REFERER(3)\fP. We recommend using those.
-
-There is an alternative option that sets or replaces headers only for requests
-that are sent with CONNECT to a proxy: \fICURLOPT_PROXYHEADER(3)\fP. Use
-\fICURLOPT_HEADEROPT(3)\fP to control the behavior.
-.SH SPECIFIC HTTP HEADERS
-Setting some specific headers causes libcurl to act differently.
-.IP "Host:"
-The specified host name is used for cookie matching if the cookie engine is
-also enabled for this transfer. If the request is done over HTTP/2 or HTTP/3,
-the custom host name is instead used in the ":authority" header field and
-Host: is not sent at all over the wire.
-.IP "Transfer-Encoding: chunked"
-Tells libcurl the upload is to be done using this chunked encoding instead of
-providing the Content-Length: field in the request.
-.SH SPECIFIC MIME HEADERS
-When used to build a MIME e-mail for IMAP or SMTP, the following
-document-level headers can be set to override libcurl-generated values:
-.IP "Mime-Version:"
-Tells the parser at the receiving site how to interpret the MIME framing.
-It defaults to "1.0" and should normally not be altered.
-.IP "Content-Type:"
-Indicates the document's global structure type. By default, libcurl sets it
-to "multipart/mixed", describing a document made of independent parts. When a
-MIME mail is only composed of alternative representations of the same data
-(i.e.: HTML and plain text), this header must be set to "multipart/alternative".
-In all cases the value must be of the form "multipart/*" to respect the
-document structure and may not include the "boundary=" parameter.
-.P
-Other specific headers that do not have a libcurl default value but are
-strongly desired by mail delivery and user agents should also be included.
-These are "From:", "To:", "Date:" and "Subject:" among others and their
-presence and value is generally checked by anti-spam utilities.
-.SH SECURITY CONCERNS
-By default, this option makes libcurl send the given headers in all HTTP
-requests done by this handle. You should therefore use this option with
-caution if you for example connect to the remote site using a proxy and a
-CONNECT request, you should to consider if that proxy is supposed to also get
-the headers. They may be private or otherwise sensitive to leak.
-
-Use \fICURLOPT_HEADEROPT(3)\fP to make the headers only get sent to where you
-intend them to get sent.
-
-Custom headers are sent in all requests done by the easy handle, which implies
-that if you tell libcurl to follow redirects
-(\fICURLOPT_FOLLOWLOCATION(3)\fP), the same set of custom headers is sent in
-the subsequent request. Redirects can of course go to other hosts and thus
-those servers get all the contents of your custom headers too.
-
-Starting in 7.58.0, libcurl specifically prevents "Authorization:" headers
-from being sent to other hosts than the first used one, unless specifically
-permitted with the \fICURLOPT_UNRESTRICTED_AUTH(3)\fP option.
-
-Starting in 7.64.0, libcurl specifically prevents "Cookie:" headers from being
-sent to other hosts than the first used one, unless specifically permitted
-with the \fICURLOPT_UNRESTRICTED_AUTH(3)\fP option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP, IMAP and SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-
-struct curl_slist *list = NULL;
-
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- list = curl_slist_append(list, "Shoesize: 10");
- list = curl_slist_append(list, "Accept:");
-
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
-
- curl_easy_perform(curl);
-
- curl_slist_free_all(list); /* free the list */
-}
-.fi
-
-.SH AVAILABILITY
-As long as HTTP is enabled. Use in MIME mail added in 7.56.0.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_mime_init (3),
-.BR CURLOPT_CUSTOMREQUEST (3),
-.BR CURLOPT_HEADER (3),
-.BR CURLOPT_HEADEROPT (3),
-.BR CURLOPT_MIMEPOST (3),
-.BR CURLOPT_PROXYHEADER (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTPHEADER.md b/docs/libcurl/opts/CURLOPT_HTTPHEADER.md
new file mode 100644
index 000000000..0ccda775e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTPHEADER.md
@@ -0,0 +1,181 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTPHEADER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CUSTOMREQUEST (3)
+ - CURLOPT_HEADER (3)
+ - CURLOPT_HEADEROPT (3)
+ - CURLOPT_MIMEPOST (3)
+ - CURLOPT_PROXYHEADER (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+CURLOPT_HTTPHEADER - set of HTTP headers
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPHEADER,
+ struct curl_slist *headers);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of HTTP headers to pass to the server and/or
+proxy in your HTTP request. The same list can be used for both host and proxy
+requests!
+
+When used within an IMAP or SMTP request to upload a MIME mail, the given
+header list establishes the document-level MIME headers to prepend to the
+uploaded document described by CURLOPT_MIMEPOST(3). This does not affect
+raw mail uploads.
+
+The linked list should be a fully valid list of **struct curl_slist**
+structs properly filled in. Use curl_slist_append(3) to create the list
+and curl_slist_free_all(3) to clean up an entire list. If you add a
+header that is otherwise generated and used by libcurl internally, your added
+header is used instead. If you add a header with no content as in 'Accept:'
+(no data on the right side of the colon), the internally used header is
+disabled/removed. With this option you can add new headers, replace internal
+headers and remove internal headers. To add a header with no content (nothing
+to the right side of the colon), use the form 'name;' (note the ending
+semicolon).
+
+The headers included in the linked list **must not** be CRLF-terminated,
+because libcurl adds CRLF after each header item itself. Failure to comply
+with this might result in strange behavior. libcurl passes on the verbatim
+strings you give it, without any filter or other safe guards. That includes
+white space and control characters.
+
+The first line in an HTTP request (containing the method, usually a GET or
+POST) is not a header and cannot be replaced using this option. Only the lines
+following the request-line are headers. Adding this method line in this list
+of headers only causes your request to send an invalid header. Use
+CURLOPT_CUSTOMREQUEST(3) to change the method.
+
+When this option is passed to curl_easy_setopt(3), libcurl does not copy
+the entire list so you **must** keep it around until you no longer use this
+*handle* for a transfer before you call curl_slist_free_all(3) on
+the list.
+
+Pass a NULL to this option to reset back to no custom headers.
+
+The most commonly replaced HTTP headers have "shortcuts" in the options
+CURLOPT_COOKIE(3), CURLOPT_USERAGENT(3) and
+CURLOPT_REFERER(3). We recommend using those.
+
+There is an alternative option that sets or replaces headers only for requests
+that are sent with CONNECT to a proxy: CURLOPT_PROXYHEADER(3). Use
+CURLOPT_HEADEROPT(3) to control the behavior.
+
+# SPECIFIC HTTP HEADERS
+
+Setting some specific headers causes libcurl to act differently.
+
+## Host:
+
+The specified hostname is used for cookie matching if the cookie engine is
+also enabled for this transfer. If the request is done over HTTP/2 or HTTP/3,
+the custom hostname is instead used in the ":authority" header field and
+Host: is not sent at all over the wire.
+
+## Transfer-Encoding: chunked
+
+Tells libcurl the upload is to be done using this chunked encoding instead of
+providing the Content-Length: field in the request.
+
+# SPECIFIC MIME HEADERS
+
+When used to build a MIME email for IMAP or SMTP, the following document-level
+headers can be set to override libcurl-generated values:
+
+## Mime-Version:
+
+Tells the parser at the receiving site how to interpret the MIME framing.
+It defaults to "1.0" and should normally not be altered.
+
+## Content-Type:
+
+Indicates the document's global structure type. By default, libcurl sets it
+to "multipart/mixed", describing a document made of independent parts. When a
+MIME mail is only composed of alternative representations of the same data
+(i.e.: HTML and plain text), this header must be set to "multipart/alternative".
+In all cases the value must be of the form "multipart/*" to respect the
+document structure and may not include the "boundary=" parameter.
+
+Other specific headers that do not have a libcurl default value but are
+strongly desired by mail delivery and user agents should also be included.
+These are "From:", "To:", "Date:" and "Subject:" among others and their
+presence and value is generally checked by anti-spam utilities.
+
+# SECURITY CONCERNS
+
+By default, this option makes libcurl send the given headers in all HTTP
+requests done by this handle. You should therefore use this option with
+caution if you for example connect to the remote site using a proxy and a
+CONNECT request, you should to consider if that proxy is supposed to also get
+the headers. They may be private or otherwise sensitive to leak.
+
+Use CURLOPT_HEADEROPT(3) to make the headers only get sent to where you
+intend them to get sent.
+
+Custom headers are sent in all requests done by the easy handle, which implies
+that if you tell libcurl to follow redirects
+(CURLOPT_FOLLOWLOCATION(3)), the same set of custom headers is sent in
+the subsequent request. Redirects can of course go to other hosts and thus
+those servers get all the contents of your custom headers too.
+
+Starting in 7.58.0, libcurl specifically prevents "Authorization:" headers
+from being sent to other hosts than the first used one, unless specifically
+permitted with the CURLOPT_UNRESTRICTED_AUTH(3) option.
+
+Starting in 7.64.0, libcurl specifically prevents "Cookie:" headers from being
+sent to other hosts than the first used one, unless specifically permitted
+with the CURLOPT_UNRESTRICTED_AUTH(3) option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP, IMAP and SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+
+ struct curl_slist *list = NULL;
+
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ list = curl_slist_append(list, "Shoesize: 10");
+ list = curl_slist_append(list, "Accept:");
+
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ curl_easy_perform(curl);
+
+ curl_slist_free_all(list); /* free the list */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as HTTP is enabled. Use in MIME mail added in 7.56.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTPPOST.3 b/docs/libcurl/opts/CURLOPT_HTTPPOST.3
deleted file mode 100644
index 0cdef31ab..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTPPOST.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTPPOST 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTPPOST \- multipart formpost content
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPPOST,
- struct curl_httppost *formpost);
-.SH DESCRIPTION
-\fBThis option is deprecated.\fP Use \fICURLOPT_MIMEPOST(3)\fP instead.
-
-Tells libcurl you want a \fBmultipart/formdata\fP HTTP POST to be made and you
-instruct what data to pass on to the server in the \fIformpost\fP argument.
-Pass a pointer to a linked list of \fIcurl_httppost\fP structs as parameter.
-The easiest way to create such a list, is to use \fIcurl_formadd(3)\fP as
-documented. The data in this list must remain intact as long as the curl
-transfer is alive and is using it.
-
-Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
-You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP.
-
-When setting \fICURLOPT_HTTPPOST(3)\fP, libcurl automatically sets
-\fICURLOPT_NOBODY(3)\fP to 0.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-/* Fill in the file upload field. This makes libcurl load data from
- the given file name when curl_easy_perform() is called. */
-curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "sendfile",
- CURLFORM_FILE, "postit2.c",
- CURLFORM_END);
-
-/* Fill in the filename field */
-curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "filename",
- CURLFORM_COPYCONTENTS, "postit2.c",
- CURLFORM_END);
-
-/* Fill in the submit field too, even if this is rarely needed */
-curl_formadd(&formpost,
- &lastptr,
- CURLFORM_COPYNAME, "submit",
- CURLFORM_COPYCONTENTS, "send",
- CURLFORM_END);
-.fi
-.SH AVAILABILITY
-As long as HTTP is enabled. Deprecated in 7.56.0.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_formadd (3),
-.BR curl_formfree (3),
-.BR curl_mime_init (3),
-.BR CURLOPT_MIMEPOST (3),
-.BR CURLOPT_POST (3),
-.BR CURLOPT_POSTFIELDS (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTPPOST.md b/docs/libcurl/opts/CURLOPT_HTTPPOST.md
new file mode 100644
index 000000000..6fdfc1707
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTPPOST.md
@@ -0,0 +1,100 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTPPOST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MIMEPOST (3)
+ - CURLOPT_POST (3)
+ - CURLOPT_POSTFIELDS (3)
+ - curl_formadd (3)
+ - curl_formfree (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+CURLOPT_HTTPPOST - multipart formpost content
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPPOST,
+ struct curl_httppost *formpost);
+~~~
+
+# DESCRIPTION
+
+**This option is deprecated.** Use CURLOPT_MIMEPOST(3) instead.
+
+Tells libcurl you want a **multipart/formdata** HTTP POST to be made and you
+instruct what data to pass on to the server in the *formpost* argument.
+Pass a pointer to a linked list of *curl_httppost* structs as parameter.
+The easiest way to create such a list, is to use curl_formadd(3) as
+documented. The data in this list must remain intact as long as the curl
+transfer is alive and is using it.
+
+Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
+You can disable this header with CURLOPT_HTTPHEADER(3).
+
+When setting CURLOPT_HTTPPOST(3), libcurl automatically sets
+CURLOPT_NOBODY(3) to 0.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct curl_httppost *formpost;
+ struct curl_httppost *lastptr;
+
+ /* Fill in the file upload field. This makes libcurl load data from
+ the given file name when curl_easy_perform() is called. */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "sendfile",
+ CURLFORM_FILE, "postit2.c",
+ CURLFORM_END);
+
+ /* Fill in the filename field */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "filename",
+ CURLFORM_COPYCONTENTS, "postit2.c",
+ CURLFORM_END);
+
+ /* Fill in the submit field too, even if this is rarely needed */
+ curl_formadd(&formpost,
+ &lastptr,
+ CURLFORM_COPYNAME, "submit",
+ CURLFORM_COPYCONTENTS, "send",
+ CURLFORM_END);
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+ curl_formfree(formpost);
+}
+~~~
+
+# AVAILABILITY
+
+As long as HTTP is enabled. Deprecated in 7.56.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3 b/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3
deleted file mode 100644
index 63ad09adc..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTPPROXYTUNNEL 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTPPROXYTUNNEL \- tunnel through HTTP proxy
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPPROXYTUNNEL, long tunnel);
-.fi
-.SH DESCRIPTION
-Set the \fBtunnel\fP parameter to 1L to make libcurl tunnel all operations
-through the HTTP proxy (set with \fICURLOPT_PROXY(3)\fP). There is a big
-difference between using a proxy and to tunnel through it.
-
-Tunneling means that an HTTP CONNECT request is sent to the proxy, asking it
-to connect to a remote host on a specific port number and then the traffic is
-just passed through the proxy. Proxies tend to white-list specific port numbers
-it allows CONNECT requests to and often only port 80 and 443 are allowed.
-
-To suppress proxy CONNECT response headers from user callbacks use
-\fICURLOPT_SUPPRESS_CONNECT_HEADERS(3)\fP.
-
-HTTP proxies can generally only speak HTTP (for obvious reasons), which makes
-libcurl convert non-HTTP requests to HTTP when using an HTTP proxy without
-this tunnel option set. For example, asking for an FTP URL and specifying an
-HTTP proxy makes libcurl send an FTP URL in an HTTP GET request to the
-proxy. By instead tunneling through the proxy, you avoid that conversion (that
-rarely works through the proxy anyway).
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All network protocols
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1:80");
- curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_PROXYTYPE (3),
-.BR CURLOPT_PROXYPORT (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.md b/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.md
new file mode 100644
index 000000000..bd67640b4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTPPROXYTUNNEL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYPORT (3)
+ - CURLOPT_PROXYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_HTTPPROXYTUNNEL - tunnel through HTTP proxy
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPPROXYTUNNEL, long tunnel);
+~~~
+
+# DESCRIPTION
+
+Set the **tunnel** parameter to 1L to make libcurl tunnel all operations
+through the HTTP proxy (set with CURLOPT_PROXY(3)). There is a big
+difference between using a proxy and to tunnel through it.
+
+Tunneling means that an HTTP CONNECT request is sent to the proxy, asking it
+to connect to a remote host on a specific port number and then the traffic is
+just passed through the proxy. Proxies tend to white-list specific port numbers
+it allows CONNECT requests to and often only port 80 and 443 are allowed.
+
+To suppress proxy CONNECT response headers from user callbacks use
+CURLOPT_SUPPRESS_CONNECT_HEADERS(3).
+
+HTTP proxies can generally only speak HTTP (for obvious reasons), which makes
+libcurl convert non-HTTP requests to HTTP when using an HTTP proxy without
+this tunnel option set. For example, asking for an FTP URL and specifying an
+HTTP proxy makes libcurl send an FTP URL in an HTTP GET request to the
+proxy. By instead tunneling through the proxy, you avoid that conversion (that
+rarely works through the proxy anyway).
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All network protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1:80");
+ curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3 b/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3
deleted file mode 100644
index ab1fdd9fc..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTP_CONTENT_DECODING 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTP_CONTENT_DECODING \- HTTP content decoding control
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_CONTENT_DECODING,
- long enabled);
-.SH DESCRIPTION
-Pass a long to tell libcurl how to act on content decoding. If set to zero,
-content decoding is disabled. If set to 1 it is enabled. Libcurl has no
-default content decoding but requires you to use
-\fICURLOPT_ACCEPT_ENCODING(3)\fP for that.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ACCEPT_ENCODING (3),
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md b/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md
new file mode 100644
index 000000000..b48c0f9fb
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTP_CONTENT_DECODING
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ACCEPT_ENCODING (3)
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_HTTP_CONTENT_DECODING - HTTP content decoding control
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_CONTENT_DECODING,
+ long enabled);
+~~~
+
+# DESCRIPTION
+
+Pass a long to tell libcurl how to act on content decoding. If set to zero,
+content decoding is disabled. If set to 1 it is enabled. Libcurl has no
+default content decoding but requires you to use
+CURLOPT_ACCEPT_ENCODING(3) for that.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3 b/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3
deleted file mode 100644
index 2aa0185d8..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTP_TRANSFER_DECODING 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTP_TRANSFER_DECODING \- HTTP transfer decoding control
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_TRANSFER_DECODING,
- long enabled);
-.SH DESCRIPTION
-Pass a long to tell libcurl how to act on transfer decoding. If set to zero,
-transfer decoding is disabled, if set to 1 it is enabled (default). libcurl
-does chunked transfer decoding by default unless this option is set to zero.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.2 Does not work with the hyper backend (it always has transfer
-decoding enabled).
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTP_CONTENT_DECODING (3),
-.BR CURLOPT_ACCEPT_ENCODING (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md b/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md
new file mode 100644
index 000000000..ba83acaae
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTP_TRANSFER_DECODING
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ACCEPT_ENCODING (3)
+ - CURLOPT_HTTP_CONTENT_DECODING (3)
+---
+
+# NAME
+
+CURLOPT_HTTP_TRANSFER_DECODING - HTTP transfer decoding control
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_TRANSFER_DECODING,
+ long enabled);
+~~~
+
+# DESCRIPTION
+
+Pass a long to tell libcurl how to act on transfer decoding. If set to zero,
+transfer decoding is disabled, if set to 1 it is enabled (default). libcurl
+does chunked transfer decoding by default unless this option is set to zero.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.2 Does not work with the hyper backend (it always has transfer
+decoding enabled).
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
deleted file mode 100644
index bbccda304..000000000
--- a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
+++ /dev/null
@@ -1,103 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_HTTP_VERSION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_HTTP_VERSION \- HTTP protocol version to use
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_VERSION, long version);
-.fi
-.SH DESCRIPTION
-Pass \fIversion\fP a long, set to one of the values described below. They ask
-libcurl to use the specific HTTP versions.
-
-Note that the HTTP version is just a request. libcurl still prioritizes to
-reuse existing connections so it might then reuse a connection using a HTTP
-version you have not asked for.
-
-.IP CURL_HTTP_VERSION_NONE
-We do not care about what version the library uses. libcurl uses whatever it
-thinks fit.
-.IP CURL_HTTP_VERSION_1_0
-Enforce HTTP 1.0 requests.
-.IP CURL_HTTP_VERSION_1_1
-Enforce HTTP 1.1 requests.
-.IP CURL_HTTP_VERSION_2_0
-Attempt HTTP 2 requests. libcurl falls back to HTTP 1.1 if HTTP 2 cannot be
-negotiated with the server. (Added in 7.33.0)
-
-When libcurl uses HTTP/2 over HTTPS, it does not itself insist on TLS 1.2 or
-higher even though that is required by the specification. A user can add this
-version requirement with \fICURLOPT_SSLVERSION(3)\fP.
-
-The alias \fICURL_HTTP_VERSION_2\fP was added in 7.43.0 to better reflect the
-actual protocol name.
-.IP CURL_HTTP_VERSION_2TLS
-Attempt HTTP 2 over TLS (HTTPS) only. libcurl falls back to HTTP 1.1 if HTTP 2
-cannot be negotiated with the HTTPS server. For clear text HTTP servers,
-libcurl uses 1.1. (Added in 7.47.0)
-.IP CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE
-Issue non-TLS HTTP requests using HTTP/2 without HTTP/1.1 Upgrade. It requires
-prior knowledge that the server supports HTTP/2 straight away. HTTPS requests
-still do HTTP/2 the standard way with negotiated protocol version in the TLS
-handshake. (Added in 7.49.0)
-.IP CURL_HTTP_VERSION_3
-(Added in 7.66.0) This option makes libcurl attempt to use HTTP/3 to the host
-given in the URL, with fallback to earlier HTTP versions if needed.
-.IP CURL_HTTP_VERSION_3ONLY
-(Added in 7.88.0) Setting this makes libcurl attempt to use HTTP/3 directly to
-server given in the URL and does not downgrade to earlier HTTP version if the
-server does not support HTTP/3.
-.SH DEFAULT
-Since curl 7.62.0: CURL_HTTP_VERSION_2TLS
-
-Before that: CURL_HTTP_VERSION_1_1
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
- (long)CURL_HTTP_VERSION_2TLS);
- ret = curl_easy_perform(curl);
- if(ret == CURLE_HTTP_RETURNED_ERROR) {
- /* an HTTP response error problem */
- }
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ALTSVC (3),
-.BR CURLOPT_HTTP09_ALLOWED (3),
-.BR CURLOPT_HTTP200ALIASES (3),
-.BR CURLOPT_SSLVERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.md b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.md
new file mode 100644
index 000000000..69dc48c61
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.md
@@ -0,0 +1,119 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_HTTP_VERSION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ALTSVC (3)
+ - CURLOPT_HTTP09_ALLOWED (3)
+ - CURLOPT_HTTP200ALIASES (3)
+ - CURLOPT_SSLVERSION (3)
+---
+
+# NAME
+
+CURLOPT_HTTP_VERSION - HTTP protocol version to use
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP_VERSION, long version);
+~~~
+
+# DESCRIPTION
+
+Pass *version* a long, set to one of the values described below. They ask
+libcurl to use the specific HTTP versions.
+
+Note that the HTTP version is just a request. libcurl still prioritizes to
+reuse existing connections so it might then reuse a connection using an HTTP
+version you have not asked for.
+
+## CURL_HTTP_VERSION_NONE
+
+We do not care about what version the library uses. libcurl uses whatever it
+thinks fit.
+
+## CURL_HTTP_VERSION_1_0
+
+Enforce HTTP 1.0 requests.
+
+## CURL_HTTP_VERSION_1_1
+
+Enforce HTTP 1.1 requests.
+
+## CURL_HTTP_VERSION_2_0
+
+Attempt HTTP 2 requests. libcurl falls back to HTTP 1.1 if HTTP 2 cannot be
+negotiated with the server. (Added in 7.33.0)
+
+When libcurl uses HTTP/2 over HTTPS, it does not itself insist on TLS 1.2 or
+higher even though that is required by the specification. A user can add this
+version requirement with CURLOPT_SSLVERSION(3).
+
+The alias *CURL_HTTP_VERSION_2* was added in 7.43.0 to better reflect the
+actual protocol name.
+
+## CURL_HTTP_VERSION_2TLS
+
+Attempt HTTP 2 over TLS (HTTPS) only. libcurl falls back to HTTP 1.1 if HTTP 2
+cannot be negotiated with the HTTPS server. For clear text HTTP servers,
+libcurl uses 1.1. (Added in 7.47.0)
+
+## CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE
+
+Issue non-TLS HTTP requests using HTTP/2 without HTTP/1.1 Upgrade. It requires
+prior knowledge that the server supports HTTP/2 straight away. HTTPS requests
+still do HTTP/2 the standard way with negotiated protocol version in the TLS
+handshake. (Added in 7.49.0)
+
+## CURL_HTTP_VERSION_3
+
+(Added in 7.66.0) This option makes libcurl attempt to use HTTP/3 to the host
+given in the URL, with fallback to earlier HTTP versions if needed.
+
+## CURL_HTTP_VERSION_3ONLY
+
+(Added in 7.88.0) Setting this makes libcurl attempt to use HTTP/3 directly to
+server given in the URL and does not downgrade to earlier HTTP version if the
+server does not support HTTP/3.
+
+# DEFAULT
+
+Since curl 7.62.0: CURL_HTTP_VERSION_2TLS
+
+Before that: CURL_HTTP_VERSION_1_1
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HTTP_VERSION,
+ (long)CURL_HTTP_VERSION_2TLS);
+ ret = curl_easy_perform(curl);
+ if(ret == CURLE_HTTP_RETURNED_ERROR) {
+ /* an HTTP response error problem */
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3 b/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3
deleted file mode 100644
index c6364b43b..000000000
--- a/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_IGNORE_CONTENT_LENGTH 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_IGNORE_CONTENT_LENGTH \- ignore content length
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IGNORE_CONTENT_LENGTH,
- long ignore);
-.SH DESCRIPTION
-If \fIignore\fP is set to 1L, ignore the Content-Length header in the HTTP
-response and ignore asking for or relying on it for FTP transfers.
-
-This is useful for doing HTTP transfers with ancient web servers which report
-incorrect content length for files over 2 gigabytes. If this option is used,
-curl cannot accurately report progress, and it instead stops the download when
-the server ends the connection.
-
-It is also useful with FTP when for example the file is growing while the
-transfer is in progress which otherwise unconditionally causes libcurl to
-report error.
-
-Only use this option if strictly necessary.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* we know the server is silly, ignore content-length */
- curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.14.1. Support for FTP added in 7.46.0. This option is not working
-for HTTP when libcurl is built to use the hyper backend.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTP_VERSION (3),
-.BR CURLOPT_MAXFILESIZE_LARGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.md b/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.md
new file mode 100644
index 000000000..d12b49120
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_IGNORE_CONTENT_LENGTH.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_IGNORE_CONTENT_LENGTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTP_VERSION (3)
+ - CURLOPT_MAXFILESIZE_LARGE (3)
+---
+
+# NAME
+
+CURLOPT_IGNORE_CONTENT_LENGTH - ignore content length
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IGNORE_CONTENT_LENGTH,
+ long ignore);
+~~~
+
+# DESCRIPTION
+
+If *ignore* is set to 1L, ignore the Content-Length header in the HTTP
+response and ignore asking for or relying on it for FTP transfers.
+
+This is useful for doing HTTP transfers with ancient web servers which report
+incorrect content length for files over 2 gigabytes. If this option is used,
+curl cannot accurately report progress, and it instead stops the download when
+the server ends the connection.
+
+It is also useful with FTP when for example the file is growing while the
+transfer is in progress which otherwise unconditionally causes libcurl to
+report error.
+
+Only use this option if strictly necessary.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* we know the server is silly, ignore content-length */
+ curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.14.1. Support for FTP added in 7.46.0. This option is not working
+for HTTP when libcurl is built to use the hyper backend.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_INFILESIZE.3 b/docs/libcurl/opts/CURLOPT_INFILESIZE.3
deleted file mode 100644
index 9661c0256..000000000
--- a/docs/libcurl/opts/CURLOPT_INFILESIZE.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_INFILESIZE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_INFILESIZE \- size of the input file to send off
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INFILESIZE, long filesize);
-.fi
-.SH DESCRIPTION
-When uploading a file to a remote site, \fIfilesize\fP should be used to tell
-libcurl what the expected size of the input file is. This value must be passed
-as a long. See also \fICURLOPT_INFILESIZE_LARGE(3)\fP for sending files larger
-than 2GB.
-
-For uploading using SCP, this option or \fICURLOPT_INFILESIZE_LARGE(3)\fP is
-mandatory.
-
-To unset this value again, set it to -1.
-
-Using \fICURLOPT_UPLOAD(3)\fP to a HTTP/1.1 server and this value set to -1,
-makes libcurl do a chunked transfer-encoded upload.
-
-When sending emails using SMTP, this command can be used to specify the
-optional SIZE parameter for the MAIL FROM command.
-
-This option does not limit how much data libcurl actually sends, as that is
-controlled entirely by what the read callback returns, but telling one value
-and sending a different amount may lead to errors.
-.SH DEFAULT
-Unset
-.SH PROTOCOLS
-Many
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- long uploadsize = FILE_SIZE;
-
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/destination.tar.gz");
-
- curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
-
- curl_easy_setopt(curl, CURLOPT_INFILESIZE, uploadsize);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-SMTP support added in 7.23.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_CONTENT_LENGTH_UPLOAD_T (3),
-.BR CURLOPT_INFILESIZE_LARGE (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_INFILESIZE.md b/docs/libcurl/opts/CURLOPT_INFILESIZE.md
new file mode 100644
index 000000000..eab597ff4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_INFILESIZE.md
@@ -0,0 +1,85 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_INFILESIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONTENT_LENGTH_UPLOAD_T (3)
+ - CURLOPT_INFILESIZE_LARGE (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_INFILESIZE - size of the input file to send off
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INFILESIZE, long filesize);
+~~~
+
+# DESCRIPTION
+
+When uploading a file to a remote site, *filesize* should be used to tell
+libcurl what the expected size of the input file is. This value must be passed
+as a long. See also CURLOPT_INFILESIZE_LARGE(3) for sending files larger
+than 2GB.
+
+For uploading using SCP, this option or CURLOPT_INFILESIZE_LARGE(3) is
+mandatory.
+
+To unset this value again, set it to -1.
+
+Using CURLOPT_UPLOAD(3) to an HTTP/1.1 server and this value set to -1, makes
+libcurl do a chunked transfer-encoded upload.
+
+When sending emails using SMTP, this command can be used to specify the
+optional SIZE parameter for the MAIL FROM command.
+
+This option does not limit how much data libcurl actually sends, as that is
+controlled entirely by what the read callback returns, but telling one value
+and sending a different amount may lead to errors.
+
+# DEFAULT
+
+Unset
+
+# PROTOCOLS
+
+Many
+
+# EXAMPLE
+
+~~~c
+
+#define FILE_SIZE 12345L
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ long uploadsize = FILE_SIZE;
+
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "ftp://example.com/destination.tar.gz");
+
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, uploadsize);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+SMTP support added in 7.23.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3 b/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3
deleted file mode 100644
index fedd9438b..000000000
--- a/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_INFILESIZE_LARGE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_INFILESIZE_LARGE \- size of the input file to send off
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INFILESIZE_LARGE,
- curl_off_t filesize);
-.SH DESCRIPTION
-When uploading a file to a remote site, \fIfilesize\fP should be used to tell
-libcurl what the expected size of the input file is. This value must be passed
-as a \fBcurl_off_t\fP.
-
-For uploading using SCP, this option or \fICURLOPT_INFILESIZE(3)\fP is
-mandatory.
-
-To unset this value again, set it to -1.
-
-When sending emails using SMTP, this command can be used to specify the
-optional SIZE parameter for the MAIL FROM command.
-
-This option does not limit how much data libcurl actually sends, as that is
-controlled entirely by what the read callback returns, but telling one value
-and sending a different amount may lead to errors.
-.SH DEFAULT
-Unset
-.SH PROTOCOLS
-Many
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_off_t uploadsize = FILE_SIZE;
-
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/destination.tar.gz");
-
- curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
-
- curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadsize);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-SMTP support added in 7.23.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_CONTENT_LENGTH_UPLOAD_T (3),
-.BR CURLOPT_INFILESIZE (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.md b/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.md
new file mode 100644
index 000000000..5f8a3386f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_INFILESIZE_LARGE.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_INFILESIZE_LARGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CONTENT_LENGTH_UPLOAD_T (3)
+ - CURLOPT_INFILESIZE (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_INFILESIZE_LARGE - size of the input file to send off
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INFILESIZE_LARGE,
+ curl_off_t filesize);
+~~~
+
+# DESCRIPTION
+
+When uploading a file to a remote site, *filesize* should be used to tell
+libcurl what the expected size of the input file is. This value must be passed
+as a **curl_off_t**.
+
+For uploading using SCP, this option or CURLOPT_INFILESIZE(3) is
+mandatory.
+
+To unset this value again, set it to -1.
+
+When sending emails using SMTP, this command can be used to specify the
+optional SIZE parameter for the MAIL FROM command.
+
+This option does not limit how much data libcurl actually sends, as that is
+controlled entirely by what the read callback returns, but telling one value
+and sending a different amount may lead to errors.
+
+# DEFAULT
+
+Unset
+
+# PROTOCOLS
+
+Many
+
+# EXAMPLE
+
+~~~c
+#define FILE_SIZE 123456
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_off_t uploadsize = FILE_SIZE;
+
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "ftp://example.com/destination.tar.gz");
+
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadsize);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+SMTP support added in 7.23.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_INTERFACE.3 b/docs/libcurl/opts/CURLOPT_INTERFACE.3
deleted file mode 100644
index 921a682a0..000000000
--- a/docs/libcurl/opts/CURLOPT_INTERFACE.3
+++ /dev/null
@@ -1,81 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_INTERFACE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_INTERFACE \- source interface for outgoing traffic
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERFACE, char *interface);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter. This sets the \fIinterface\fP name to use as
-outgoing network interface. The name can be an interface name, an IP address,
-or a host name.
-
-If the parameter starts with "if!" then it is treated only as an interface
-name. If the parameter starts with \&"host!" it is treated as either an IP
-address or a hostname.
-
-If "if!" is specified but the parameter does not match an existing interface,
-\fICURLE_INTERFACE_FAILED\fP is returned from the libcurl function used to
-perform the transfer.
-
-libcurl does not support using network interface names for this option on
-Windows.
-
-We strongly advise against specifying the interface with a hostname, as it
-causes libcurl to do a blocking name resolve call to retrieve the IP
-address. That name resolve operation does \fBnot\fP use DNS-over-HTTPS even if
-\fICURLOPT_DOH_URL(3)\fP is set.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL, use whatever the TCP stack finds suitable
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- curl_easy_setopt(curl, CURLOPT_INTERFACE, "eth0");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-The "if!" and "host!" syntax was added in 7.24.0.
-.SH RETURN VALUE
-Returns CURLE_OK on success or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_SOCKOPTFUNCTION (3),
-.BR CURLOPT_TCP_NODELAY (3)
diff --git a/docs/libcurl/opts/CURLOPT_INTERFACE.md b/docs/libcurl/opts/CURLOPT_INTERFACE.md
new file mode 100644
index 000000000..24927fdf8
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_INTERFACE.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_INTERFACE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SOCKOPTFUNCTION (3)
+ - CURLOPT_TCP_NODELAY (3)
+---
+
+# NAME
+
+CURLOPT_INTERFACE - source interface for outgoing traffic
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERFACE, char *interface);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter. This sets the *interface* name to use as
+outgoing network interface. The name can be an interface name, an IP address,
+or a hostname.
+
+If the parameter starts with "if!" then it is treated only as an interface
+name. If the parameter starts with &"host!" it is treated as either an IP
+address or a hostname.
+
+If "if!" is specified but the parameter does not match an existing interface,
+*CURLE_INTERFACE_FAILED* is returned from the libcurl function used to
+perform the transfer.
+
+libcurl does not support using network interface names for this option on
+Windows.
+
+We strongly advise against specifying the interface with a hostname, as it
+causes libcurl to do a blocking name resolve call to retrieve the IP
+address. That name resolve operation does **not** use DNS-over-HTTPS even if
+CURLOPT_DOH_URL(3) is set.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL, use whatever the TCP stack finds suitable
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ curl_easy_setopt(curl, CURLOPT_INTERFACE, "eth0");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+The "if!" and "host!" syntax was added in 7.24.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK on success or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3 b/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3
deleted file mode 100644
index b5a6caaaf..000000000
--- a/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_INTERLEAVEDATA 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_INTERLEAVEDATA \- pointer passed to RTSP interleave callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-This is the userdata \fIpointer\fP that is passed to
-\fICURLOPT_INTERLEAVEFUNCTION(3)\fP when interleaved RTP data is received. If
-the interleave function callback is not set, this pointer is not used
-anywhere.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-static size_t rtp_write(void *ptr, size_t size, size_t nmemb, void *user)
-{
- struct local *l = (struct local *)user;
- /* take care of the packet in 'ptr', then return... */
- return size * nmemb;
-}
-{
- struct local rtp_data;
- curl_easy_setopt(curl, CURLOPT_INTERLEAVEFUNCTION, rtp_write);
- curl_easy_setopt(curl, CURLOPT_INTERLEAVEDATA, &rtp_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_INTERLEAVEFUNCTION (3),
-.BR CURLOPT_RTSP_REQUEST (3)
diff --git a/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.md b/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.md
new file mode 100644
index 000000000..64311f83c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_INTERLEAVEDATA.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_INTERLEAVEDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_INTERLEAVEFUNCTION (3)
+ - CURLOPT_RTSP_REQUEST (3)
+---
+
+# NAME
+
+CURLOPT_INTERLEAVEDATA - pointer passed to RTSP interleave callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+This is the userdata *pointer* that is passed to
+CURLOPT_INTERLEAVEFUNCTION(3) when interleaved RTP data is received. If
+the interleave function callback is not set, this pointer is not used
+anywhere.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+struct local {
+ void *custom;
+};
+static size_t rtp_write(void *ptr, size_t size, size_t nmemb, void *userp)
+{
+ struct local *l = userp;
+ printf("my pointer: %p\n", l->custom);
+ /* take care of the packet in 'ptr', then return... */
+ return size * nmemb;
+}
+
+int main(void)
+{
+ struct local rtp_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_INTERLEAVEFUNCTION, rtp_write);
+ curl_easy_setopt(curl, CURLOPT_INTERLEAVEDATA, &rtp_data);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3 b/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3
deleted file mode 100644
index a117c8821..000000000
--- a/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.3
+++ /dev/null
@@ -1,93 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_INTERLEAVEFUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_INTERLEAVEFUNCTION \- callback for RTSP interleaved data
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-size_t interleave_callback(void *ptr, size_t size, size_t nmemb,
- void *userdata);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEFUNCTION,
- interleave_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl as soon as it has received
-interleaved RTP data. This function gets called for each $ block and therefore
-contains exactly one upper-layer protocol unit (e.g. one RTP packet). Curl
-writes the interleaved header as well as the included data for each call. The
-first byte is always an ASCII dollar sign. The dollar sign is followed by a
-one byte channel identifier and then a 2 byte integer length in network byte
-order. See RFC 2326 Section 10.12 for more information on how RTP interleaving
-behaves. If unset or set to NULL, curl uses the default write function.
-
-Interleaved RTP poses some challenges for the client application. Since the
-stream data is sharing the RTSP control connection, it is critical to service
-the RTP in a timely fashion. If the RTP data is not handled quickly,
-subsequent response processing may become unreasonably delayed and the
-connection may close. The application may use \fICURL_RTSPREQ_RECEIVE\fP to
-service RTP data when no requests are desired. If the application makes a
-request, (e.g. \fICURL_RTSPREQ_PAUSE\fP) then the response handler processes
-any pending RTP data before marking the request as finished.
-
-The \fICURLOPT_INTERLEAVEDATA(3)\fP is passed in the \fIuserdata\fP argument in
-the callback.
-
-Your callback should return the number of bytes actually taken care of. If
-that amount differs from the amount passed to your callback function, it
-signals an error condition to the library. This causes the transfer to abort
-and the libcurl function used returns \fICURLE_WRITE_ERROR\fP.
-
-You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
-.SH DEFAULT
-NULL, the interleave data is then passed to the regular write function:
-\fICURLOPT_WRITEFUNCTION(3)\fP.
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-static size_t rtp_write(void *ptr, size_t size, size_t nmemb, void *user)
-{
- struct local *l = (struct local *)user;
- /* take care of the packet in 'ptr', then return... */
- return size * nmemb;
-}
-{
- struct local rtp_data;
- curl_easy_setopt(curl, CURLOPT_INTERLEAVEFUNCTION, rtp_write);
- curl_easy_setopt(curl, CURLOPT_INTERLEAVEDATA, &rtp_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_INTERLEAVEDATA (3),
-.BR CURLOPT_RTSP_REQUEST (3)
diff --git a/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.md b/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.md
new file mode 100644
index 000000000..5f8e999df
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_INTERLEAVEFUNCTION.md
@@ -0,0 +1,102 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_INTERLEAVEFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_INTERLEAVEDATA (3)
+ - CURLOPT_RTSP_REQUEST (3)
+---
+
+# NAME
+
+CURLOPT_INTERLEAVEFUNCTION - callback for RTSP interleaved data
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+size_t interleave_callback(void *ptr, size_t size, size_t nmemb,
+ void *userdata);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEFUNCTION,
+ interleave_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl as soon as it has received
+interleaved RTP data. This function gets called for each $ block and therefore
+contains exactly one upper-layer protocol unit (e.g. one RTP packet). Curl
+writes the interleaved header as well as the included data for each call. The
+first byte is always an ASCII dollar sign. The dollar sign is followed by a
+one byte channel identifier and then a 2 byte integer length in network byte
+order. See RFC 2326 Section 10.12 for more information on how RTP interleaving
+behaves. If unset or set to NULL, curl uses the default write function.
+
+Interleaved RTP poses some challenges for the client application. Since the
+stream data is sharing the RTSP control connection, it is critical to service
+the RTP in a timely fashion. If the RTP data is not handled quickly,
+subsequent response processing may become unreasonably delayed and the
+connection may close. The application may use *CURL_RTSPREQ_RECEIVE* to
+service RTP data when no requests are desired. If the application makes a
+request, (e.g. *CURL_RTSPREQ_PAUSE*) then the response handler processes
+any pending RTP data before marking the request as finished.
+
+The CURLOPT_INTERLEAVEDATA(3) is passed in the *userdata* argument in
+the callback.
+
+Your callback should return the number of bytes actually taken care of. If
+that amount differs from the amount passed to your callback function, it
+signals an error condition to the library. This causes the transfer to abort
+and the libcurl function used returns *CURLE_WRITE_ERROR*.
+
+You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
+
+# DEFAULT
+
+NULL, the interleave data is then passed to the regular write function:
+CURLOPT_WRITEFUNCTION(3).
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+struct local {
+ void *custom;
+};
+
+static size_t rtp_write(void *ptr, size_t size, size_t nmemb, void *userp)
+{
+ struct local *l = userp;
+ printf("our ptr: %p\n", l->custom);
+ /* take care of the packet in 'ptr', then return... */
+ return size * nmemb;
+}
+
+int main(void)
+{
+ struct local rtp_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_INTERLEAVEFUNCTION, rtp_write);
+ curl_easy_setopt(curl, CURLOPT_INTERLEAVEDATA, &rtp_data);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_IOCTLDATA.3 b/docs/libcurl/opts/CURLOPT_IOCTLDATA.3
deleted file mode 100644
index 41de13c9b..000000000
--- a/docs/libcurl/opts/CURLOPT_IOCTLDATA.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_IOCTLDATA 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_IOCTLDATA \- pointer passed to I/O callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IOCTLDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass the \fIpointer\fP that is untouched by libcurl and passed as the 3rd
-argument in the ioctl callback set with \fICURLOPT_IOCTLFUNCTION(3)\fP.
-.SH DEFAULT
-By default, the value of this parameter is NULL.
-.SH PROTOCOLS
-Used with HTTP
-.SH EXAMPLE
-.nf
-static curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp)
-{
- struct data *io = (struct data *)clientp;
- if(cmd == CURLIOCMD_RESTARTREAD) {
- lseek(fd, 0, SEEK_SET);
- current_offset = 0;
- return CURLIOE_OK;
- }
- return CURLIOE_UNKNOWNCMD;
-}
-{
- struct data ioctl_data;
- curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_callback);
- curl_easy_setopt(curl, CURLOPT_IOCTLDATA, &ioctl_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.12.3. Deprecated since 7.18.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_IOCTLFUNCTION (3),
-.BR CURLOPT_SEEKFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_IOCTLDATA.md b/docs/libcurl/opts/CURLOPT_IOCTLDATA.md
new file mode 100644
index 000000000..2490fbc7f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_IOCTLDATA.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_IOCTLDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_IOCTLFUNCTION (3)
+ - CURLOPT_SEEKFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_IOCTLDATA - pointer passed to I/O callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IOCTLDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass the *pointer* that is untouched by libcurl and passed as the 3rd
+argument in the ioctl callback set with CURLOPT_IOCTLFUNCTION(3).
+
+# DEFAULT
+
+By default, the value of this parameter is NULL.
+
+# PROTOCOLS
+
+Used with HTTP
+
+# EXAMPLE
+
+~~~c
+#include <unistd.h> /* for lseek */
+
+struct data {
+ int fd; /* our file descriptor */
+};
+
+static curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp)
+{
+ struct data *io = (struct data *)clientp;
+ if(cmd == CURLIOCMD_RESTARTREAD) {
+ lseek(io->fd, 0, SEEK_SET);
+ return CURLIOE_OK;
+ }
+ return CURLIOE_UNKNOWNCMD;
+}
+int main(void)
+{
+ struct data ioctl_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_callback);
+ curl_easy_setopt(curl, CURLOPT_IOCTLDATA, &ioctl_data);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.12.3. Deprecated since 7.18.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3 b/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3
deleted file mode 100644
index 5eb2a17c6..000000000
--- a/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.3
+++ /dev/null
@@ -1,95 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_IOCTLFUNCTION 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_IOCTLFUNCTION \- callback for I/O operations
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef enum {
- CURLIOE_OK, /* I/O operation successful */
- CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
- CURLIOE_FAILRESTART, /* failed to restart the read */
- CURLIOE_LAST /* never use */
-} curlioerr;
-
-typedef enum {
- CURLIOCMD_NOP, /* no operation */
- CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
- CURLIOCMD_LAST /* never use */
-} curliocmd;
-
-curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IOCTLFUNCTION, ioctl_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl when something special
-I/O-related needs to be done that the library cannot do by itself. For now,
-rewinding the read data stream is the only action it can request. The
-rewinding of the read data stream may be necessary when doing an HTTP PUT or
-POST with a multi-pass authentication method.
-
-The callback MUST return \fICURLIOE_UNKNOWNCMD\fP if the input \fIcmd\fP is
-not \fICURLIOCMD_RESTARTREAD\fP.
-
-The \fIclientp\fP argument to the callback is set with the
-\fICURLOPT_IOCTLDATA(3)\fP option.
-
-This option is deprecated! Do not use it. Use \fICURLOPT_SEEKFUNCTION(3)\fP
-instead to provide seeking! If \fICURLOPT_SEEKFUNCTION(3)\fP is set, this
-parameter is ignored when seeking.
-.SH DEFAULT
-By default, this parameter is set to NULL. Not used.
-.SH PROTOCOLS
-Used with HTTP
-.SH EXAMPLE
-.nf
-static curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp)
-{
- struct data *io = (struct data *)clientp;
- if(cmd == CURLIOCMD_RESTARTREAD) {
- lseek(fd, 0, SEEK_SET);
- current_offset = 0;
- return CURLIOE_OK;
- }
- return CURLIOE_UNKNOWNCMD;
-}
-{
- struct data ioctl_data;
- curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_callback);
- curl_easy_setopt(curl, CURLOPT_IOCTLDATA, &ioctl_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.12.3. Deprecated since 7.18.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_IOCTLDATA (3),
-.BR CURLOPT_SEEKFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.md b/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.md
new file mode 100644
index 000000000..8804ae578
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_IOCTLFUNCTION.md
@@ -0,0 +1,103 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_IOCTLFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_IOCTLDATA (3)
+ - CURLOPT_SEEKFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_IOCTLFUNCTION - callback for I/O operations
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+typedef enum {
+ CURLIOE_OK, /* I/O operation successful */
+ CURLIOE_UNKNOWNCMD, /* command was unknown to callback */
+ CURLIOE_FAILRESTART, /* failed to restart the read */
+ CURLIOE_LAST /* never use */
+} curlioerr;
+
+typedef enum {
+ CURLIOCMD_NOP, /* no operation */
+ CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
+ CURLIOCMD_LAST /* never use */
+} curliocmd;
+
+curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IOCTLFUNCTION, ioctl_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl when something special
+I/O-related needs to be done that the library cannot do by itself. For now,
+rewinding the read data stream is the only action it can request. The
+rewinding of the read data stream may be necessary when doing an HTTP PUT or
+POST with a multi-pass authentication method.
+
+The callback MUST return *CURLIOE_UNKNOWNCMD* if the input *cmd* is
+not *CURLIOCMD_RESTARTREAD*.
+
+The *clientp* argument to the callback is set with the
+CURLOPT_IOCTLDATA(3) option.
+
+**This option is deprecated**. Do not use it. Use CURLOPT_SEEKFUNCTION(3)
+instead to provide seeking! If CURLOPT_SEEKFUNCTION(3) is set, this
+parameter is ignored when seeking.
+
+# DEFAULT
+
+By default, this parameter is set to NULL. Not used.
+
+# PROTOCOLS
+
+Used with HTTP
+
+# EXAMPLE
+
+~~~c
+#include <unistd.h> /* for lseek */
+
+struct data {
+ int fd; /* our file descriptor */
+};
+
+static curlioerr ioctl_callback(CURL *handle, int cmd, void *clientp)
+{
+ struct data *io = (struct data *)clientp;
+ if(cmd == CURLIOCMD_RESTARTREAD) {
+ lseek(io->fd, 0, SEEK_SET);
+ return CURLIOE_OK;
+ }
+ return CURLIOE_UNKNOWNCMD;
+}
+int main(void)
+{
+ struct data ioctl_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_callback);
+ curl_easy_setopt(curl, CURLOPT_IOCTLDATA, &ioctl_data);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.12.3. Deprecated since 7.18.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_IPRESOLVE.3 b/docs/libcurl/opts/CURLOPT_IPRESOLVE.3
deleted file mode 100644
index c5970686f..000000000
--- a/docs/libcurl/opts/CURLOPT_IPRESOLVE.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_IPRESOLVE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_IPRESOLVE \- IP protocol version to use
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IPRESOLVE, long resolve);
-.fi
-.SH DESCRIPTION
-Allows an application to select what kind of IP addresses to use when
-establishing a connection or choosing one from the connection pool. This is
-interesting when using host names that resolve to more than one IP family.
-
-If the URL provided for a transfer contains a numerical IP version as a host
-name, this option does not override or prohibit libcurl from using that IP
-version.
-
-Available values for this option are:
-.IP CURL_IPRESOLVE_WHATEVER
-Default, can use addresses of all IP versions that your system allows.
-.IP CURL_IPRESOLVE_V4
-Uses only IPv4 addresses.
-.IP CURL_IPRESOLVE_V6
-Uses only IPv6 addresses.
-.SH DEFAULT
-CURL_IPRESOLVE_WHATEVER
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- /* of all addresses example.com resolves to, only IPv6 ones are used */
- curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_HTTP_VERSION (3),
-.BR CURLOPT_RESOLVE (3),
-.BR CURLOPT_SSLVERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_IPRESOLVE.md b/docs/libcurl/opts/CURLOPT_IPRESOLVE.md
new file mode 100644
index 000000000..7d06405ec
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_IPRESOLVE.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_IPRESOLVE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTP_VERSION (3)
+ - CURLOPT_RESOLVE (3)
+ - CURLOPT_SSLVERSION (3)
+---
+
+# NAME
+
+CURLOPT_IPRESOLVE - IP protocol version to use
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_IPRESOLVE, long resolve);
+~~~
+
+# DESCRIPTION
+
+Allows an application to select what kind of IP addresses to use when
+establishing a connection or choosing one from the connection pool. This is
+interesting when using host names that resolve to more than one IP family.
+
+If the URL provided for a transfer contains a numerical IP version as a host
+name, this option does not override or prohibit libcurl from using that IP
+version.
+
+Available values for this option are:
+
+## CURL_IPRESOLVE_WHATEVER
+
+Default, can use addresses of all IP versions that your system allows.
+
+## CURL_IPRESOLVE_V4
+
+Uses only IPv4 addresses.
+
+## CURL_IPRESOLVE_V6
+
+Uses only IPv6 addresses.
+
+# DEFAULT
+
+CURL_IPRESOLVE_WHATEVER
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ /* of all addresses example.com resolves to, only IPv6 ones are used */
+ curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT.3 b/docs/libcurl/opts/CURLOPT_ISSUERCERT.3
deleted file mode 100644
index 9ac3d2eef..000000000
--- a/docs/libcurl/opts/CURLOPT_ISSUERCERT.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ISSUERCERT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_ISSUERCERT \- issuer SSL certificate filename
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT, char *file);
-.fi
-.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 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_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). (Added in 7.19.0)
-
-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/");
- curl_easy_setopt(curl, CURLOPT_ISSUERCERT, "/etc/certs/cacert.pem");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If built TLS enabled
-.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_CRLFILE (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT.md b/docs/libcurl/opts/CURLOPT_ISSUERCERT.md
new file mode 100644
index 000000000..9b35d5d79
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ISSUERCERT.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ISSUERCERT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CRLFILE (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_ISSUERCERT - issuer SSL certificate filename
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT, char *file);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to a null-terminated string naming a *file* 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
+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
+CURLOPT_SSL_VERIFYPEER(3) 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 (CURLOPT_SSL_VERIFYPEER(3)
+has to be set too for the check to fail). (Added in 7.19.0)
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_ISSUERCERT, "/etc/certs/cacert.pem");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built TLS enabled
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3
deleted file mode 100644
index f9b56057c..000000000
--- a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_ISSUERCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
-.SH NAME
-CURLOPT_ISSUERCERT_BLOB \- issuer SSL certificate from memory blob
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT_BLOB,
- struct curl_blob *stblob);
-.fi
-.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 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),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md
new file mode 100644
index 000000000..4832f4125
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md
@@ -0,0 +1,92 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_ISSUERCERT_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CRLFILE (3)
+ - CURLOPT_ISSUERCERT (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_ISSUERCERT_BLOB - issuer SSL certificate from memory blob
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT_BLOB,
+ struct curl_blob *stblob);
+~~~
+
+# 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
+CURLOPT_SSL_VERIFYPEER(3) 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 (CURLOPT_SSL_VERIFYPEER(3)
+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 CURLOPT_ISSUERCERT(3) which instead
+expects a filename as input.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+
+extern char *certificateData;
+extern size_t filesize;
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.71.0. This option is supported by the OpenSSL backends.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3 b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3
deleted file mode 100644
index b25af4679..000000000
--- a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_KEEP_SENDING_ON_ERROR 3 "22 Sep 2016" libcurl libcurl
-.SH NAME
-CURLOPT_KEEP_SENDING_ON_ERROR \- keep sending on early HTTP response >= 300
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEEP_SENDING_ON_ERROR,
- long keep_sending);
-.fi
-.SH DESCRIPTION
-A long parameter set to 1 tells the library to keep sending the request body
-if the HTTP code returned is equal to or larger than 300. The default action
-would be to stop sending and close the stream or connection.
-
-This option is suitable for manual NTLM authentication, i.e. if an application
-does not use \fICURLOPT_HTTPAUTH(3)\fP, but instead sets "Authorization: NTLM ..."
-headers manually using \fICURLOPT_HTTPHEADER(3)\fP.
-
-Most applications do not need this option.
-.SH DEFAULT
-0, stop sending on error
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "sending data");
- curl_easy_setopt(curl, CURLOPT_KEEP_SENDING_ON_ERROR, 1L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP. Added in 7.51.0.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_RESPONSE_CODE (3),
-.BR CURLOPT_FAILONERROR (3),
-.BR CURLOPT_HTTPHEADER (3)
diff --git a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md
new file mode 100644
index 000000000..090a8fc2d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_KEEP_SENDING_ON_ERROR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RESPONSE_CODE (3)
+ - CURLOPT_FAILONERROR (3)
+ - CURLOPT_HTTPHEADER (3)
+---
+
+# NAME
+
+CURLOPT_KEEP_SENDING_ON_ERROR - keep sending on early HTTP response >= 300
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEEP_SENDING_ON_ERROR,
+ long keep_sending);
+~~~
+
+# DESCRIPTION
+
+A long parameter set to 1 tells the library to keep sending the request body
+if the HTTP code returned is equal to or larger than 300. The default action
+would be to stop sending and close the stream or connection.
+
+This option is suitable for manual NTLM authentication, i.e. if an application
+does not use CURLOPT_HTTPAUTH(3), but instead sets "Authorization: NTLM ..."
+headers manually using CURLOPT_HTTPHEADER(3).
+
+Most applications do not need this option.
+
+# DEFAULT
+
+0, stop sending on error
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "sending data");
+ curl_easy_setopt(curl, CURLOPT_KEEP_SENDING_ON_ERROR, 1L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP. Added in 7.51.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_KEYPASSWD.3 b/docs/libcurl/opts/CURLOPT_KEYPASSWD.3
deleted file mode 100644
index 4d69a3c88..000000000
--- a/docs/libcurl/opts/CURLOPT_KEYPASSWD.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_KEYPASSWD 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_KEYPASSWD \- passphrase to private key
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEYPASSWD, char *pwd);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter. It is used as the
-password required to use the \fICURLOPT_SSLKEY(3)\fP or
-\fICURLOPT_SSH_PRIVATE_KEYFILE(3)\fP private key. You never need a pass
-phrase to load a certificate but you need one to load your private key.
-
-The application does not have to keep the string around after setting this
-option.
-.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) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "superman");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was known as CURLOPT_SSLKEYPASSWD up to 7.16.4 and
-CURLOPT_SSLCERTPASSWD up to 7.9.2.
-.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_SSH_PRIVATE_KEYFILE (3),
-.BR CURLOPT_SSLKEY (3)
diff --git a/docs/libcurl/opts/CURLOPT_KEYPASSWD.md b/docs/libcurl/opts/CURLOPT_KEYPASSWD.md
new file mode 100644
index 000000000..7407f0939
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_KEYPASSWD.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_KEYPASSWD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_PRIVATE_KEYFILE (3)
+ - CURLOPT_SSLKEY (3)
+---
+
+# NAME
+
+CURLOPT_KEYPASSWD - passphrase to private key
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEYPASSWD, char *pwd);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. It is used as the
+password required to use the CURLOPT_SSLKEY(3) or
+CURLOPT_SSH_PRIVATE_KEYFILE(3) private key. You never need a pass phrase to
+load a certificate but you need one to load your private key.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "superman");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was known as CURLOPT_SSLKEYPASSWD up to 7.16.4 and
+CURLOPT_SSLCERTPASSWD up to 7.9.2.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_KRBLEVEL.3 b/docs/libcurl/opts/CURLOPT_KRBLEVEL.3
deleted file mode 100644
index 9a1f4ae92..000000000
--- a/docs/libcurl/opts/CURLOPT_KRBLEVEL.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_KRBLEVEL 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_KRBLEVEL \- FTP kerberos security level
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KRBLEVEL, char *level);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter. Set the kerberos security level for FTP; this also
-enables kerberos awareness. This is a string that should match one of the
-following: \&'clear', \&'safe', \&'confidential' or \&'private'. If the string
-is set but does not match one of these, 'private' is used. Set the string to
-NULL to disable kerberos support for FTP.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_KRBLEVEL, "private");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was known as CURLOPT_KRB4LEVEL up to 7.16.3
-.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_KRBLEVEL (3),
-.BR CURLOPT_USE_SSL (3)
diff --git a/docs/libcurl/opts/CURLOPT_KRBLEVEL.md b/docs/libcurl/opts/CURLOPT_KRBLEVEL.md
new file mode 100644
index 000000000..cb8e27689
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_KRBLEVEL.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_KRBLEVEL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_KRBLEVEL (3)
+ - CURLOPT_USE_SSL (3)
+---
+
+# NAME
+
+CURLOPT_KRBLEVEL - FTP kerberos security level
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KRBLEVEL, char *level);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter. Set the kerberos security level for FTP;
+this also enables kerberos awareness. This is a string that should match one
+of the following: &'clear', &'safe', &'confidential' or &'private'. If the
+string is set but does not match one of these, 'private' is used. Set the
+string to NULL to disable kerberos support for FTP.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_KRBLEVEL, "private");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was known as CURLOPT_KRB4LEVEL up to 7.16.3
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORT.3 b/docs/libcurl/opts/CURLOPT_LOCALPORT.3
deleted file mode 100644
index 267a1c87a..000000000
--- a/docs/libcurl/opts/CURLOPT_LOCALPORT.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_LOCALPORT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_LOCALPORT \- local port number to use for socket
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORT, long port);
-.fi
-.SH DESCRIPTION
-Pass a long. This sets the local port number of the socket used for the
-connection. This can be used in combination with \fICURLOPT_INTERFACE(3)\fP
-and you are recommended to use \fICURLOPT_LOCALPORTRANGE(3)\fP as well when
-this option is set. Valid port numbers are 1 - 65535.
-.SH DEFAULT
-0, disabled - use whatever the system thinks is fine
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_LOCALPORT, 49152L);
- /* and try 20 more ports following that */
- curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, 20L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.2
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLINFO_LOCAL_PORT (3),
-.BR CURLOPT_INTERFACE (3),
-.BR CURLOPT_LOCALPORTRANGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORT.md b/docs/libcurl/opts/CURLOPT_LOCALPORT.md
new file mode 100644
index 000000000..25a21c15e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_LOCALPORT.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_LOCALPORT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_LOCAL_PORT (3)
+ - CURLOPT_INTERFACE (3)
+ - CURLOPT_LOCALPORTRANGE (3)
+---
+
+# NAME
+
+CURLOPT_LOCALPORT - local port number to use for socket
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORT, long port);
+~~~
+
+# DESCRIPTION
+
+Pass a long. This sets the local port number of the socket used for the
+connection. This can be used in combination with CURLOPT_INTERFACE(3)
+and you are recommended to use CURLOPT_LOCALPORTRANGE(3) as well when
+this option is set. Valid port numbers are 1 - 65535.
+
+# DEFAULT
+
+0, disabled - use whatever the system thinks is fine
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_LOCALPORT, 49152L);
+ /* and try 20 more ports following that */
+ curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, 20L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.2
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3 b/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3
deleted file mode 100644
index 1e54f43ed..000000000
--- a/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_LOCALPORTRANGE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_LOCALPORTRANGE \- number of additional local ports to try
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORTRANGE,
- long range);
-.fi
-.SH DESCRIPTION
-Pass a long. The \fIrange\fP argument is the number of attempts libcurl makes
-to find a working local port number. It starts with the given
-\fICURLOPT_LOCALPORT(3)\fP and adds one to the number for each retry. Setting
-this option to 1 or below makes libcurl only do one try for the exact port
-number. Port numbers by nature are scarce resources that are busy at times so
-setting this value to something too low might cause unnecessary connection
-setup failures.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_LOCALPORT, 49152L);
- /* and try 20 more ports following that */
- curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, 20L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.2
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_INTERFACE (3),
-.BR CURLOPT_LOCALPORT (3)
diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md b/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md
new file mode 100644
index 000000000..520020790
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_LOCALPORTRANGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_INTERFACE (3)
+ - CURLOPT_LOCALPORT (3)
+---
+
+# NAME
+
+CURLOPT_LOCALPORTRANGE - number of additional local ports to try
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOCALPORTRANGE,
+ long range);
+~~~
+
+# DESCRIPTION
+
+Pass a long. The *range* argument is the number of attempts libcurl makes
+to find a working local port number. It starts with the given
+CURLOPT_LOCALPORT(3) and adds one to the number for each retry. Setting
+this option to 1 or below makes libcurl only do one try for the exact port
+number. Port numbers by nature are scarce resources that are busy at times so
+setting this value to something too low might cause unnecessary connection
+setup failures.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_LOCALPORT, 49152L);
+ /* and try 20 more ports following that */
+ curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, 20L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.2
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3
deleted file mode 100644
index aacf18695..000000000
--- a/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_LOGIN_OPTIONS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_LOGIN_OPTIONS \- login options
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOGIN_OPTIONS, char *options);
-.fi
-.SH DESCRIPTION
-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 RFC 2384, RFC 5092 and
-the IETF draft \fBdraft-earhart-url-smtp-00.txt\fP.
-
-\fICURLOPT_LOGIN_OPTIONS(3)\fP can be used to set protocol specific login
-options, such as the preferred authentication mechanism via "AUTH=NTLM" or
-"AUTH=*", and should be used in conjunction with the \fICURLOPT_USERNAME(3)\fP
-option.
-
-Since 8.2.0, IMAP supports the login option "AUTH=+LOGIN". With this option,
-curl uses the plain (not SASL) LOGIN IMAP command even if the server
-advertises SASL authentication. Care should be taken in using this option, as
-it sends your password in plain text. This does not work if the IMAP server
-disables the plain LOGIN (e.g. to prevent password snooping).
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Only IMAP, LDAP, POP3 and SMTP support login options.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
- curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, "AUTH=*");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.34.0. Support for OpenLDAP added in 7.82.0.
-.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_PASSWORD (3),
-.BR CURLOPT_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md b/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md
new file mode 100644
index 000000000..a57b44690
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_LOGIN_OPTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_LOGIN_OPTIONS - login options
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOGIN_OPTIONS, char *options);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be pointing to the
+null-terminated *options* string to use for the transfer.
+
+For more information about the login options please see RFC 2384, RFC 5092 and
+the IETF draft **draft-earhart-url-smtp-00.txt**.
+
+CURLOPT_LOGIN_OPTIONS(3) can be used to set protocol specific login options,
+such as the preferred authentication mechanism via "AUTH=NTLM" or "AUTH=*",
+and should be used in conjunction with the CURLOPT_USERNAME(3) option.
+
+Since 8.2.0, IMAP supports the login option "AUTH=+LOGIN". With this option,
+curl uses the plain (not SASL) LOGIN IMAP command even if the server
+advertises SASL authentication. Care should be taken in using this option, as
+it sends your password in plain text. This does not work if the IMAP server
+disables the plain LOGIN (e.g. to prevent password snooping).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Only IMAP, LDAP, POP3 and SMTP support login options.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, "AUTH=*");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.34.0. Support for OpenLDAP added in 7.82.0.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3 b/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3
deleted file mode 100644
index a28ec6bc3..000000000
--- a/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_LOW_SPEED_LIMIT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_LOW_SPEED_LIMIT \- low speed limit in bytes per second
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_LIMIT,
- long speedlimit);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter. It contains the average transfer speed in bytes per
-second that the transfer should be below during
-\fICURLOPT_LOW_SPEED_TIME(3)\fP seconds for libcurl to consider it to be too
-slow and abort.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, url);
- /* abort if slower than 30 bytes/sec during 60 seconds */
- curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60L);
- curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 30L);
- res = curl_easy_perform(curl);
- if(CURLE_OPERATION_TIMEDOUT == res) {
- printf("Timeout!\\n");
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_LOW_SPEED_TIME (3),
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3),
-.BR CURLOPT_MAX_SEND_SPEED_LARGE (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md b/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md
new file mode 100644
index 000000000..99df9faed
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_LOW_SPEED_LIMIT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_LOW_SPEED_TIME (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+ - CURLOPT_MAX_SEND_SPEED_LARGE (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_LOW_SPEED_LIMIT - low speed limit in bytes per second
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_LIMIT,
+ long speedlimit);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter. It contains the average transfer speed in bytes per
+second that the transfer should be below during
+CURLOPT_LOW_SPEED_TIME(3) seconds for libcurl to consider it to be too
+slow and abort.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ /* abort if slower than 30 bytes/sec during 60 seconds */
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60L);
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 30L);
+ res = curl_easy_perform(curl);
+ if(CURLE_OPERATION_TIMEDOUT == res) {
+ printf("Timeout!\n");
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3 b/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3
deleted file mode 100644
index 013cc916d..000000000
--- a/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_LOW_SPEED_TIME 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_LOW_SPEED_TIME \- low speed limit time period
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_TIME,
- long speedtime);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter. It contains the time in number seconds that the
-transfer speed should be below the \fICURLOPT_LOW_SPEED_LIMIT(3)\fP for the
-library to consider it too slow and abort.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, url);
- /* abort if slower than 30 bytes/sec during 60 seconds */
- curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60L);
- curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 30L);
- res = curl_easy_perform(curl);
- if(CURLE_OPERATION_TIMEDOUT == res) {
- printf("Timeout!\\n");
- }
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md b/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md
new file mode 100644
index 000000000..a3a9ef1ff
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_LOW_SPEED_TIME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_LOW_SPEED_TIME - low speed limit time period
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOW_SPEED_TIME,
+ long speedtime);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter. It contains the time in number seconds that the
+transfer speed should be below the CURLOPT_LOW_SPEED_LIMIT(3) for the
+library to consider it too slow and abort.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ /* abort if slower than 30 bytes/sec during 60 seconds */
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 60L);
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 30L);
+ res = curl_easy_perform(curl);
+ if(CURLE_OPERATION_TIMEDOUT == res) {
+ printf("Timeout!\n");
+ }
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3 b/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3
deleted file mode 100644
index 403c1b6b7..000000000
--- a/docs/libcurl/opts/CURLOPT_MAIL_AUTH.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAIL_AUTH 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAIL_AUTH \- SMTP authentication address
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_AUTH, char *auth);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter. This is used to
-specify the authentication address (identity) of a submitted message that is
-being relayed to another server.
-
-This optional parameter allows co-operating agents in a trusted environment to
-communicate the authentication of individual messages and should only be used
-by the application program, using libcurl, if the application is itself a mail
-server acting in such an environment. If the application is operating as such
-and the AUTH address is not known or is invalid, then an empty string should
-be used for this parameter.
-
-Unlike \fICURLOPT_MAIL_FROM(3)\fP and \fICURLOPT_MAIL_RCPT(3)\fP, the address
-should not be specified within a pair of angled brackets (<>). However, if an
-empty string is used then a pair of brackets are sent by libcurl as required
-by RFC 2554.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
- curl_easy_setopt(curl, CURLOPT_MAIL_AUTH, "<secret@cave>");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.25.0
-.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_MAIL_FROM (3),
-.BR CURLOPT_MAIL_RCPT (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_AUTH.md b/docs/libcurl/opts/CURLOPT_MAIL_AUTH.md
new file mode 100644
index 000000000..a5dbc7d79
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAIL_AUTH.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAIL_AUTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAIL_FROM (3)
+ - CURLOPT_MAIL_RCPT (3)
+---
+
+# NAME
+
+CURLOPT_MAIL_AUTH - SMTP authentication address
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_AUTH, char *auth);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. This is used to
+specify the authentication address (identity) of a submitted message that is
+being relayed to another server.
+
+This optional parameter allows co-operating agents in a trusted environment to
+communicate the authentication of individual messages and should only be used
+by the application program, using libcurl, if the application is itself a mail
+server acting in such an environment. If the application is operating as such
+and the AUTH address is not known or is invalid, then an empty string should
+be used for this parameter.
+
+Unlike CURLOPT_MAIL_FROM(3) and CURLOPT_MAIL_RCPT(3), the address
+should not be specified within a pair of angled brackets (<>). However, if an
+empty string is used then a pair of brackets are sent by libcurl as required
+by RFC 2554.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_MAIL_AUTH, "<secret@cave>");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.25.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_FROM.3 b/docs/libcurl/opts/CURLOPT_MAIL_FROM.3
deleted file mode 100644
index b0b130ea8..000000000
--- a/docs/libcurl/opts/CURLOPT_MAIL_FROM.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAIL_FROM 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAIL_FROM \- SMTP sender address
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_FROM, char *from);
-.fi
-.SH DESCRIPTION
-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 (<>)
-around it, which if not specified are added automatically.
-
-If this parameter is not specified then an empty address is sent to the SMTP
-server which might cause the email to be rejected.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-blank
-.SH PROTOCOLS
-SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
- curl_easy_setopt(curl, CURLOPT_MAIL_FROM, "president@example.com");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.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_MAIL_AUTH (3),
-.BR CURLOPT_MAIL_RCPT (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_FROM.md b/docs/libcurl/opts/CURLOPT_MAIL_FROM.md
new file mode 100644
index 000000000..c4984b056
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAIL_FROM.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAIL_FROM
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAIL_AUTH (3)
+ - CURLOPT_MAIL_RCPT (3)
+---
+
+# NAME
+
+CURLOPT_MAIL_FROM - SMTP sender address
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_FROM, char *from);
+~~~
+
+# DESCRIPTION
+
+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 (<>)
+around it, which if not specified are added automatically.
+
+If this parameter is not specified then an empty address is sent to the SMTP
+server which might cause the email to be rejected.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_MAIL_FROM, "president@example.com");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3 b/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3
deleted file mode 100644
index 60a68dc04..000000000
--- a/docs/libcurl/opts/CURLOPT_MAIL_RCPT.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAIL_RCPT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAIL_RCPT \- list of SMTP mail recipients
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_RCPT,
- struct curl_slist *rcpts);
-.SH DESCRIPTION
-Pass a pointer to a linked list of recipients to pass to the server in your
-SMTP mail request. The linked list should be a fully valid list of
-\fBstruct curl_slist\fP structs properly filled in. Use
-\fIcurl_slist_append(3)\fP to create the list and \fIcurl_slist_free_all(3)\fP
-to clean up an entire list.
-
-When performing a mail transfer, each recipient should be specified within a
-pair of angled brackets (<>), however, should you not use an angled bracket as
-the first character libcurl assumes you provided a single email address and
-encloses that address within brackets for you.
-
-When performing an address verification (\fBVRFY\fP command), each recipient
-should be specified as the user name or user name and domain (as per Section
-3.5 of RFC 5321).
-
-When performing a mailing list expand (\fBEXPN\fP command), each recipient
-should be specified using the mailing list name, such as "Friends" or
-"London-Office".
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- struct curl_slist *list;
- list = curl_slist_append(NULL, "root@localhost");
- list = curl_slist_append(list, "person@example.com");
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
- curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, list);
- ret = curl_easy_perform(curl);
- curl_slist_free_all(list);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0. The \fBVRFY\fP and \fBEXPN\fP logic was added in 7.34.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_MAIL_AUTH (3),
-.BR CURLOPT_MAIL_FROM (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT.md b/docs/libcurl/opts/CURLOPT_MAIL_RCPT.md
new file mode 100644
index 000000000..ce57074f0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAIL_RCPT.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAIL_RCPT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAIL_AUTH (3)
+ - CURLOPT_MAIL_FROM (3)
+---
+
+# NAME
+
+CURLOPT_MAIL_RCPT - list of SMTP mail recipients
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_RCPT,
+ struct curl_slist *rcpts);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of recipients to pass to the server in your
+SMTP mail request. The linked list should be a fully valid list of
+**struct curl_slist** structs properly filled in. Use
+curl_slist_append(3) to create the list and curl_slist_free_all(3)
+to clean up an entire list.
+
+When performing a mail transfer, each recipient should be specified within a
+pair of angled brackets (<>), however, should you not use an angled bracket as
+the first character libcurl assumes you provided a single email address and
+encloses that address within brackets for you.
+
+When performing an address verification (**VRFY** command), each recipient
+should be specified as the user name or user name and domain (as per Section
+3.5 of RFC 5321).
+
+When performing a mailing list expand (**EXPN** command), each recipient
+should be specified using the mailing list name, such as "Friends" or
+"London-Office".
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ struct curl_slist *list;
+ list = curl_slist_append(NULL, "root@localhost");
+ list = curl_slist_append(list, "person@example.com");
+ curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, list);
+ res = curl_easy_perform(curl);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0. The **VRFY** and **EXPN** logic was added in 7.34.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.3 b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.3
deleted file mode 100644
index 8d8c9c7bb..000000000
--- a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAIL_RCPT_ALLOWFAILS 3 "16 Jan 2020" libcurl libcurl
-.SH NAME
-CURLOPT_MAIL_RCPT_ALLOWFAILS \- allow RCPT TO command to fail for some recipients
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_RCPT_ALLOWFAILS,
- long allow);
-.SH DESCRIPTION
-If \fIallow\fP is set to 1L, allow RCPT TO command to fail for some recipients.
-
-When sending data to multiple recipients, by default curl aborts the SMTP
-conversation if either one of the recipients causes the RCPT TO command to
-return an error.
-
-The default behavior can be changed by setting \fIallow\fP to 1L which makes
-libcurl ignore errors for individual recipients and proceed with the remaining
-accepted recipients.
-
-If all recipients trigger RCPT TO failures and this flag is specified, curl
-aborts the SMTP conversation and returns the error received from to the last
-RCPT TO command.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- struct curl_slist *list;
-
- /* Adding one valid and one invalid email address */
- list = curl_slist_append(NULL, "person@example.com");
- list = curl_slist_append(list, "invalidemailaddress");
-
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
- curl_easy_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS, 1L);
-
- ret = curl_easy_perform(curl);
- curl_slist_free_all(list);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was called CURLOPT_MAIL_RCPT_ALLLOWFAILS before 8.2.0
-
-Added in 7.69.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_MAIL_FROM (3),
-.BR CURLOPT_MAIL_RCPT (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md
new file mode 100644
index 000000000..cf595e26b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAIL_RCPT_ALLOWFAILS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAIL_FROM (3)
+ - CURLOPT_MAIL_RCPT (3)
+---
+
+# NAME
+
+CURLOPT_MAIL_RCPT_ALLOWFAILS - allow RCPT TO command to fail for some recipients
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_RCPT_ALLOWFAILS,
+ long allow);
+~~~
+
+# DESCRIPTION
+
+If *allow* is set to 1L, allow RCPT TO command to fail for some recipients.
+
+When sending data to multiple recipients, by default curl aborts the SMTP
+conversation if either one of the recipients causes the RCPT TO command to
+return an error.
+
+The default behavior can be changed by setting *allow* to 1L which makes
+libcurl ignore errors for individual recipients and proceed with the remaining
+accepted recipients.
+
+If all recipients trigger RCPT TO failures and this flag is specified, curl
+aborts the SMTP conversation and returns the error received from to the last
+RCPT TO command.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct curl_slist *list;
+ CURLcode res;
+
+ /* Adding one valid and one invalid email address */
+ list = curl_slist_append(NULL, "person@example.com");
+ list = curl_slist_append(list, "invalidemailaddress");
+
+ curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS, 1L);
+
+ res = curl_easy_perform(curl);
+ curl_slist_free_all(list);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was called CURLOPT_MAIL_RCPT_ALLLOWFAILS before 8.2.0
+
+Added in 7.69.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3 b/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3
deleted file mode 100644
index acfab2d78..000000000
--- a/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAXAGE_CONN 3 "18 Apr 2019" libcurl libcurl
-.SH NAME
-CURLOPT_MAXAGE_CONN \- max idle time allowed for reusing a connection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXAGE_CONN, long age);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter containing \fIage\fP - the maximum time in seconds
-allowed for an existing connection to have been idle to be considered for
-reuse for this request.
-
-The "connection cache" holds previously used connections. When a new request
-is to be done, libcurl considers any connection that matches for reuse. The
-\fICURLOPT_MAXAGE_CONN(3)\fP limit prevents libcurl from trying too old
-connections for reuse, since old connections have a higher risk of not working
-and thus trying them is a performance loss and sometimes service loss due to
-the difficulties to figure out the situation. If a connection is found in the
-cache that is older than this set \fIage\fP, it is closed instead.
-.SH DEFAULT
-Default maximum age is set to 118 seconds.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* only allow 30 seconds idle time */
- curl_easy_setopt(curl, CURLOPT_MAXAGE_CONN, 30L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.65.0
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_FORBID_REUSE (3),
-.BR CURLOPT_FRESH_CONNECT (3),
-.BR CURLOPT_MAXLIFETIME_CONN (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.md b/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.md
new file mode 100644
index 000000000..3d0a9cb2a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAXAGE_CONN.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAXAGE_CONN
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FORBID_REUSE (3)
+ - CURLOPT_FRESH_CONNECT (3)
+ - CURLOPT_MAXLIFETIME_CONN (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_MAXAGE_CONN - max idle time allowed for reusing a connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXAGE_CONN, long age);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter containing *age* - the maximum time in seconds
+allowed for an existing connection to have been idle to be considered for
+reuse for this request.
+
+The "connection cache" holds previously used connections. When a new request
+is to be done, libcurl considers any connection that matches for reuse. The
+CURLOPT_MAXAGE_CONN(3) limit prevents libcurl from trying too old
+connections for reuse, since old connections have a higher risk of not working
+and thus trying them is a performance loss and sometimes service loss due to
+the difficulties to figure out the situation. If a connection is found in the
+cache that is older than this set *age*, it is closed instead.
+
+# DEFAULT
+
+Default maximum age is set to 118 seconds.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* only allow 30 seconds idle time */
+ curl_easy_setopt(curl, CURLOPT_MAXAGE_CONN, 30L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.65.0
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3 b/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3
deleted file mode 100644
index eb09ff8fb..000000000
--- a/docs/libcurl/opts/CURLOPT_MAXCONNECTS.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAXCONNECTS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAXCONNECTS \- maximum connection cache size
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXCONNECTS, long amount);
-.fi
-.SH DESCRIPTION
-Pass a long. The set \fIamount\fP is the maximum number of simultaneously open
-persistent connections that libcurl may cache in the pool associated with this
-handle. The default is 5, and there is not much point in changing this value
-unless you are perfectly aware of how this works. This concerns connections
-using any of the protocols that support persistent connections.
-
-When reaching the maximum limit, curl closes the oldest one in the cache to
-prevent increasing the number of open connections.
-
-If you already have performed transfers with this curl handle, setting a
-smaller \fICURLOPT_MAXCONNECTS(3)\fP than before may cause open connections to
-get closed unnecessarily.
-
-If you add this easy handle to a multi handle, this setting is not
-acknowledged, and you must instead use \fIcurl_multi_setopt(3)\fP and the
-\fICURLMOPT_MAXCONNECTS(3)\fP option.
-.SH DEFAULT
-5
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* limit the connection cache for this handle to no more than 3 */
- curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 3L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLMOPT_MAX_HOST_CONNECTIONS (3),
-.BR CURLMOPT_MAX_TOTAL_CONNECTIONS (3),
-.BR CURLMOPT_MAXCONNECTS (3),
-.BR CURLOPT_MAXREDIRS (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAXCONNECTS.md b/docs/libcurl/opts/CURLOPT_MAXCONNECTS.md
new file mode 100644
index 000000000..807df4da1
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAXCONNECTS.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAXCONNECTS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_MAXCONNECTS (3)
+ - CURLMOPT_MAX_HOST_CONNECTIONS (3)
+ - CURLMOPT_MAX_TOTAL_CONNECTIONS (3)
+ - CURLOPT_MAXREDIRS (3)
+---
+
+# NAME
+
+CURLOPT_MAXCONNECTS - maximum connection cache size
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXCONNECTS, long amount);
+~~~
+
+# DESCRIPTION
+
+Pass a long. The set *amount* is the maximum number of simultaneously open
+persistent connections that libcurl may cache in the pool associated with this
+handle. The default is 5, and there is not much point in changing this value
+unless you are perfectly aware of how this works. This concerns connections
+using any of the protocols that support persistent connections.
+
+When reaching the maximum limit, curl closes the oldest one in the cache to
+prevent increasing the number of open connections.
+
+If you already have performed transfers with this curl handle, setting a
+smaller CURLOPT_MAXCONNECTS(3) than before may cause open connections to
+get closed unnecessarily.
+
+If you add this easy handle to a multi handle, this setting is not
+acknowledged, and you must instead use curl_multi_setopt(3) and the
+CURLMOPT_MAXCONNECTS(3) option.
+
+# DEFAULT
+
+5
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* limit the connection cache for this handle to no more than 3 */
+ curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 3L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3 b/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3
deleted file mode 100644
index 88f4d61a7..000000000
--- a/docs/libcurl/opts/CURLOPT_MAXFILESIZE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAXFILESIZE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAXFILESIZE \- maximum file size allowed to download
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXFILESIZE, long size);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter. This specifies the maximum accepted \fIsize\fP (in
-bytes) of a file to download. If the file requested is found larger than this
-value, the transfer is aborted and \fICURLE_FILESIZE_EXCEEDED\fP is returned.
-
-The file size is not always known prior to the download start, and for such
-transfers this option has no effect - even if the file transfer eventually
-ends up being larger than this given limit.
-
-If you want a limit above 2GB, use \fICURLOPT_MAXFILESIZE_LARGE(3)\fP.
-
-Since 8.4.0, this option also stops ongoing transfers if they reach this
-threshold.
-.SH DEFAULT
-None
-.SH PROTOCOLS
-FTP, HTTP and MQTT
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* refuse to download if larger than 1000 bytes! */
- curl_easy_setopt(curl, CURLOPT_MAXFILESIZE, 1000L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3),
-.BR CURLOPT_MAXFILESIZE_LARGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE.md b/docs/libcurl/opts/CURLOPT_MAXFILESIZE.md
new file mode 100644
index 000000000..a90c94b7d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAXFILESIZE.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAXFILESIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAXFILESIZE_LARGE (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+---
+
+# NAME
+
+CURLOPT_MAXFILESIZE - maximum file size allowed to download
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXFILESIZE, long size);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter. This specifies the maximum accepted *size* (in
+bytes) of a file to download. If the file requested is found larger than this
+value, the transfer is aborted and *CURLE_FILESIZE_EXCEEDED* is returned.
+
+The file size is not always known prior to the download start, and for such
+transfers this option has no effect - even if the file transfer eventually
+ends up being larger than this given limit.
+
+If you want a limit above 2GB, use CURLOPT_MAXFILESIZE_LARGE(3).
+
+Since 8.4.0, this option also stops ongoing transfers if they reach this
+threshold.
+
+# DEFAULT
+
+None
+
+# PROTOCOLS
+
+FTP, HTTP and MQTT
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* refuse to download if larger than 1000 bytes! */
+ curl_easy_setopt(curl, CURLOPT_MAXFILESIZE, 1000L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3
deleted file mode 100644
index 79dadafc5..000000000
--- a/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAXFILESIZE_LARGE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAXFILESIZE_LARGE \- maximum file size allowed to download
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXFILESIZE_LARGE,
- curl_off_t size);
-.SH DESCRIPTION
-Pass a curl_off_t as parameter. This specifies the maximum accepted \fIsize\fP
-(in bytes) of a file to download. If the file requested is found larger than
-this value, the transfer is aborted and \fICURLE_FILESIZE_EXCEEDED\fP is
-returned.
-
-The file size is not always known prior to the download start, and for such
-transfers this option has no effect - even if the file transfer eventually
-ends up being larger than this given limit.
-
-Since 8.4.0, this option also stops ongoing transfers if they reach this
-threshold.
-.SH DEFAULT
-None
-.SH PROTOCOLS
-FTP, HTTP and MQTT
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_off_t ridiculous = 1 << 48;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* refuse to download if larger than ridiculous */
- curl_easy_setopt(curl, CURLOPT_MAXFILESIZE_LARGE, ridiculous);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.11.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3),
-.BR CURLOPT_MAXFILESIZE (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md b/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md
new file mode 100644
index 000000000..041282f41
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAXFILESIZE_LARGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAXFILESIZE (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+---
+
+# NAME
+
+CURLOPT_MAXFILESIZE_LARGE - maximum file size allowed to download
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXFILESIZE_LARGE,
+ curl_off_t size);
+~~~
+
+# DESCRIPTION
+
+Pass a curl_off_t as parameter. This specifies the maximum accepted *size*
+(in bytes) of a file to download. If the file requested is found larger than
+this value, the transfer is aborted and *CURLE_FILESIZE_EXCEEDED* is
+returned.
+
+The file size is not always known prior to the download start, and for such
+transfers this option has no effect - even if the file transfer eventually
+ends up being larger than this given limit.
+
+Since 8.4.0, this option also stops ongoing transfers if they reach this
+threshold.
+
+# DEFAULT
+
+None
+
+# PROTOCOLS
+
+FTP, HTTP and MQTT
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_off_t ridiculous = (curl_off_t)1 << 48;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* refuse to download if larger than ridiculous */
+ curl_easy_setopt(curl, CURLOPT_MAXFILESIZE_LARGE, ridiculous);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.11.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.3 b/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.3
deleted file mode 100644
index 8cbf5e922..000000000
--- a/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAXLIFETIME_CONN 3 "10 Nov 2021" libcurl libcurl
-.SH NAME
-CURLOPT_MAXLIFETIME_CONN \- max lifetime (since creation) allowed for reusing a connection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXLIFETIME_CONN,
- long maxlifetime);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter containing \fImaxlifetime\fP - the maximum time in
-seconds, since the creation of the connection, that you allow an existing
-connection to have to be considered for reuse for this request.
-
-libcurl features a connection cache that holds previously used connections.
-When a new request is to be done, libcurl considers any connection that
-matches for reuse. The \fICURLOPT_MAXLIFETIME_CONN(3)\fP limit prevents
-libcurl from trying too old connections for reuse. This can be used for
-client-side load balancing. If a connection is found in the cache that is
-older than this set \fImaxlifetime\fP, it is instead marked for closure.
-
-If set to 0, this behavior is disabled: all connections are eligible for reuse.
-.SH DEFAULT
-Default \fImaxlifetime\fP is 0 seconds (i.e., disabled).
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* only allow each connection to be reused for 30 seconds */
- curl_easy_setopt(curl, CURLOPT_MAXLIFETIME_CONN, 30L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.80.0
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_FORBID_REUSE (3),
-.BR CURLOPT_FRESH_CONNECT (3),
-.BR CURLOPT_MAXAGE_CONN (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md b/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md
new file mode 100644
index 000000000..f731ad999
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAXLIFETIME_CONN.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAXLIFETIME_CONN
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FORBID_REUSE (3)
+ - CURLOPT_FRESH_CONNECT (3)
+ - CURLOPT_MAXAGE_CONN (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_MAXLIFETIME_CONN - max lifetime (since creation) allowed for reusing a connection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXLIFETIME_CONN,
+ long maxlifetime);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter containing *maxlifetime* - the maximum time in
+seconds, since the creation of the connection, that you allow an existing
+connection to have to be considered for reuse for this request.
+
+libcurl features a connection cache that holds previously used connections.
+When a new request is to be done, libcurl considers any connection that
+matches for reuse. The CURLOPT_MAXLIFETIME_CONN(3) limit prevents
+libcurl from trying too old connections for reuse. This can be used for
+client-side load balancing. If a connection is found in the cache that is
+older than this set *maxlifetime*, it is instead marked for closure.
+
+If set to 0, this behavior is disabled: all connections are eligible for reuse.
+
+# DEFAULT
+
+Default *maxlifetime* is 0 seconds (i.e., disabled).
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* only allow each connection to be reused for 30 seconds */
+ curl_easy_setopt(curl, CURLOPT_MAXLIFETIME_CONN, 30L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.80.0
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_MAXREDIRS.3 b/docs/libcurl/opts/CURLOPT_MAXREDIRS.3
deleted file mode 100644
index 38a4e3fed..000000000
--- a/docs/libcurl/opts/CURLOPT_MAXREDIRS.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAXREDIRS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAXREDIRS \- maximum number of redirects allowed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXREDIRS, long amount);
-.fi
-.SH DESCRIPTION
-Pass a long. The set number is the redirection limit \fIamount\fP. If that
-many redirections have been followed, the next redirect triggers the error
-(\fICURLE_TOO_MANY_REDIRECTS\fP). This option only makes sense if the
-\fICURLOPT_FOLLOWLOCATION(3)\fP is used at the same time.
-
-Setting the limit to 0 makes libcurl refuse any redirect.
-
-Set it to -1 for an infinite number of redirects. This allows your application
-to get stuck in never-ending redirect loops.
-.SH DEFAULT
-30 (since 8.3.0), it was previously unlimited.
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
-
- /* enable redirect following */
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
-
- /* allow three redirects */
- curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3L);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_REDIRECT_COUNT (3),
-.BR CURLINFO_REDIRECT_URL (3),
-.BR CURLOPT_FOLLOWLOCATION (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAXREDIRS.md b/docs/libcurl/opts/CURLOPT_MAXREDIRS.md
new file mode 100644
index 000000000..5ace67e42
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAXREDIRS.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAXREDIRS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_COUNT (3)
+ - CURLINFO_REDIRECT_URL (3)
+ - CURLOPT_FOLLOWLOCATION (3)
+---
+
+# NAME
+
+CURLOPT_MAXREDIRS - maximum number of redirects allowed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAXREDIRS, long amount);
+~~~
+
+# DESCRIPTION
+
+Pass a long. The set number is the redirection limit *amount*. If that
+many redirections have been followed, the next redirect triggers the error
+(*CURLE_TOO_MANY_REDIRECTS*). This option only makes sense if the
+CURLOPT_FOLLOWLOCATION(3) is used at the same time.
+
+Setting the limit to 0 makes libcurl refuse any redirect.
+
+Set it to -1 for an infinite number of redirects. This allows your application
+to get stuck in never-ending redirect loops.
+
+# DEFAULT
+
+30 (since 8.3.0), it was previously unlimited.
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+
+ /* enable redirect following */
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+
+ /* allow three redirects */
+ curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
deleted file mode 100644
index 0fdad4ba3..000000000
--- a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAX_RECV_SPEED_LARGE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAX_RECV_SPEED_LARGE \- rate limit data download speed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAX_RECV_SPEED_LARGE,
- curl_off_t maxspeed);
-.SH DESCRIPTION
-Pass a curl_off_t as parameter. If a download exceeds this \fImaxspeed\fP
-(counted in bytes per second) the transfer pauses to keep the average speed
-less than or equal to the parameter value. Defaults to unlimited speed.
-
-This is not an exact science. libcurl attempts to keep the average speed below
-the given threshold over a period time.
-
-If you set \fImaxspeed\fP to a value lower than \fICURLOPT_BUFFERSIZE(3)\fP,
-libcurl might download faster than the set limit initially.
-
-This option does not affect transfer speeds done with FILE:// URLs.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-All but file://
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* cap the download speed to 31415 bytes/sec */
- curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)31415);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.5
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_MAX_SEND_SPEED_LARGE (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md
new file mode 100644
index 000000000..646f301e4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAX_RECV_SPEED_LARGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_MAX_SEND_SPEED_LARGE (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_MAX_RECV_SPEED_LARGE - rate limit data download speed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAX_RECV_SPEED_LARGE,
+ curl_off_t maxspeed);
+~~~
+
+# DESCRIPTION
+
+Pass a curl_off_t as parameter. If a download exceeds this *maxspeed*
+(counted in bytes per second) the transfer pauses to keep the average speed
+less than or equal to the parameter value. Defaults to unlimited speed.
+
+This is not an exact science. libcurl attempts to keep the average speed below
+the given threshold over a period time.
+
+If you set *maxspeed* to a value lower than CURLOPT_BUFFERSIZE(3),
+libcurl might download faster than the set limit initially.
+
+This option does not affect transfer speeds done with FILE:// URLs.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+All but file://
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* cap the download speed to 31415 bytes/sec */
+ curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)31415);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.5
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3 b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
deleted file mode 100644
index 57ef15059..000000000
--- a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MAX_SEND_SPEED_LARGE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_MAX_SEND_SPEED_LARGE \- rate limit data upload speed
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAX_SEND_SPEED_LARGE,
- curl_off_t maxspeed);
-.SH DESCRIPTION
-Pass a curl_off_t as parameter with the \fImaxspeed\fP. If an upload exceeds
-this speed (counted in bytes per second) the transfer pauses to keep the
-average speed less than or equal to the parameter value. Defaults to unlimited
-speed.
-
-This is not an exact science. libcurl attempts to keep the average speed below
-the given threshold over a period time.
-
-If you set \fImaxspeed\fP to a value lower than
-\fICURLOPT_UPLOAD_BUFFERSIZE(3)\fP, libcurl might "shoot over" the limit on
-its first send and still send off a full buffer.
-
-This option does not affect transfer speeds done with FILE:// URLs.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-All except file://
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* cap the upload speed to 1000 bytes/sec */
- curl_easy_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t)1000);
- /* (set some upload options as well!) */
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.15.5
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md
new file mode 100644
index 000000000..8b709ccb7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MAX_SEND_SPEED_LARGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+---
+
+# NAME
+
+CURLOPT_MAX_SEND_SPEED_LARGE - rate limit data upload speed
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAX_SEND_SPEED_LARGE,
+ curl_off_t maxspeed);
+~~~
+
+# DESCRIPTION
+
+Pass a curl_off_t as parameter with the *maxspeed*. If an upload exceeds
+this speed (counted in bytes per second) the transfer pauses to keep the
+average speed less than or equal to the parameter value. Defaults to unlimited
+speed.
+
+This is not an exact science. libcurl attempts to keep the average speed below
+the given threshold over a period time.
+
+If you set *maxspeed* to a value lower than
+CURLOPT_UPLOAD_BUFFERSIZE(3), libcurl might "shoot over" the limit on
+its first send and still send off a full buffer.
+
+This option does not affect transfer speeds done with FILE:// URLs.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+All except file://
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* cap the upload speed to 1000 bytes/sec */
+ curl_easy_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t)1000);
+ /* (set some upload options as well!) */
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.15.5
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_MIMEPOST.3 b/docs/libcurl/opts/CURLOPT_MIMEPOST.3
deleted file mode 100644
index a5fb508a9..000000000
--- a/docs/libcurl/opts/CURLOPT_MIMEPOST.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MIMEPOST 3 "22 Aug 2017" libcurl libcurl
-.SH NAME
-CURLOPT_MIMEPOST \- send data from mime structure
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-curl_mime *mime;
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIMEPOST, mime);
-.SH DESCRIPTION
-Pass a mime handle previously obtained from \fIcurl_mime_init(3)\fP.
-
-This setting is supported by the HTTP protocol to post forms and by the
-SMTP and IMAP protocols to provide the email data to send/upload.
-
-This option is the preferred way of posting an HTTP form, replacing and
-extending the \fICURLOPT_HTTPPOST(3)\fP option.
-
-When setting \fICURLOPT_MIMEPOST(3)\fP to NULL, libcurl resets the request
-type for HTTP to the default to disable the POST. Typically that would mean it
-is reset to GET. Instead you should set a desired request method explicitly.
-.SH PROTOCOLS
-HTTP, SMTP, IMAP.
-.SH EXAMPLE
-.nf
- curl_mime *multipart = curl_mime_init(handle);
- curl_mimepart *part = curl_mime_addpart(multipart);
- curl_mime_name(part, "name");
- curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "project");
- curl_mime_data(part, "curl", CURL_ZERO_TERMINATED);
- part = curl_mime_addpart(multipart);
- curl_mime_name(part, "logotype-image");
- curl_mime_filedata(part, "curl.png");
-
- /* Set the form info */
- curl_easy_setopt(handle, CURLOPT_MIMEPOST, multipart);
-
- curl_easy_perform(handle); /* post away! */
-
- curl_mime_free(multipart); /* free the post data */
-.fi
-.SH AVAILABILITY
-Added in 7.56.0
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR curl_mime_init (3),
-.BR CURLOPT_HTTPPOST (3),
-.BR CURLOPT_POSTFIELDS (3),
-.BR CURLOPT_PUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_MIMEPOST.md b/docs/libcurl/opts/CURLOPT_MIMEPOST.md
new file mode 100644
index 000000000..588b7e803
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MIMEPOST.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MIMEPOST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPPOST (3)
+ - CURLOPT_POSTFIELDS (3)
+ - CURLOPT_PUT (3)
+ - curl_mime_init (3)
+---
+
+# NAME
+
+CURLOPT_MIMEPOST - send data from mime structure
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+curl_mime *mime;
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIMEPOST, mime);
+~~~
+
+# DESCRIPTION
+
+Pass a mime handle previously obtained from curl_mime_init(3).
+
+This setting is supported by the HTTP protocol to post forms and by the
+SMTP and IMAP protocols to provide the email data to send/upload.
+
+This option is the preferred way of posting an HTTP form, replacing and
+extending the CURLOPT_HTTPPOST(3) option.
+
+When setting CURLOPT_MIMEPOST(3) to NULL, libcurl resets the request
+type for HTTP to the default to disable the POST. Typically that would mean it
+is reset to GET. Instead you should set a desired request method explicitly.
+
+# PROTOCOLS
+
+HTTP, SMTP, IMAP.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_mime *multipart = curl_mime_init(curl);
+ if(multipart) {
+ curl_mimepart *part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "name");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "project");
+ curl_mime_data(part, "curl", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_filedata(part, "curl.png");
+
+ /* Set the form info */
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, multipart);
+
+ curl_easy_perform(curl); /* post away! */
+ curl_mime_free(multipart); /* free the post data */
+ }
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.56.0
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.3
deleted file mode 100644
index bcef3c5c8..000000000
--- a/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_MIME_OPTIONS 3 "2 Oct 2021" libcurl libcurl
-.SH NAME
-CURLOPT_MIME_OPTIONS \- set MIME option flags
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIME_OPTIONS, long options);
-.fi
-.SH DESCRIPTION
-Pass a long that holds a bitmask of CURLMIMEOPT_* defines. Each bit is a
-Boolean flag used while encoding a MIME tree or multipart form data.
-
-Available bits are:
-.IP CURLMIMEOPT_FORMESCAPE
-Tells libcurl to escape multipart form field and file names using the
-backslash-escaping algorithm rather than percent-encoding (HTTP only).
-
-Backslash-escaping consists in preceding backslashes and double quotes with
-a backslash. Percent encoding maps all occurrences of double quote,
-carriage return and line feed to %22, %0D and %0A respectively.
-
-Before version 7.81.0, percent-encoding was never applied.
-
-HTTP browsers used to do backslash-escaping in the past but have over time
-transitioned to use percent-encoding. This option allows one to address
-server-side applications that have not yet have been converted.
-
-As an example, consider field or file name \fIstrange\\name"kind\fP.
-When the containing multipart form is sent, this is normally transmitted as
-\fIstrange\\name%22kind\fP. When this option is set, it is sent as
-\fIstrange\\\\name\\"kind\fP.
-.SH DEFAULT
-0, meaning disabled.
-.SH PROTOCOLS
-HTTP, IMAP, SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-curl_mime *form = NULL;
-
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_MIME_OPTIONS, CURLMIMEOPT_FORMESCAPE);
-
- form = curl_mime_init(curl);
- if(form) {
- curl_mimepart *part = curl_mime_addpart(form);
-
- if(part) {
- curl_mime_filedata(part, "strange\\\\file\\\\name");
- curl_mime_name(part, "strange\\"field\\"name");
- curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
-
- /* Perform the request */
- curl_easy_perform(curl);
- }
- }
-
- curl_easy_cleanup(curl);
- curl_mime_free(mime);
-}
-.fi
-.SH AVAILABILITY
-Option added in 7.81.0.
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPPOST (3),
-.BR CURLOPT_MIMEPOST (3)
diff --git a/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.md b/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.md
new file mode 100644
index 000000000..a8da7d7ab
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MIME_OPTIONS.md
@@ -0,0 +1,97 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_MIME_OPTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPPOST (3)
+ - CURLOPT_MIMEPOST (3)
+---
+
+# NAME
+
+CURLOPT_MIME_OPTIONS - set MIME option flags
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIME_OPTIONS, long options);
+~~~
+
+# DESCRIPTION
+
+Pass a long that holds a bitmask of CURLMIMEOPT_* defines. Each bit is a
+Boolean flag used while encoding a MIME tree or multipart form data.
+
+Available bits are:
+
+## CURLMIMEOPT_FORMESCAPE
+
+Tells libcurl to escape multipart form field and file names using the
+backslash-escaping algorithm rather than percent-encoding (HTTP only).
+
+Backslash-escaping consists in preceding backslashes and double quotes with
+a backslash. Percent encoding maps all occurrences of double quote,
+carriage return and line feed to %22, %0D and %0A respectively.
+
+Before version 7.81.0, percent-encoding was never applied.
+
+HTTP browsers used to do backslash-escaping in the past but have over time
+transitioned to use percent-encoding. This option allows one to address
+server-side applications that have not yet have been converted.
+
+As an example, consider field or filename *strangename"kind*. When the
+containing multipart form is sent, this is normally transmitted as
+*strangename%22kind*. When this option is set, it is sent as
+*strangename"kind*.
+
+# DEFAULT
+
+0, meaning disabled.
+
+# PROTOCOLS
+
+HTTP, IMAP, SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ curl_mime *form = NULL;
+
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_MIME_OPTIONS, CURLMIMEOPT_FORMESCAPE);
+
+ form = curl_mime_init(curl);
+ if(form) {
+ curl_mimepart *part = curl_mime_addpart(form);
+
+ if(part) {
+ curl_mime_filedata(part, "strange\\file\\name");
+ curl_mime_name(part, "strange\"field\"name");
+ curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+ }
+
+ curl_easy_cleanup(curl);
+ curl_mime_free(form);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Option added in 7.81.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_NETRC.3 b/docs/libcurl/opts/CURLOPT_NETRC.3
deleted file mode 100644
index b9809de8b..000000000
--- a/docs/libcurl/opts/CURLOPT_NETRC.3
+++ /dev/null
@@ -1,123 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NETRC 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NETRC \- enable use of .netrc
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC, long level);
-.fi
-.SH DESCRIPTION
-This parameter controls the preference \fIlevel\fP of libcurl between using
-user names and passwords from your \fI~/.netrc\fP file, relative to user names
-and passwords in the URL supplied with \fICURLOPT_URL(3)\fP.
-
-On Windows, libcurl uses the file as \fI%HOME%/_netrc\fP. If \fI%HOME%\fP is
-not set on Windows, libcurl falls back to \fI%USERPROFILE%\fP.
-
-You can also tell libcurl a different file name to use with
-\fICURLOPT_NETRC_FILE(3)\fP.
-
-libcurl uses a user name (and supplied or prompted password) supplied with
-\fICURLOPT_USERPWD(3)\fP or \fICURLOPT_USERNAME(3)\fP in preference to any of
-the options controlled by this parameter.
-
-Only machine name, user name and password are taken into account (init macros
-and similar things are not supported).
-
-libcurl does not verify that the file has the correct properties set (as the
-standard Unix ftp client does). It should only be readable by user.
-
-\fIlevel\fP is a long that should be set to one of the values described below.
-.IP "CURL_NETRC_IGNORED (0)"
-libcurl ignores the \fI.netrc\fP file. This is the default.
-.IP "CURL_NETRC_OPTIONAL (1)"
-The use of the \fI.netrc\fP file is optional, and information in the URL is to
-be preferred. The file is scanned for the host and user name (to find the
-password only) or for the host only, to find the first user name and password
-after that \fImachine\fP, which ever information is not specified.
-.IP "CURL_NETRC_REQUIRED (2)"
-The use of the \fI.netrc\fP file is required, and any credential information
-present in the URL is ignored. The file is scanned for the host and user name
-(to find the password only) or for the host only, to find the first user name
-and password after that \fImachine\fP, which ever information is not
-specified.
-.SH FILE FORMAT
-The \fB.netrc\fP file format is simple: you specify lines with a machine name
-and follow the login and password that are associated with that machine.
-
-Each field is provided as a sequence of letters that ends with a space or
-newline. Starting in 7.84.0, libcurl also supports quoted strings. They start
-and end with double quotes and support the escaped special letters \\\", \\n,
-\\r, and \\t. Quoted strings are the only way a space character can be used in
-a user name or password.
-
-.IP "machine <name>"
-Provides credentials for a host called \fBname\fP. libcurl searches the .netrc
-file for a machine token that matches the host name specified in the URL. Once
-a match is made, the subsequent tokens are processed, stopping when the end of
-file is reached or another "machine" is encountered.
-.IP default
-This is the same as "machine" name except that default matches any name. There
-can be only one default token, and it must be after all machine tokens. To
-provide a default anonymous login for hosts that are not otherwise matched,
-add a line similar to this in the end:
-
- default login anonymous password user@domain
-.IP "login <name>"
-The user name string for the remote machine.
-.IP "password <secret>"
-Supply a password. If this token is present, curl supplies the specified
-string if the remote server requires a password as part of the login process.
-Note that if this token is present in the .netrc file you really should make
-sure the file is not readable by anyone besides the user.
-.IP "macdef <name>"
-Define a macro. This feature is not supported by libcurl. In order for the
-rest of the .netrc to still work fine, libcurl properly skips every definition
-done with "macdef" that it finds.
-.SH DEFAULT
-CURL_NETRC_IGNORED
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/");
- curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_USERPWD (3),
-.BR CURLOPT_USERNAME (3),
-.BR CURLOPT_NETRC_FILE (3)
diff --git a/docs/libcurl/opts/CURLOPT_NETRC.md b/docs/libcurl/opts/CURLOPT_NETRC.md
new file mode 100644
index 000000000..89a55b4d9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NETRC.md
@@ -0,0 +1,141 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NETRC
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_NETRC_FILE (3)
+ - CURLOPT_USERNAME (3)
+ - CURLOPT_USERPWD (3)
+---
+
+# NAME
+
+CURLOPT_NETRC - enable use of .netrc
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC, long level);
+~~~
+
+# DESCRIPTION
+
+This parameter controls the preference *level* of libcurl between using
+user names and passwords from your *~/.netrc* file, relative to user names
+and passwords in the URL supplied with CURLOPT_URL(3).
+
+On Windows, libcurl uses the file as *%HOME%/_netrc*. If *%HOME%* is
+not set on Windows, libcurl falls back to *%USERPROFILE%*.
+
+You can also tell libcurl a different filename to use with
+CURLOPT_NETRC_FILE(3).
+
+libcurl uses a user name (and supplied or prompted password) supplied with
+CURLOPT_USERPWD(3) or CURLOPT_USERNAME(3) in preference to any of
+the options controlled by this parameter.
+
+Only machine name, user name and password are taken into account (init macros
+and similar things are not supported).
+
+libcurl does not verify that the file has the correct properties set (as the
+standard Unix ftp client does). It should only be readable by user.
+
+*level* is a long that should be set to one of the values described below.
+
+## CURL_NETRC_IGNORED (0)
+
+libcurl ignores the *.netrc* file. This is the default.
+
+## CURL_NETRC_OPTIONAL (1)
+
+The use of the *.netrc* file is optional, and information in the URL is to
+be preferred. The file is scanned for the host and user name (to find the
+password only) or for the host only, to find the first user name and password
+after that *machine*, which ever information is not specified.
+
+## CURL_NETRC_REQUIRED (2)
+
+The use of the *.netrc* file is required, and any credential information
+present in the URL is ignored. The file is scanned for the host and user name
+(to find the password only) or for the host only, to find the first user name
+and password after that *machine*, which ever information is not
+specified.
+
+# FILE FORMAT
+
+The **.netrc** file format is simple: you specify lines with a machine name
+and follow the login and password that are associated with that machine.
+
+Each field is provided as a sequence of letters that ends with a space or
+newline. Starting in 7.84.0, libcurl also supports quoted strings. They start
+and end with double quotes and support the escaped special letters ", n,
+r, and t. Quoted strings are the only way a space character can be used in
+a user name or password.
+
+## machine <name>
+
+Provides credentials for a host called **name**. libcurl searches the .netrc
+file for a machine token that matches the hostname specified in the URL. Once
+a match is made, the subsequent tokens are processed, stopping when the end of
+file is reached or another "machine" is encountered.
+
+## default
+
+This is the same as "machine" name except that default matches any name. There
+can be only one default token, and it must be after all machine tokens. To
+provide a default anonymous login for hosts that are not otherwise matched,
+add a line similar to this in the end:
+
+ default login anonymous password user@domain
+
+## login <name>
+
+The user name string for the remote machine.
+
+## password <secret>
+
+Supply a password. If this token is present, curl supplies the specified
+string if the remote server requires a password as part of the login process.
+Note that if this token is present in the .netrc file you really should make
+sure the file is not readable by anyone besides the user.
+
+## macdef <name>
+
+Define a macro. This feature is not supported by libcurl. In order for the
+rest of the .netrc to still work fine, libcurl properly skips every definition
+done with "macdef" that it finds.
+
+# DEFAULT
+
+CURL_NETRC_IGNORED
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_NETRC_FILE.3 b/docs/libcurl/opts/CURLOPT_NETRC_FILE.3
deleted file mode 100644
index e960813d8..000000000
--- a/docs/libcurl/opts/CURLOPT_NETRC_FILE.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NETRC_FILE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NETRC_FILE \- file name to read .netrc info from
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC_FILE, char *file);
-.fi
-.SH DESCRIPTION
-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
-checks for a .netrc file in the current user's home directory.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/");
- curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
- curl_easy_setopt(curl, CURLOPT_NETRC_FILE, "/tmp/magic-netrc");
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.9
-.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_NETRC (3),
-.BR CURLOPT_PASSWORD (3),
-.BR CURLOPT_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_NETRC_FILE.md b/docs/libcurl/opts/CURLOPT_NETRC_FILE.md
new file mode 100644
index 000000000..62fe7a521
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NETRC_FILE.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NETRC_FILE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_NETRC (3)
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_NETRC_FILE - filename to read .netrc info from
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC_FILE, char *file);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, pointing to a null-terminated string
+containing the full path name to the *file* you want libcurl to use as .netrc
+file. If this option is omitted, and CURLOPT_NETRC(3) is set, libcurl checks
+for a .netrc file in the current user's home directory.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
+ curl_easy_setopt(curl, CURLOPT_NETRC_FILE, "/tmp/magic-netrc");
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.9
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3 b/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3
deleted file mode 100644
index ac2141fc7..000000000
--- a/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.3
+++ /dev/null
@@ -1,61 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NEW_DIRECTORY_PERMS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NEW_DIRECTORY_PERMS \- permissions for remotely created directories
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NEW_DIRECTORY_PERMS,
- long mode);
-.SH DESCRIPTION
-Pass a long as a parameter, containing the value of the permissions that is
-set on newly created directories on the remote server. The default value is
-\fI0755\fP, but any valid value can be used. The only protocols that can use
-this are \fIsftp://\fP, \fIscp://\fP, and \fIfile://\fP.
-.SH DEFAULT
-0755
-.SH PROTOCOLS
-SFTP, SCP and FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://upload.example.com/newdir/file.zip");
- curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
- curl_easy_setopt(curl, CURLOPT_NEW_DIRECTORY_PERMS, 0644L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FTP_CREATE_MISSING_DIRS (3),
-.BR CURLOPT_NEW_FILE_PERMS (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md b/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md
new file mode 100644
index 000000000..bb302d42b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NEW_DIRECTORY_PERMS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FTP_CREATE_MISSING_DIRS (3)
+ - CURLOPT_NEW_FILE_PERMS (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_NEW_DIRECTORY_PERMS - permissions for remotely created directories
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NEW_DIRECTORY_PERMS,
+ long mode);
+~~~
+
+# DESCRIPTION
+
+Pass a long as a parameter, containing the value of the permissions that is
+set on newly created directories on the remote server. The default value is
+*0755*, but any valid value can be used. The only protocols that can use
+this are *sftp://*, *scp://*, and *file://*.
+
+# DEFAULT
+
+0755
+
+# PROTOCOLS
+
+SFTP, SCP and FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "sftp://upload.example.com/newdir/file.zip");
+ curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
+ curl_easy_setopt(curl, CURLOPT_NEW_DIRECTORY_PERMS, 0644L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3 b/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3
deleted file mode 100644
index 07de59dca..000000000
--- a/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NEW_FILE_PERMS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NEW_FILE_PERMS \- permissions for remotely created files
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NEW_FILE_PERMS,
- long mode);
-.SH DESCRIPTION
-Pass a long as a parameter, containing the value of the permissions that are
-set on newly created files on the remote server. The default value is
-\fI0644\fP, but any valid value can be used. The only protocols that can use
-this are \fIsftp://\fP, \fIscp://\fP, and \fIfile://\fP.
-.SH DEFAULT
-0644
-.SH PROTOCOLS
-SFTP, SCP and FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://upload.example.com/file.txt");
- curl_easy_setopt(curl, CURLOPT_NEW_FILE_PERMS, 0664L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_NEW_DIRECTORY_PERMS (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md b/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md
new file mode 100644
index 000000000..dd12c0bbd
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md
@@ -0,0 +1,60 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NEW_FILE_PERMS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_NEW_DIRECTORY_PERMS (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_NEW_FILE_PERMS - permissions for remotely created files
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NEW_FILE_PERMS,
+ long mode);
+~~~
+
+# DESCRIPTION
+
+Pass a long as a parameter, containing the value of the permissions that are
+set on newly created files on the remote server. The default value is *0644*.
+The only protocols that can use this are *sftp://*, *scp://*, and *file://*.
+
+# DEFAULT
+
+0644
+
+# PROTOCOLS
+
+SFTP, SCP and FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://upload.example.com/file.txt");
+ curl_easy_setopt(curl, CURLOPT_NEW_FILE_PERMS, 0664L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_NOBODY.3 b/docs/libcurl/opts/CURLOPT_NOBODY.3
deleted file mode 100644
index 971b9c7e1..000000000
--- a/docs/libcurl/opts/CURLOPT_NOBODY.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NOBODY 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NOBODY \- do the download request without getting the body
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOBODY, long opt);
-.fi
-.SH DESCRIPTION
-A long parameter set to 1 tells libcurl to not include the body-part in the
-output when doing what would otherwise be a download. For HTTP(S), this makes
-libcurl do a HEAD request. For most other protocols it means just not asking
-to transfer the body data.
-
-For HTTP operations when \fICURLOPT_NOBODY(3)\fP has been set, disabling this
-option (with 0) makes it a GET again - only if the method is still set to be
-HEAD. The proper way to get back to a GET request is to set
-\fICURLOPT_HTTPGET(3)\fP and for other methods, use the POST or UPLOAD
-options.
-
-Enabling \fICURLOPT_NOBODY(3)\fP means asking for a download without a body.
-
-If you do a transfer with HTTP that involves a method other than HEAD, you get
-a body (unless the resource and server sends a zero byte body for the specific
-URL you request).
-.SH DEFAULT
-0, the body is transferred
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* get us the resource without a body - use HEAD! */
- curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPGET (3),
-.BR CURLOPT_MIMEPOST (3),
-.BR CURLOPT_POSTFIELDS (3),
-.BR CURLOPT_REQUEST_TARGET (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_NOBODY.md b/docs/libcurl/opts/CURLOPT_NOBODY.md
new file mode 100644
index 000000000..9d63154c9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NOBODY.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NOBODY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPGET (3)
+ - CURLOPT_MIMEPOST (3)
+ - CURLOPT_POSTFIELDS (3)
+ - CURLOPT_REQUEST_TARGET (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_NOBODY - do the download request without getting the body
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOBODY, long opt);
+~~~
+
+# DESCRIPTION
+
+A long parameter set to 1 tells libcurl to not include the body-part in the
+output when doing what would otherwise be a download. For HTTP(S), this makes
+libcurl do a HEAD request. For most other protocols it means just not asking
+to transfer the body data.
+
+For HTTP operations when CURLOPT_NOBODY(3) has been set, disabling this
+option (with 0) makes it a GET again - only if the method is still set to be
+HEAD. The proper way to get back to a GET request is to set
+CURLOPT_HTTPGET(3) and for other methods, use the POST or UPLOAD
+options.
+
+Enabling CURLOPT_NOBODY(3) means asking for a download without a body.
+
+If you do a transfer with HTTP that involves a method other than HEAD, you get
+a body (unless the resource and server sends a zero byte body for the specific
+URL you request).
+
+# DEFAULT
+
+0, the body is transferred
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* get us the resource without a body - use HEAD! */
+ curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_NOPROGRESS.3 b/docs/libcurl/opts/CURLOPT_NOPROGRESS.3
deleted file mode 100644
index 91b20c2b9..000000000
--- a/docs/libcurl/opts/CURLOPT_NOPROGRESS.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NOPROGRESS 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NOPROGRESS \- switch off the progress meter
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROGRESS, long onoff);
-.fi
-.SH DESCRIPTION
-If \fIonoff\fP is to 1, it tells the library to shut off the progress meter
-completely for requests done with this \fIhandle\fP. It also prevents the
-\fICURLOPT_XFERINFOFUNCTION(3)\fP or \fICURLOPT_PROGRESSFUNCTION(3)\fP from
-getting called.
-.SH DEFAULT
-1, meaning it normally runs without a progress meter.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* enable progress meter */
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_PROGRESSFUNCTION (3),
-.BR CURLOPT_VERBOSE (3),
-.BR CURLOPT_XFERINFOFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_NOPROGRESS.md b/docs/libcurl/opts/CURLOPT_NOPROGRESS.md
new file mode 100644
index 000000000..e2845a96f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NOPROGRESS.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NOPROGRESS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_PROGRESSFUNCTION (3)
+ - CURLOPT_VERBOSE (3)
+ - CURLOPT_XFERINFOFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_NOPROGRESS - switch off the progress meter
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROGRESS, long onoff);
+~~~
+
+# DESCRIPTION
+
+If *onoff* is to 1, it tells the library to shut off the progress meter
+completely for requests done with this *handle*. It also prevents the
+CURLOPT_XFERINFOFUNCTION(3) or CURLOPT_PROGRESSFUNCTION(3) from
+getting called.
+
+# DEFAULT
+
+1, meaning it normally runs without a progress meter.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* enable progress meter */
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_NOPROXY.3 b/docs/libcurl/opts/CURLOPT_NOPROXY.3
deleted file mode 100644
index dd76e78ab..000000000
--- a/docs/libcurl/opts/CURLOPT_NOPROXY.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NOPROXY 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NOPROXY \- disable proxy use for specific hosts
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROXY, char *noproxy);
-.fi
-.SH DESCRIPTION
-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
-list is matched as either a domain which contains the hostname, or the
-hostname itself. For example, "ample.com" would match ample.com, ample.com:80,
-and www.ample.com, but not www.example.com or ample.com.org.
-
-Setting the \fInoproxy\fP string to "" (an empty string) explicitly enables
-the proxy for all host names, even if there is an environment variable set for
-it.
-
-Enter IPv6 numerical addresses in the list of host names without enclosing
-brackets:
-
- "example.com,::1,localhost"
-
-Since 7.86.0, IP addresses specified to this option can be provided using CIDR
-notation: an appended slash and number specifies the number of "network bits"
-out of the address to use in the comparison. For example "192.168.0.0/16"
-would match all addresses starting with "192.168".
-
-The application does not have to keep the string around after setting this
-option.
-.SH "Environment variables"
-If there is an environment variable called \fBno_proxy\fP (or \fBNO_PROXY\fP),
-it is used if the \fICURLOPT_NOPROXY(3)\fP option is not set. It works exactly
-the same way.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- /* accept various URLs */
- curl_easy_setopt(curl, CURLOPT_URL, input);
- /* use this proxy */
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80");
- /* ... but make sure this host name is not proxied */
- curl_easy_setopt(curl, CURLOPT_NOPROXY, "www.example.com");
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.4
-.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 (3),
-.BR CURLOPT_PROXYAUTH (3),
-.BR CURLOPT_PROXYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_NOPROXY.md b/docs/libcurl/opts/CURLOPT_NOPROXY.md
new file mode 100644
index 000000000..91292e22e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NOPROXY.md
@@ -0,0 +1,91 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NOPROXY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYAUTH (3)
+ - CURLOPT_PROXYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_NOPROXY - disable proxy use for specific hosts
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROXY, char *noproxy);
+~~~
+
+# DESCRIPTION
+
+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
+list is matched as either a domain which contains the hostname, or the
+hostname itself. For example, "ample.com" would match ample.com, ample.com:80,
+and www.ample.com, but not www.example.com or ample.com.org.
+
+Setting the *noproxy* string to "" (an empty string) explicitly enables
+the proxy for all host names, even if there is an environment variable set for
+it.
+
+Enter IPv6 numerical addresses in the list of host names without enclosing
+brackets:
+
+ "example.com,::1,localhost"
+
+Since 7.86.0, IP addresses specified to this option can be provided using CIDR
+notation: an appended slash and number specifies the number of "network bits"
+out of the address to use in the comparison. For example "192.168.0.0/16"
+would match all addresses starting with "192.168".
+
+The application does not have to keep the string around after setting this
+option.
+
+# Environment variables
+
+If there is an environment variable called **no_proxy** (or **NO_PROXY**),
+it is used if the CURLOPT_NOPROXY(3) option is not set. It works exactly
+the same way.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* accept various URLs */
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* use this proxy */
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80");
+ /* ... but make sure this host name is not proxied */
+ curl_easy_setopt(curl, CURLOPT_NOPROXY, "www.example.com");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.4
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_NOSIGNAL.3 b/docs/libcurl/opts/CURLOPT_NOSIGNAL.3
deleted file mode 100644
index 2ab15c2b6..000000000
--- a/docs/libcurl/opts/CURLOPT_NOSIGNAL.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_NOSIGNAL 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_NOSIGNAL \- skip all signal handling
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOSIGNAL, long onoff);
-.fi
-.SH DESCRIPTION
-If \fIonoff\fP is 1, libcurl uses no functions that install signal handlers or
-any functions that cause signals to be sent to the process. This option is
-here to allow multi-threaded unix applications to still set/use all timeout
-options etc, without risking getting signals.
-
-If this option is set and libcurl has been built with the standard name
-resolver, timeouts cannot occur while the name resolve takes place. Consider
-building libcurl with the c-ares or threaded resolver backends to enable
-asynchronous DNS lookups, to enable timeouts for name resolves without the use
-of signals.
-
-Setting \fICURLOPT_NOSIGNAL(3)\fP to 1 makes libcurl NOT ask the system to
-ignore SIGPIPE signals, which otherwise are sent by the system when trying to
-send data to a socket which is closed in the other end. libcurl makes an
-effort to never cause such SIGPIPE signals to trigger, but some operating
-systems have no way to avoid them and even on those that have there are some
-corner cases when they may still happen, contrary to our desire. In addition,
-using \fICURLAUTH_NTLM_WB\fP authentication could cause a SIGCHLD signal to be
-raised.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
-
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH SEE ALSO
-.BR CURLOPT_TIMEOUT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_NOSIGNAL.md b/docs/libcurl/opts/CURLOPT_NOSIGNAL.md
new file mode 100644
index 000000000..50ae65cca
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_NOSIGNAL.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_NOSIGNAL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_NOSIGNAL - skip all signal handling
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOSIGNAL, long onoff);
+~~~
+
+# DESCRIPTION
+
+If *onoff* is 1, libcurl uses no functions that install signal handlers or
+any functions that cause signals to be sent to the process. This option is
+here to allow multi-threaded unix applications to still set/use all timeout
+options etc, without risking getting signals.
+
+If this option is set and libcurl has been built with the standard name
+resolver, timeouts cannot occur while the name resolve takes place. Consider
+building libcurl with the c-ares or threaded resolver backends to enable
+asynchronous DNS lookups, to enable timeouts for name resolves without the use
+of signals.
+
+Setting CURLOPT_NOSIGNAL(3) to 1 makes libcurl NOT ask the system to
+ignore SIGPIPE signals, which otherwise are sent by the system when trying to
+send data to a socket which is closed in the other end. libcurl makes an
+effort to never cause such SIGPIPE signals to trigger, but some operating
+systems have no way to avoid them and even on those that have there are some
+corner cases when they may still happen, contrary to our desire. In addition,
+using *CURLAUTH_NTLM_WB* authentication could cause a SIGCHLD signal to be
+raised.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3 b/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3
deleted file mode 100644
index 816941136..000000000
--- a/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.3
+++ /dev/null
@@ -1,88 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_OPENSOCKETDATA 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_OPENSOCKETDATA \- pointer passed to open socket callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_OPENSOCKETDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP that is untouched by libcurl and passed as the first
-argument in the open socket callback set with
-\fICURLOPT_OPENSOCKETFUNCTION(3)\fP.
-.SH DEFAULT
-The default value of this parameter is NULL.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-/* make libcurl use the already established socket 'sockfd' */
-
-static curl_socket_t opensocket(void *clientp,
- curlsocktype purpose,
- struct curl_sockaddr *address)
-{
- curl_socket_t sockfd;
- sockfd = *(curl_socket_t *)clientp;
- /* the actual externally set socket is passed in via the OPENSOCKETDATA
- option */
- return sockfd;
-}
-
-static int sockopt_callback(void *clientp, curl_socket_t curlfd,
- curlsocktype purpose)
-{
- /* This return code was added in libcurl 7.21.5 */
- return CURL_SOCKOPT_ALREADY_CONNECTED;
-}
-
-curl = curl_easy_init();
-if(curl) {
- /* libcurl thinks that you connect to the host
- * and port that you specify in the URL option. */
- curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
- /* call this function to get a socket */
- curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
- curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
-
- /* call this function to set options for the socket */
- curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
-
- res = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.17.1
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CLOSESOCKETFUNCTION (3),
-.BR CURLOPT_OPENSOCKETFUNCTION (3),
-.BR CURLOPT_SOCKOPTFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md b/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md
new file mode 100644
index 000000000..f3e7ef855
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md
@@ -0,0 +1,92 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_OPENSOCKETDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CLOSESOCKETFUNCTION (3)
+ - CURLOPT_OPENSOCKETFUNCTION (3)
+ - CURLOPT_SOCKOPTFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_OPENSOCKETDATA - pointer passed to open socket callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_OPENSOCKETDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* that is untouched by libcurl and passed as the first
+argument in the open socket callback set with
+CURLOPT_OPENSOCKETFUNCTION(3).
+
+# DEFAULT
+
+The default value of this parameter is NULL.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+/* make libcurl use the already established socket 'sockfd' */
+
+static curl_socket_t opensocket(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address)
+{
+ curl_socket_t sockfd;
+ sockfd = *(curl_socket_t *)clientp;
+ /* the actual externally set socket is passed in via the OPENSOCKETDATA
+ option */
+ return sockfd;
+}
+
+static int sockopt_callback(void *clientp, curl_socket_t curlfd,
+ curlsocktype purpose)
+{
+ /* This return code was added in libcurl 7.21.5 */
+ return CURL_SOCKOPT_ALREADY_CONNECTED;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ extern int sockfd; /* the already connected one */
+
+ /* libcurl thinks that you connect to the host
+ * and port that you specify in the URL option. */
+ curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
+ /* call this function to get a socket */
+ curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
+ curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
+
+ /* call this function to set options for the socket */
+ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.17.1
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3 b/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3
deleted file mode 100644
index 86c122404..000000000
--- a/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.3
+++ /dev/null
@@ -1,129 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_OPENSOCKETFUNCTION 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_OPENSOCKETFUNCTION \- callback for opening socket
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef enum {
- CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
-} curlsocktype;
-
-struct curl_sockaddr {
- int family;
- int socktype;
- int protocol;
- unsigned int addrlen;
- struct sockaddr addr;
-};
-
-curl_socket_t opensocket_callback(void *clientp,
- curlsocktype purpose,
- struct curl_sockaddr *address);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_OPENSOCKETFUNCTION, opensocket_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl instead of the \fIsocket(2)\fP
-call. The callback's \fIpurpose\fP argument identifies the exact purpose for
-this particular socket. \fICURLSOCKTYPE_IPCXN\fP is for IP based connections
-and is the only purpose currently used in libcurl. Future versions of libcurl
-may support more purposes.
-
-The \fIclientp\fP pointer contains whatever user-defined value set using the
-\fICURLOPT_OPENSOCKETDATA(3)\fP function.
-
-The callback gets the resolved peer address as the \fIaddress\fP argument and
-is allowed to modify the address or refuse to connect completely. The callback
-function should return the newly created socket or \fICURL_SOCKET_BAD\fP in
-case no connection could be established or another error was detected. Any
-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 signals an unrecoverable error to libcurl and it returns
-\fICURLE_COULDNT_CONNECT\fP from the function that triggered this callback.
-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
-\fICURLOPT_SOCKOPTFUNCTION(3)\fP to signal that it already is connected.
-.SH DEFAULT
-The default behavior is the equivalent of this:
-.nf
- return socket(addr->family, addr->socktype, addr->protocol);
-.fi
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-/* make libcurl use the already established socket 'sockfd' */
-
-static curl_socket_t opensocket(void *clientp,
- curlsocktype purpose,
- struct curl_sockaddr *address)
-{
- curl_socket_t sockfd;
- sockfd = *(curl_socket_t *)clientp;
- /* the actual externally set socket is passed in via the OPENSOCKETDATA
- option */
- return sockfd;
-}
-
-static int sockopt_callback(void *clientp, curl_socket_t curlfd,
- curlsocktype purpose)
-{
- /* This return code was added in libcurl 7.21.5 */
- return CURL_SOCKOPT_ALREADY_CONNECTED;
-}
-
-curl = curl_easy_init();
-if(curl) {
- /* libcurl thinks that you connect to the host
- * and port that you specify in the URL option. */
- curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
- /* call this function to get a socket */
- curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
- curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
-
- /* call this function to set options for the socket */
- curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
-
- res = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.17.1.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CLOSESOCKETFUNCTION (3),
-.BR CURLOPT_OPENSOCKETFUNCTION (3),
-.BR CURLOPT_SOCKOPTFUNCTION (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md b/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md
new file mode 100644
index 000000000..125ccff68
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md
@@ -0,0 +1,132 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_OPENSOCKETFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CLOSESOCKETFUNCTION (3)
+ - CURLOPT_OPENSOCKETFUNCTION (3)
+ - CURLOPT_SOCKOPTFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_OPENSOCKETFUNCTION - callback for opening socket
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+typedef enum {
+ CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
+} curlsocktype;
+
+struct curl_sockaddr {
+ int family;
+ int socktype;
+ int protocol;
+ unsigned int addrlen;
+ struct sockaddr addr;
+};
+
+curl_socket_t opensocket_callback(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_OPENSOCKETFUNCTION, opensocket_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl instead of the *socket(2)*
+call. The callback's *purpose* argument identifies the exact purpose for
+this particular socket. *CURLSOCKTYPE_IPCXN* is for IP based connections
+and is the only purpose currently used in libcurl. Future versions of libcurl
+may support more purposes.
+
+The *clientp* pointer contains whatever user-defined value set using the
+CURLOPT_OPENSOCKETDATA(3) function.
+
+The callback gets the resolved peer address as the *address* argument and
+is allowed to modify the address or refuse to connect completely. The callback
+function should return the newly created socket or *CURL_SOCKET_BAD* in
+case no connection could be established or another error was detected. Any
+additional *setsockopt(2)* calls can of course be done on the socket at
+the user's discretion. A *CURL_SOCKET_BAD* return value from the callback
+function signals an unrecoverable error to libcurl and it returns
+*CURLE_COULDNT_CONNECT* from the function that triggered this callback.
+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
+CURLOPT_SOCKOPTFUNCTION(3) to signal that it already is connected.
+
+# DEFAULT
+
+The default behavior is the equivalent of this:
+~~~c
+ return socket(addr->family, addr->socktype, addr->protocol);
+~~~
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+/* make libcurl use the already established socket 'sockfd' */
+
+static curl_socket_t opensocket(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address)
+{
+ curl_socket_t sockfd;
+ sockfd = *(curl_socket_t *)clientp;
+ /* the actual externally set socket is passed in via the OPENSOCKETDATA
+ option */
+ return sockfd;
+}
+
+static int sockopt_callback(void *clientp, curl_socket_t curlfd,
+ curlsocktype purpose)
+{
+ /* This return code was added in libcurl 7.21.5 */
+ return CURL_SOCKOPT_ALREADY_CONNECTED;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ extern int sockfd; /* the already connected one */
+ /* libcurl thinks that you connect to the host
+ * and port that you specify in the URL option. */
+ curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
+ /* call this function to get a socket */
+ curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
+ curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
+
+ /* call this function to set options for the socket */
+ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.17.1.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PASSWORD.3 b/docs/libcurl/opts/CURLOPT_PASSWORD.3
deleted file mode 100644
index 3816f78a7..000000000
--- a/docs/libcurl/opts/CURLOPT_PASSWORD.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PASSWORD 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PASSWORD \- password to use in authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PASSWORD, char *pwd);
-.fi
-.SH DESCRIPTION
-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
-\fICURLOPT_USERNAME(3)\fP option.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-blank
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- curl_easy_setopt(curl, CURLOPT_PASSWORD, "qwerty");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.1
-.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_HTTPAUTH (3),
-.BR CURLOPT_PROXYAUTH (3),
-.BR CURLOPT_USERNAME (3),
-.BR CURLOPT_USERPWD (3)
diff --git a/docs/libcurl/opts/CURLOPT_PASSWORD.md b/docs/libcurl/opts/CURLOPT_PASSWORD.md
new file mode 100644
index 000000000..9849802d1
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PASSWORD.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PASSWORD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPAUTH (3)
+ - CURLOPT_PROXYAUTH (3)
+ - CURLOPT_USERNAME (3)
+ - CURLOPT_USERPWD (3)
+---
+
+# NAME
+
+CURLOPT_PASSWORD - password to use in authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PASSWORD, char *pwd);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be pointing to the
+null-terminated password to use for the transfer.
+
+The CURLOPT_PASSWORD(3) option should be used in conjunction with the
+CURLOPT_USERNAME(3) option.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ curl_easy_setopt(curl, CURLOPT_PASSWORD, "qwerty");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.1
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3 b/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3
deleted file mode 100644
index 8ffa1d855..000000000
--- a/docs/libcurl/opts/CURLOPT_PATH_AS_IS.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PATH_AS_IS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PATH_AS_IS \- do not handle dot dot sequences
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PATH_AS_IS, long leaveit);
-.fi
-.SH DESCRIPTION
-Set the long \fIleaveit\fP to 1, to explicitly tell libcurl to not alter the
-given path before passing it on to the server.
-
-This instructs libcurl to NOT squash sequences of "/../" or "/./" that may
-exist in the URL's path part and that is supposed to be removed according to
-RFC 3986 section 5.2.4.
-
-Some server implementations are known to (erroneously) require the dot dot
-sequences to remain in the path and some clients want to pass these on in
-order to try out server implementations.
-
-By default libcurl normalizes such sequences before using the path.
-
-The corresponding flag for the \fIcurl_url_set(3)\fP function is called
-\fBCURLU_PATH_AS_IS\fP.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/../../etc/password");
-
- curl_easy_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.42.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_url_set (3),
-.BR CURLOPT_STDERR (3),
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_URL (3)
-
-
diff --git a/docs/libcurl/opts/CURLOPT_PATH_AS_IS.md b/docs/libcurl/opts/CURLOPT_PATH_AS_IS.md
new file mode 100644
index 000000000..499469172
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PATH_AS_IS.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PATH_AS_IS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_STDERR (3)
+ - CURLOPT_URL (3)
+ - curl_url_set (3)
+---
+
+# NAME
+
+CURLOPT_PATH_AS_IS - do not handle dot dot sequences
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PATH_AS_IS, long leaveit);
+~~~
+
+# DESCRIPTION
+
+Set the long *leaveit* to 1, to explicitly tell libcurl to not alter the
+given path before passing it on to the server.
+
+This instructs libcurl to NOT squash sequences of "/../" or "/./" that may
+exist in the URL's path part and that is supposed to be removed according to
+RFC 3986 section 5.2.4.
+
+Some server implementations are known to (erroneously) require the dot dot
+sequences to remain in the path and some clients want to pass these on in
+order to try out server implementations.
+
+By default libcurl normalizes such sequences before using the path.
+
+The corresponding flag for the curl_url_set(3) function is called
+**CURLU_PATH_AS_IS**.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "https://example.com/../../etc/password");
+
+ curl_easy_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.42.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
deleted file mode 100644
index aa082af70..000000000
--- a/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.3
+++ /dev/null
@@ -1,134 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PINNEDPUBLICKEY 3 "27 Aug 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PINNEDPUBLICKEY \- pinned public key
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY,
- char *pinnedpubkey);
-.fi
-.SH DESCRIPTION
-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 ";"
-
-When negotiating a TLS or SSL connection, the server sends a certificate
-indicating its identity. A public key is extracted from this certificate and
-if it does not exactly match the public key provided to this option, curl
-aborts the connection before sending or receiving any data.
-
-This option is independent of option \fICURLOPT_SSL_VERIFYPEER(3)\fP. If you
-turn off that option then the peer is still verified by public key.
-
-On mismatch, \fICURLE_SSL_PINNEDPUBKEYNOTMATCH\fP is returned.
-
-The application does not have to keep the string around after setting this
-option.
-.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) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, "/etc/publickey.der");
- /* OR
- curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjAa3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74Gxa2eg7fRbEgoChTociMee9wno=");
- */
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH PUBLIC KEY EXTRACTION
-If you do not have the server's public key file you can extract it from the
-server's certificate.
-.nf
-# retrieve the server's certificate if you do not already have it
-#
-# be sure to examine the certificate to see if it is what you expected
-#
-# Windows-specific:
-# - Use NUL instead of /dev/null.
-# - OpenSSL may wait for input instead of disconnecting. Hit enter.
-# - If you do not have sed, then just copy the certificate into a file:
-# Lines from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----.
-#
-openssl s_client -servername www.example.com -connect www.example.com:443 < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem
-
-# extract public key in pem format from certificate
-openssl x509 -in www.example.com.pem -pubkey -noout > www.example.com.pubkey.pem
-
-# convert public key from pem to der
-openssl asn1parse -noout -inform pem -in www.example.com.pubkey.pem -out www.example.com.pubkey.der
-
-# sha256 hash and base64 encode der to string for use
-openssl dgst -sha256 -binary www.example.com.pubkey.der | openssl base64
-.fi
-The public key in PEM format contains a header, base64 data and a
-footer:
-.nf
------BEGIN PUBLIC KEY-----
-[BASE 64 DATA]
------END PUBLIC KEY-----
-.fi
-.SH AVAILABILITY
-PEM/DER support:
-
- 7.39.0: OpenSSL, GnuTLS
-
- 7.43.0: wolfSSL
-
- 7.47.0: mbedTLS
-
- 7.54.1: Secure Transport on macOS 10.7+/iOS 10+
-
- 7.58.1: Schannel
-
-sha256 support:
-
- 7.44.0: OpenSSL, GnuTLS and wolfSSL
-
- 7.47.0: mbedTLS
-
- 7.54.1: Secure Transport on macOS 10.7+/iOS 10+
-
- 7.58.1: Schannel
-
-Other SSL backends not supported.
-.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_CAINFO (3),
-.BR CURLOPT_CAPATH (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.md b/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.md
new file mode 100644
index 000000000..922e2a6d6
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PINNEDPUBLICKEY.md
@@ -0,0 +1,143 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PINNEDPUBLICKEY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_CAPATH (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PINNEDPUBLICKEY - pinned public key
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY,
+ char *pinnedpubkey);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. The string can be the
+filename 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 ";"
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. A public key is extracted from this certificate and
+if it does not exactly match the public key provided to this option, curl
+aborts the connection before sending or receiving any data.
+
+This option is independent of option CURLOPT_SSL_VERIFYPEER(3). If you turn
+off that option then the peer is still verified by public key.
+
+On mismatch, *CURLE_SSL_PINNEDPUBKEYNOTMATCH* is returned.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, "/etc/publickey.der");
+ /* OR
+ curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY,
+ "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjAa3HWY3"
+ "tvRMwE=;sha256//t62CeU2tQiqkexU74Gxa2eg7fRbEg"
+ "oChTociMee9wno=");
+ */
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# PUBLIC KEY EXTRACTION
+
+If you do not have the server's public key file you can extract it from the
+server's certificate.
+~~~
+# retrieve the server's certificate if you do not already have it
+#
+# be sure to examine the certificate to see if it is what you expected
+#
+# Windows-specific:
+# - Use NUL instead of /dev/null.
+# - OpenSSL may wait for input instead of disconnecting. Hit enter.
+# - If you do not have sed, then just copy the certificate into a file:
+# Lines from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----.
+#
+openssl s_client -servername www.example.com -connect www.example.com:443 \
+ < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem
+
+# extract public key in pem format from certificate
+openssl x509 -in www.example.com.pem -pubkey -noout > www.example.com.pubkey.pem
+
+# convert public key from pem to der
+openssl asn1parse -noout -inform pem -in www.example.com.pubkey.pem \
+ -out www.example.com.pubkey.der
+
+# sha256 hash and base64 encode der to string for use
+openssl dgst -sha256 -binary www.example.com.pubkey.der | openssl base64
+~~~
+
+The public key in PEM format contains a header, base64 data and a
+footer:
+~~~
+-----BEGIN PUBLIC KEY-----
+[BASE 64 DATA]
+-----END PUBLIC KEY-----
+~~~
+
+# AVAILABILITY
+
+## PEM/DER support
+
+7.39.0: OpenSSL, GnuTLS
+
+7.43.0: wolfSSL
+
+7.47.0: mbedTLS
+
+7.54.1: Secure Transport on macOS 10.7+/iOS 10+
+
+7.58.1: Schannel
+
+## sha256 support
+
+7.44.0: OpenSSL, GnuTLS and wolfSSL
+
+7.47.0: mbedTLS
+
+7.54.1: Secure Transport on macOS 10.7+/iOS 10+
+
+7.58.1: Schannel
+
+Other SSL backends not supported.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PIPEWAIT.3 b/docs/libcurl/opts/CURLOPT_PIPEWAIT.3
deleted file mode 100644
index 593149edd..000000000
--- a/docs/libcurl/opts/CURLOPT_PIPEWAIT.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PIPEWAIT 3 "12 May 2015" libcurl libcurl
-.SH NAME
-CURLOPT_PIPEWAIT \- wait for multiplexing
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PIPEWAIT, long wait);
-.fi
-.SH DESCRIPTION
-Set \fIwait\fP to 1L to tell libcurl to prefer to wait for a connection to
-confirm or deny that it can do multiplexing before continuing.
-
-When about to perform a new transfer that allows multiplexing, libcurl checks
-for existing connections to use. If no such connection exists it immediately
-continues and creates a fresh new connection to use.
-
-By setting this option to 1 - and having \fICURLMOPT_PIPELINING(3)\fP enabled
-for the multi handle this transfer is associated with - libcurl instead waits
-for the connection to reveal if it is possible to multiplex on before it
-continues. This enables libcurl to much better keep the number of connections
-to a minimum when using multiplexing protocols.
-
-With this option set, libcurl prefers to wait and reuse an existing connection
-for multiplexing rather than the opposite: prefer to open a new connection
-rather than waiting.
-
-The waiting time is as long as it takes for the connection to get up and for
-libcurl to get the necessary response back that informs it about its protocol
-and support level.
-.SH DEFAULT
-0 (off)
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PIPEWAIT, 1L);
-
- /* now add this easy handle to the multi handle */
-}
-.fi
-.SH AVAILABILITY
-Added in 7.43.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_MAX_HOST_CONNECTIONS (3),
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLOPT_FORBID_REUSE (3),
-.BR CURLOPT_FRESH_CONNECT (3)
diff --git a/docs/libcurl/opts/CURLOPT_PIPEWAIT.md b/docs/libcurl/opts/CURLOPT_PIPEWAIT.md
new file mode 100644
index 000000000..1be844dd0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PIPEWAIT.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PIPEWAIT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_MAX_HOST_CONNECTIONS (3)
+ - CURLMOPT_PIPELINING (3)
+ - CURLOPT_FORBID_REUSE (3)
+ - CURLOPT_FRESH_CONNECT (3)
+---
+
+# NAME
+
+CURLOPT_PIPEWAIT - wait for multiplexing
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PIPEWAIT, long wait);
+~~~
+
+# DESCRIPTION
+
+Set *wait* to 1L to tell libcurl to prefer to wait for a connection to
+confirm or deny that it can do multiplexing before continuing.
+
+When about to perform a new transfer that allows multiplexing, libcurl checks
+for existing connections to use. If no such connection exists it immediately
+continues and creates a fresh new connection to use.
+
+By setting this option to 1 - and having CURLMOPT_PIPELINING(3) enabled
+for the multi handle this transfer is associated with - libcurl instead waits
+for the connection to reveal if it is possible to multiplex on before it
+continues. This enables libcurl to much better keep the number of connections
+to a minimum when using multiplexing protocols.
+
+With this option set, libcurl prefers to wait and reuse an existing connection
+for multiplexing rather than the opposite: prefer to open a new connection
+rather than waiting.
+
+The waiting time is as long as it takes for the connection to get up and for
+libcurl to get the necessary response back that informs it about its protocol
+and support level.
+
+# DEFAULT
+
+0 (off)
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PIPEWAIT, 1L);
+
+ /* now add this easy handle to the multi handle */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.43.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PORT.3 b/docs/libcurl/opts/CURLOPT_PORT.3
deleted file mode 100644
index f29d33ce8..000000000
--- a/docs/libcurl/opts/CURLOPT_PORT.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PORT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PORT \- remote port number to connect to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PORT, long number);
-.fi
-.SH DESCRIPTION
-We discourage using this option since its scope is not obvious and hard to
-predict. Set the preferred port number in the URL instead.
-
-This option sets \fInumber\fP to be the remote port number to connect to,
-instead of the one specified in the URL or the default port for the used
-protocol.
-
-Usually, you just let the URL decide which port to use but this allows the
-application to override that.
-
-While this option accepts a 'long', a port number is an unsigned 16 bit number
-and therefore using a port number lower than zero or over 65535 causes a
-\fBCURLE_BAD_FUNCTION_ARGUMENT\fP error.
-.SH DEFAULT
-By default this is 0 which makes it not used. This also makes port number zero
-impossible to set with this API.
-.SH PROTOCOLS
-Used for all protocols that speak to a port number.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_PORT, 8080L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLINFO_PRIMARY_PORT (3),
-.BR CURLOPT_STDERR (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_PORT.md b/docs/libcurl/opts/CURLOPT_PORT.md
new file mode 100644
index 000000000..42dc80133
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PORT.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PORT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PRIMARY_PORT (3)
+ - CURLOPT_STDERR (3)
+ - CURLOPT_URL (3)
+---
+
+# NAME
+
+CURLOPT_PORT - remote port number to connect to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PORT, long number);
+~~~
+
+# DESCRIPTION
+
+We discourage using this option since its scope is not obvious and hard to
+predict. Set the preferred port number in the URL instead.
+
+This option sets *number* to be the remote port number to connect to,
+instead of the one specified in the URL or the default port for the used
+protocol.
+
+Usually, you just let the URL decide which port to use but this allows the
+application to override that.
+
+While this option accepts a 'long', a port number is an unsigned 16 bit number
+and therefore using a port number lower than zero or over 65535 causes a
+**CURLE_BAD_FUNCTION_ARGUMENT** error.
+
+# DEFAULT
+
+By default this is 0 which makes it not used. This also makes port number zero
+impossible to set with this API.
+
+# PROTOCOLS
+
+Used for all protocols that speak to a port number.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_PORT, 8080L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_POST.3 b/docs/libcurl/opts/CURLOPT_POST.3
deleted file mode 100644
index 6f8100feb..000000000
--- a/docs/libcurl/opts/CURLOPT_POST.3
+++ /dev/null
@@ -1,100 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_POST 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_POST \- make an HTTP POST
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POST, long post);
-.fi
-.SH DESCRIPTION
-A parameter set to 1 tells libcurl to do a regular HTTP post. This also makes
-libcurl use a "Content-Type: application/x-www-form-urlencoded" header. This
-is the most commonly used POST method.
-
-Use one of \fICURLOPT_POSTFIELDS(3)\fP or \fICURLOPT_COPYPOSTFIELDS(3)\fP
-options to specify what data to post and \fICURLOPT_POSTFIELDSIZE(3)\fP or
-\fICURLOPT_POSTFIELDSIZE_LARGE(3)\fP to set the data size.
-
-Optionally, you can provide data to POST using the
-\fICURLOPT_READFUNCTION(3)\fP and \fICURLOPT_READDATA(3)\fP options but then
-you must make sure to not set \fICURLOPT_POSTFIELDS(3)\fP to anything but
-NULL. When providing data with a callback, you must transmit it using chunked
-transfer-encoding or you must set the size of the data with the
-\fICURLOPT_POSTFIELDSIZE(3)\fP or \fICURLOPT_POSTFIELDSIZE_LARGE(3)\fP
-options. To enable chunked encoding, you simply pass in the appropriate
-Transfer-Encoding header, see the post-callback.c example.
-
-You can override the default POST Content-Type: header by setting your own
-with \fICURLOPT_HTTPHEADER(3)\fP.
-
-Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
-You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
-
-If you use POST to an HTTP 1.1 server, you can send data without knowing the
-size before starting the POST if you use chunked encoding. You enable this by
-adding a header like "Transfer-Encoding: chunked" with
-\fICURLOPT_HTTPHEADER(3)\fP. With HTTP 1.0 or without chunked transfer, you
-must specify the size in the request. (Since 7.66.0, libcurl automatically
-uses chunked encoding for POSTs if the size is unknown.)
-
-When setting \fICURLOPT_POST(3)\fP to 1, libcurl automatically sets
-\fICURLOPT_NOBODY(3)\fP and \fICURLOPT_HTTPGET(3)\fP to 0.
-
-If you issue a POST request and then want to make a HEAD or GET using the same
-reused handle, you must explicitly set the new request type using
-\fICURLOPT_NOBODY(3)\fP or \fICURLOPT_HTTPGET(3)\fP or similar.
-
-When setting \fICURLOPT_POST(3)\fP to 0, libcurl resets the request type to
-the default to disable the POST. Typically that would mean it's reset to GET.
-Instead you should set a new request type explicitly as described above.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_POST, 1L);
-
- /* set up the read callback with CURLOPT_READFUNCTION */
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPPOST (3),
-.BR CURLOPT_POSTFIELDS (3),
-.BR CURLOPT_PUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_POST.md b/docs/libcurl/opts/CURLOPT_POST.md
new file mode 100644
index 000000000..96fcd42de
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_POST.md
@@ -0,0 +1,102 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_POST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPPOST (3)
+ - CURLOPT_POSTFIELDS (3)
+ - CURLOPT_PUT (3)
+---
+
+# NAME
+
+CURLOPT_POST - make an HTTP POST
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POST, long post);
+~~~
+
+# DESCRIPTION
+
+A parameter set to 1 tells libcurl to do a regular HTTP post. This also makes
+libcurl use a "Content-Type: application/x-www-form-urlencoded" header. This
+is the most commonly used POST method.
+
+Use one of CURLOPT_POSTFIELDS(3) or CURLOPT_COPYPOSTFIELDS(3)
+options to specify what data to post and CURLOPT_POSTFIELDSIZE(3) or
+CURLOPT_POSTFIELDSIZE_LARGE(3) to set the data size.
+
+Optionally, you can provide data to POST using the
+CURLOPT_READFUNCTION(3) and CURLOPT_READDATA(3) options but then
+you must make sure to not set CURLOPT_POSTFIELDS(3) to anything but
+NULL. When providing data with a callback, you must transmit it using chunked
+transfer-encoding or you must set the size of the data with the
+CURLOPT_POSTFIELDSIZE(3) or CURLOPT_POSTFIELDSIZE_LARGE(3)
+options. To enable chunked encoding, you simply pass in the appropriate
+Transfer-Encoding header, see the post-callback.c example.
+
+You can override the default POST Content-Type: header by setting your own
+with CURLOPT_HTTPHEADER(3).
+
+Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
+You can disable this header with CURLOPT_HTTPHEADER(3) as usual.
+
+If you use POST to an HTTP 1.1 server, you can send data without knowing the
+size before starting the POST if you use chunked encoding. You enable this by
+adding a header like "Transfer-Encoding: chunked" with
+CURLOPT_HTTPHEADER(3). With HTTP 1.0 or without chunked transfer, you
+must specify the size in the request. (Since 7.66.0, libcurl automatically
+uses chunked encoding for POSTs if the size is unknown.)
+
+When setting CURLOPT_POST(3) to 1, libcurl automatically sets
+CURLOPT_NOBODY(3) and CURLOPT_HTTPGET(3) to 0.
+
+If you issue a POST request and then want to make a HEAD or GET using the same
+reused handle, you must explicitly set the new request type using
+CURLOPT_NOBODY(3) or CURLOPT_HTTPGET(3) or similar.
+
+When setting CURLOPT_POST(3) to 0, libcurl resets the request type to the
+default to disable the POST. Typically that means gets reset to GET. Instead
+you should set a new request type explicitly as described above.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_POST, 1L);
+
+ /* set up the read callback with CURLOPT_READFUNCTION */
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3 b/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
deleted file mode 100644
index 08946f286..000000000
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDS.3
+++ /dev/null
@@ -1,123 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_POSTFIELDS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_POSTFIELDS \- data to POST to server
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDS, char *postdata);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter, pointing to the data buffer to use in an HTTP POST
-operation. The data must be formatted and encoded the way you want the server
-to receive it. libcurl does not convert or encode it in any way. For example,
-the web server may assume that this data is URL encoded.
-
-The data pointed to is NOT copied by the library: as a consequence, it must be
-preserved by the calling application until the associated transfer finishes.
-This behavior can be changed (so libcurl does copy the data) by instead using
-the \fICURLOPT_COPYPOSTFIELDS(3)\fP option.
-
-This POST is a normal \fBapplication/x-www-form-urlencoded\fP kind (and
-libcurl sets that Content-Type by default when this option is used), which is
-commonly used by HTML forms. Change Content-Type with
-\fICURLOPT_HTTPHEADER(3)\fP.
-
-You can use \fIcurl_easy_escape(3)\fP to URL encode your data, if
-necessary. It returns a pointer to an encoded string that can be passed as
-\fIpostdata\fP.
-
-Using \fICURLOPT_POSTFIELDS(3)\fP implies setting \fICURLOPT_POST(3)\fP to 1.
-
-If \fICURLOPT_POSTFIELDS(3)\fP is explicitly set to NULL then libcurl gets the
-POST data from the read callback. If you want to send a zero-byte POST set
-\fICURLOPT_POSTFIELDS(3)\fP to an empty string, or set \fICURLOPT_POST(3)\fP
-to 1 and \fICURLOPT_POSTFIELDSIZE(3)\fP to 0.
-
-libcurl assumes this option points to a null-terminated string unless you also
-set \fICURLOPT_POSTFIELDSIZE(3)\fP to specify the length of the provided data,
-which then is strictly required if you want to send off null bytes included in
-the data.
-
-Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header,
-and libcurl adds that header automatically if the POST is either known to be
-larger than 1MB or if the expected size is unknown. You can disable this
-header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
-
-To make \fBmultipart/formdata\fP posts, check out the
-\fICURLOPT_MIMEPOST(3)\fP option combined with \fIcurl_mime_init(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-/* send an application/x-www-form-urlencoded POST */
-CURL *curl = curl_easy_init();
-if(curl) {
- const char *data = "data to send";
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* size of the POST data if strlen() is not good enough */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 12L);
-
- /* pass in a pointer to the data - libcurl does not copy */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
-
- curl_easy_perform(curl);
-}
-
-/* send an application/json POST */
-CURL *curl = curl_easy_init();
-if(curl) {
- const char *json = "{\"name\": \"daniel\"}";
- struct curl_slist *slist1 = NULL;
- slist1 = curl_slist_append(slist1, "Content-Type: application/json");
- slist1 = curl_slist_append(slist1, "Accept: application/json");
-
- /* set custom headers */
- curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1);
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* pass in a pointer to the data - libcurl does not copy */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
-
- curl_easy_perform(curl);
-}
-
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_MIMEPOST (3),
-.BR CURLOPT_POSTFIELDSIZE (3),
-.BR CURLOPT_READFUNCTION (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDS.md b/docs/libcurl/opts/CURLOPT_POSTFIELDS.md
new file mode 100644
index 000000000..409e4100a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDS.md
@@ -0,0 +1,124 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_POSTFIELDS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_COPYPOSTFIELDS (3)
+ - CURLOPT_MIMEPOST (3)
+ - CURLOPT_POSTFIELDSIZE (3)
+ - CURLOPT_READFUNCTION (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_POSTFIELDS - data to POST to server
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDS, char *postdata);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, pointing to the data buffer to use in an
+HTTP POST operation. The data must be formatted and encoded the way you want
+the server to receive it. libcurl does not convert or encode it in any
+way. For example, the web server may assume that this data is URL encoded.
+
+The data pointed to is NOT copied by the library: as a consequence, it must be
+preserved by the calling application until the associated transfer finishes.
+This behavior can be changed (so libcurl does copy the data) by instead using
+the CURLOPT_COPYPOSTFIELDS(3) option.
+
+This POST is a normal **application/x-www-form-urlencoded** kind (and
+libcurl sets that Content-Type by default when this option is used), which is
+commonly used by HTML forms. Change Content-Type with
+CURLOPT_HTTPHEADER(3).
+
+You can use curl_easy_escape(3) to URL encode your data, if
+necessary. It returns a pointer to an encoded string that can be passed as
+*postdata*.
+
+Using CURLOPT_POSTFIELDS(3) implies setting CURLOPT_POST(3) to 1.
+
+If CURLOPT_POSTFIELDS(3) is explicitly set to NULL then libcurl gets the
+POST data from the read callback. If you want to send a zero-byte POST set
+CURLOPT_POSTFIELDS(3) to an empty string, or set CURLOPT_POST(3)
+to 1 and CURLOPT_POSTFIELDSIZE(3) to 0.
+
+libcurl assumes this option points to a null-terminated string unless you also
+set CURLOPT_POSTFIELDSIZE(3) to specify the length of the provided data,
+which then is strictly required if you want to send off null bytes included in
+the data.
+
+Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header,
+and libcurl adds that header automatically if the POST is either known to be
+larger than 1MB or if the expected size is unknown. You can disable this
+header with CURLOPT_HTTPHEADER(3) as usual.
+
+To make **multipart/formdata** posts, check out the
+CURLOPT_MIMEPOST(3) option combined with curl_mime_init(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+/* send an application/x-www-form-urlencoded POST */
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ const char *data = "data to send";
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* size of the POST data if strlen() is not good enough */
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 12L);
+
+ /* pass in a pointer to the data - libcurl does not copy */
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
+ curl_easy_perform(curl);
+ }
+
+ /* send an application/json POST */
+ curl = curl_easy_init();
+ if(curl) {
+ const char *json = "{\"name\": \"daniel\"}";
+ struct curl_slist *slist1 = NULL;
+ slist1 = curl_slist_append(slist1, "Content-Type: application/json");
+ slist1 = curl_slist_append(slist1, "Accept: application/json");
+
+ /* set custom headers */
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist1);
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* pass in a pointer to the data - libcurl does not copy */
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3 b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3
deleted file mode 100644
index e519dd7ac..000000000
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_POSTFIELDSIZE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_POSTFIELDSIZE \- size of POST data pointed to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE, long size);
-.fi
-.SH DESCRIPTION
-If you want to post static data to the server without having libcurl do a
-strlen() to measure the data size, this option must be used. When this option
-is used you can post fully binary data, which otherwise is likely to fail. If
-this size is set to -1, libcurl uses strlen() to get the size or relies on the
-\fICURLOPT_READFUNCTION(3)\fP (if used) to signal the end of data.
-
-If you post more than 2GB, use \fICURLOPT_POSTFIELDSIZE_LARGE(3)\fP.
-.SH DEFAULT
--1
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- const char *data = "data to send";
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* size of the POST data */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(data));
-
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_POSTFIELDS (3),
-.BR CURLOPT_POSTFIELDSIZE_LARGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md
new file mode 100644
index 000000000..d086809cb
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_POSTFIELDSIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_POSTFIELDS (3)
+ - CURLOPT_POSTFIELDSIZE_LARGE (3)
+---
+
+# NAME
+
+CURLOPT_POSTFIELDSIZE - size of POST data pointed to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE, long size);
+~~~
+
+# DESCRIPTION
+
+If you want to post static data to the server without having libcurl do a
+strlen() to measure the data size, this option must be used. When this option
+is used you can post fully binary data, which otherwise is likely to fail. If
+this size is set to -1, libcurl uses strlen() to get the size or relies on the
+CURLOPT_READFUNCTION(3) (if used) to signal the end of data.
+
+If you post more than 2GB, use CURLOPT_POSTFIELDSIZE_LARGE(3).
+
+# DEFAULT
+
+-1
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+#include <string.h> /* for strlen */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ const char *data = "data to send";
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* size of the POST data */
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(data));
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3 b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3
deleted file mode 100644
index 22dabf31a..000000000
--- a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_POSTFIELDSIZE_LARGE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_POSTFIELDSIZE_LARGE \- size of POST data pointed to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE_LARGE,
- curl_off_t size);
-.SH DESCRIPTION
-If you want to post static data to the server without having libcurl do a
-strlen() to measure the data size, this option must be used. When this option
-is used you can post fully binary data, which otherwise is likely to fail. If
-this size is set to -1, libcurl uses strlen() to get the size or relies on the
-\fICURLOPT_READFUNCTION(3)\fP (if used) to signal the end of data.
-.SH DEFAULT
--1
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- const char *data = large_chunk;
- curl_off_t length_of_data; /* set somehow */
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* size of the POST data */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, length_of_data);
-
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_COPYPOSTFIELDS (3),
-.BR CURLOPT_POSTFIELDS (3),
-.BR CURLOPT_POSTFIELDSIZE (3)
diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md
new file mode 100644
index 000000000..36fc0ff95
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_POSTFIELDSIZE_LARGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_COPYPOSTFIELDS (3)
+ - CURLOPT_POSTFIELDS (3)
+ - CURLOPT_POSTFIELDSIZE (3)
+---
+
+# NAME
+
+CURLOPT_POSTFIELDSIZE_LARGE - size of POST data pointed to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTFIELDSIZE_LARGE,
+ curl_off_t size);
+~~~
+
+# DESCRIPTION
+
+If you want to post static data to the server without having libcurl do a
+strlen() to measure the data size, this option must be used. When this option
+is used you can post fully binary data, which otherwise is likely to fail. If
+this size is set to -1, libcurl uses strlen() to get the size or relies on the
+CURLOPT_READFUNCTION(3) (if used) to signal the end of data.
+
+# DEFAULT
+
+-1
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+extern char *large_chunk; /* pointer to somewhere */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ const char *data = large_chunk;
+ curl_off_t length_of_data; /* set somehow */
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* size of the POST data */
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, length_of_data);
+
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_POSTQUOTE.3 b/docs/libcurl/opts/CURLOPT_POSTQUOTE.3
deleted file mode 100644
index 556895669..000000000
--- a/docs/libcurl/opts/CURLOPT_POSTQUOTE.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_POSTQUOTE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_POSTQUOTE \- (S)FTP commands to run after the transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTQUOTE,
- struct curl_slist *cmds);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a linked list of FTP or SFTP commands to pass to the server
-after your FTP transfer request. The commands are only issues if no error
-occur. The linked list should be a fully valid list of struct curl_slist
-structs properly filled in as described for \fICURLOPT_QUOTE(3)\fP.
-
-Disable this operation again by setting a NULL to this option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SFTP and FTP
-.SH EXAMPLE
-.nf
-struct curl_slist *cmdlist = NULL;
-cmdlist = curl_slist_append(cmdlist, "RNFR source-name");
-cmdlist = curl_slist_append(cmdlist, "RNTO new-name");
-
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
-
- /* pass in the FTP commands to run after the transfer */
- curl_easy_setopt(curl, CURLOPT_POSTQUOTE, cmdlist);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If support for the protocols are built-in.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_PREQUOTE (3),
-.BR CURLOPT_QUOTE (3)
diff --git a/docs/libcurl/opts/CURLOPT_POSTQUOTE.md b/docs/libcurl/opts/CURLOPT_POSTQUOTE.md
new file mode 100644
index 000000000..300a1f2c5
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_POSTQUOTE.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_POSTQUOTE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PREQUOTE (3)
+ - CURLOPT_QUOTE (3)
+---
+
+# NAME
+
+CURLOPT_POSTQUOTE - (S)FTP commands to run after the transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTQUOTE,
+ struct curl_slist *cmds);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of FTP or SFTP commands to pass to the server
+after your FTP transfer request. The commands are only issues if no error
+occur. The linked list should be a fully valid list of struct curl_slist
+structs properly filled in as described for CURLOPT_QUOTE(3).
+
+Disable this operation again by setting a NULL to this option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SFTP and FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct curl_slist *cmdlist = NULL;
+ cmdlist = curl_slist_append(cmdlist, "RNFR source-name");
+ cmdlist = curl_slist_append(cmdlist, "RNTO new-name");
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
+
+ /* pass in the FTP commands to run after the transfer */
+ curl_easy_setopt(curl, CURLOPT_POSTQUOTE, cmdlist);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If support for the protocols are built-in.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_POSTREDIR.3 b/docs/libcurl/opts/CURLOPT_POSTREDIR.3
deleted file mode 100644
index 38b9e8c95..000000000
--- a/docs/libcurl/opts/CURLOPT_POSTREDIR.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_POSTREDIR 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_POSTREDIR \- how to act on an HTTP POST redirect
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTREDIR,
- long bitmask);
-.SH DESCRIPTION
-Pass a bitmask to control how libcurl acts on redirects after POSTs that get a
-301, 302 or 303 response back. A parameter with bit 0 set (value
-\fBCURL_REDIR_POST_301\fP) tells the library to respect RFC 7231 (section
-6.4.2 to 6.4.4) and not convert POST requests into GET requests when following
-a 301 redirection. Setting bit 1 (value \fBCURL_REDIR_POST_302\fP) makes
-libcurl maintain the request method after a 302 redirect whilst setting bit 2
-(value \fBCURL_REDIR_POST_303\fP) makes libcurl maintain the request method
-after a 303 redirect. The value \fBCURL_REDIR_POST_ALL\fP is a convenience
-define that sets all three bits.
-
-The non-RFC behavior is ubiquitous in web browsers, so the library does the
-conversion by default to maintain consistency. However, a server may require a
-POST to remain a POST after such a redirection. This option is meaningful only
-when setting \fICURLOPT_FOLLOWLOCATION(3)\fP.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP(S)
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* a silly POST example */
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "data=true");
-
- /* example.com is redirected, so we tell libcurl to send POST on 301, 302 and
- 303 HTTP response codes */
- curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.17.1. This option was known as CURLOPT_POST301 up to 7.19.0 as it
-only supported the 301 then. CURL_REDIR_POST_303 was added in 7.26.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_EFFECTIVE_METHOD (3),
-.BR CURLINFO_REDIRECT_COUNT (3),
-.BR CURLOPT_FOLLOWLOCATION (3),
-.BR CURLOPT_MAXREDIRS (3),
-.BR CURLOPT_POSTFIELDS (3)
diff --git a/docs/libcurl/opts/CURLOPT_POSTREDIR.md b/docs/libcurl/opts/CURLOPT_POSTREDIR.md
new file mode 100644
index 000000000..0ca04a98c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_POSTREDIR.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_POSTREDIR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_EFFECTIVE_METHOD (3)
+ - CURLINFO_REDIRECT_COUNT (3)
+ - CURLOPT_FOLLOWLOCATION (3)
+ - CURLOPT_MAXREDIRS (3)
+ - CURLOPT_POSTFIELDS (3)
+---
+
+# NAME
+
+CURLOPT_POSTREDIR - how to act on an HTTP POST redirect
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_POSTREDIR,
+ long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a bitmask to control how libcurl acts on redirects after POSTs that get a
+301, 302 or 303 response back. A parameter with bit 0 set (value
+**CURL_REDIR_POST_301**) tells the library to respect RFC 7231 (section
+6.4.2 to 6.4.4) and not convert POST requests into GET requests when following
+a 301 redirection. Setting bit 1 (value **CURL_REDIR_POST_302**) makes
+libcurl maintain the request method after a 302 redirect whilst setting bit 2
+(value **CURL_REDIR_POST_303**) makes libcurl maintain the request method
+after a 303 redirect. The value **CURL_REDIR_POST_ALL** is a convenience
+define that sets all three bits.
+
+The non-RFC behavior is ubiquitous in web browsers, so the library does the
+conversion by default to maintain consistency. However, a server may require a
+POST to remain a POST after such a redirection. This option is meaningful only
+when setting CURLOPT_FOLLOWLOCATION(3).
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP(S)
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* a silly POST example */
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "data=true");
+
+ /* example.com is redirected, so we tell libcurl to send POST on 301,
+ 302 and 303 HTTP response codes */
+ curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.17.1. This option was known as CURLOPT_POST301 up to 7.19.0 as it
+only supported the 301 then. CURL_REDIR_POST_303 was added in 7.26.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PREQUOTE.3 b/docs/libcurl/opts/CURLOPT_PREQUOTE.3
deleted file mode 100644
index b216e9e67..000000000
--- a/docs/libcurl/opts/CURLOPT_PREQUOTE.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PREQUOTE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PREQUOTE \- commands to run before an FTP transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREQUOTE,
- struct curl_slist *cmds);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a linked list of FTP commands to pass to the server after
-the transfer type is set. The linked list should be a fully valid list of
-struct curl_slist structs properly filled in as described for
-\fICURLOPT_QUOTE(3)\fP. Disable this operation again by setting a NULL to this
-option.
-
-These commands are not performed when a directory listing is performed, only
-for file transfers.
-
-While \fICURLOPT_QUOTE(3)\fP and \fICURLOPT_POSTQUOTE(3)\fP work for SFTP,
-this option does not.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-struct curl_slist *cmdlist = NULL;
-cmdlist = curl_slist_append(cmdlist, "SYST");
-
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
-
- /* pass in the FTP commands to run */
- curl_easy_setopt(curl, CURLOPT_PREQUOTE, cmdlist);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with the protocol support
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_POSTQUOTE (3),
-.BR CURLOPT_QUOTE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PREQUOTE.md b/docs/libcurl/opts/CURLOPT_PREQUOTE.md
new file mode 100644
index 000000000..e5192039d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PREQUOTE.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PREQUOTE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_POSTQUOTE (3)
+ - CURLOPT_QUOTE (3)
+---
+
+# NAME
+
+CURLOPT_PREQUOTE - commands to run before an FTP transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREQUOTE,
+ struct curl_slist *cmds);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of FTP commands to pass to the server after
+the transfer type is set. The linked list should be a fully valid list of
+struct curl_slist structs properly filled in as described for
+CURLOPT_QUOTE(3). Disable this operation again by setting a NULL to this
+option.
+
+These commands are not performed when a directory listing is performed, only
+for file transfers.
+
+While CURLOPT_QUOTE(3) and CURLOPT_POSTQUOTE(3) work for SFTP,
+this option does not.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct curl_slist *cmdlist = NULL;
+ cmdlist = curl_slist_append(cmdlist, "SYST");
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
+
+ /* pass in the FTP commands to run */
+ curl_easy_setopt(curl, CURLOPT_PREQUOTE, cmdlist);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with the protocol support
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PREREQDATA.3 b/docs/libcurl/opts/CURLOPT_PREREQDATA.3
deleted file mode 100644
index 617ecf07b..000000000
--- a/docs/libcurl/opts/CURLOPT_PREREQDATA.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) Max Dymond, <max.dymond@microsoft.com>, 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PREREQDATA 3 "2 Aug 2021" libcurl libcurl
-.SH NAME
-CURLOPT_PREREQDATA \- pointer passed to the pre-request callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREREQDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP that is untouched by libcurl and passed as the first
-argument in the pre-request callback set with \fICURLOPT_PREREQFUNCTION(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static int prereq_callback(void *clientp,
- char *conn_primary_ip,
- char *conn_local_ip,
- int conn_primary_port,
- int conn_local_port)
-{
- printf("Connection made to %s:%s\\n", conn_primary_ip, conn_primary_port);
- return CURL_PREREQFUNC_OK;
-}
-
-{
- struct data prereq_data;
- curl_easy_setopt(CURL *handle, CURLOPT_PREREQFUNCTION, prereq_callback);
- curl_easy_setopt(CURL *handle, CURLOPT_PREREQDATA, &prereq_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.80.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_PRIMARY_IP (3),
-.BR CURLINFO_PRIMARY_PORT (3),
-.BR CURLOPT_PREREQFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_PREREQDATA.md b/docs/libcurl/opts/CURLOPT_PREREQDATA.md
new file mode 100644
index 000000000..14ba8e302
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PREREQDATA.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PREREQDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PRIMARY_IP (3)
+ - CURLINFO_PRIMARY_PORT (3)
+ - CURLOPT_PREREQFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_PREREQDATA - pointer passed to the pre-request callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREREQDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* that is untouched by libcurl and passed as the first
+argument in the pre-request callback set with CURLOPT_PREREQFUNCTION(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static int prereq_callback(void *clientp,
+ char *conn_primary_ip,
+ char *conn_local_ip,
+ int conn_primary_port,
+ int conn_local_port)
+{
+ printf("Connection made to %s:%d\n", conn_primary_ip, conn_primary_port);
+ return CURL_PREREQFUNC_OK;
+}
+
+int main(void)
+{
+ struct priv prereq_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_PREREQFUNCTION, prereq_callback);
+ curl_easy_setopt(curl, CURLOPT_PREREQDATA, &prereq_data);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.80.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3 b/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3
deleted file mode 100644
index 4d13a5491..000000000
--- a/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3
+++ /dev/null
@@ -1,107 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) Max Dymond, <max.dymond@microsoft.com>, 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PREREQFUNCTION 3 "2 Aug 2021" libcurl libcurl
-.SH NAME
-CURLOPT_PREREQFUNCTION \- user callback called when a connection has been
-established, but before a request has been made.
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-/* These are the return codes for the pre-request callback. */
-#define CURL_PREREQFUNC_OK 0
-#define CURL_PREREQFUNC_ABORT 1 /* fail the entire transfer */
-
-int prereq_callback(void *clientp,
- char *conn_primary_ip,
- char *conn_local_ip,
- int conn_primary_port,
- int conn_local_port);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREREQFUNCTION, prereq_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This function gets called by libcurl after a connection has been established
-or a connection has been reused (including any SSL handshaking), but before any
-request is actually made on the connection. For example, for HTTP, this
-callback is called once a connection has been established to the server, but
-before a GET/HEAD/POST/etc request has been sent.
-
-This function may be called multiple times if redirections are enabled and are
-being followed (see \fICURLOPT_FOLLOWLOCATION(3)\fP).
-
-The callback function must return \fICURL_PREREQFUNC_OK\fP on success, or
-\fICURL_PREREQFUNC_ABORT\fP to cause the transfer to fail.
-
-This function is passed the following arguments:
-.IP conn_primary_ip
-A null-terminated pointer to a C string containing the primary IP of the
-remote server established with this connection. For FTP, this is the IP for
-the control connection. IPv6 addresses are represented without surrounding
-brackets.
-.IP conn_local_ip
-A null-terminated pointer to a C string containing the originating IP for this
-connection. IPv6 addresses are represented without surrounding brackets.
-.IP conn_primary_port
-The primary port number on the remote server established with this connection.
-For FTP, this is the port for the control connection. This can be a TCP or a
-UDP port number depending on the protocol.
-.IP conn_local_port
-The originating port number for this connection. This can be a TCP or a UDP
-port number depending on the protocol.
-.IP clientp
-The pointer you set with \fICURLOPT_PREREQDATA(3)\fP.
-.SH DEFAULT
-By default, this is NULL and unused.
-.SH PROTOCOLS
-ALL
-.SH EXAMPLE
-.nf
-static int prereq_callback(void *clientp,
- char *conn_primary_ip,
- char *conn_local_ip,
- int conn_primary_port,
- int conn_local_port)
-{
- printf("Connection made to %s:%s\\n", conn_primary_ip, conn_primary_port);
- return CURL_PREREQFUNC_OK;
-}
-
-{
- struct data prereq_data;
- curl_easy_setopt(CURL *handle, CURLOPT_PREREQFUNCTION, prereq_callback);
- curl_easy_setopt(CURL *handle, CURLOPT_PREREQDATA, &prereq_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.80.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_PRIMARY_IP (3),
-.BR CURLINFO_PRIMARY_PORT (3),
-.BR CURLOPT_PREREQDATA (3)
diff --git a/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.md b/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.md
new file mode 100644
index 000000000..c81408494
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.md
@@ -0,0 +1,125 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PREREQFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PRIMARY_IP (3)
+ - CURLINFO_PRIMARY_PORT (3)
+ - CURLOPT_PREREQDATA (3)
+---
+
+# NAME
+
+CURLOPT_PREREQFUNCTION - user callback called when a connection has been
+established, but before a request has been made.
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+/* These are the return codes for the pre-request callback. */
+#define CURL_PREREQFUNC_OK 0
+#define CURL_PREREQFUNC_ABORT 1 /* fail the entire transfer */
+
+int prereq_callback(void *clientp,
+ char *conn_primary_ip,
+ char *conn_local_ip,
+ int conn_primary_port,
+ int conn_local_port);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREREQFUNCTION, prereq_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This function gets called by libcurl after a connection has been established
+or a connection has been reused (including any SSL handshaking), but before any
+request is actually made on the connection. For example, for HTTP, this
+callback is called once a connection has been established to the server, but
+before a GET/HEAD/POST/etc request has been sent.
+
+This function may be called multiple times if redirections are enabled and are
+being followed (see CURLOPT_FOLLOWLOCATION(3)).
+
+The callback function must return *CURL_PREREQFUNC_OK* on success, or
+*CURL_PREREQFUNC_ABORT* to cause the transfer to fail.
+
+This function is passed the following arguments:
+
+## conn_primary_ip
+
+A null-terminated pointer to a C string containing the primary IP of the
+remote server established with this connection. For FTP, this is the IP for
+the control connection. IPv6 addresses are represented without surrounding
+brackets.
+
+## conn_local_ip
+
+A null-terminated pointer to a C string containing the originating IP for this
+connection. IPv6 addresses are represented without surrounding brackets.
+
+## conn_primary_port
+
+The primary port number on the remote server established with this connection.
+For FTP, this is the port for the control connection. This can be a TCP or a
+UDP port number depending on the protocol.
+
+## conn_local_port
+
+The originating port number for this connection. This can be a TCP or a UDP
+port number depending on the protocol.
+
+## clientp
+
+The pointer you set with CURLOPT_PREREQDATA(3).
+
+# DEFAULT
+
+By default, this is NULL and unused.
+
+# PROTOCOLS
+
+ALL
+
+# EXAMPLE
+
+~~~c
+struct priv {
+ void *custom;
+};
+
+static int prereq_callback(void *clientp,
+ char *conn_primary_ip,
+ char *conn_local_ip,
+ int conn_primary_port,
+ int conn_local_port)
+{
+ printf("Connection made to %s:%d\n", conn_primary_ip, conn_primary_port);
+ return CURL_PREREQFUNC_OK;
+}
+
+int main(void)
+{
+ struct priv prereq_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_PREREQFUNCTION, prereq_callback);
+ curl_easy_setopt(curl, CURLOPT_PREREQDATA, &prereq_data);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.80.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PRE_PROXY.3 b/docs/libcurl/opts/CURLOPT_PRE_PROXY.3
deleted file mode 100644
index 6e06ab822..000000000
--- a/docs/libcurl/opts/CURLOPT_PRE_PROXY.3
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PRE_PROXY 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PRE_PROXY \- pre-proxy host to use
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRE_PROXY, char *preproxy);
-.fi
-.SH DESCRIPTION
-Set the \fIpreproxy\fP to use for the upcoming request. The parameter
-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].
-
-To specify port number in this string, append :[port] to the end of the host
-name. The proxy's port number may optionally be specified with the separate
-option \fICURLOPT_PROXYPORT(3)\fP. If not specified, libcurl defaults to using
-port 1080 for proxies.
-
-A pre proxy is a SOCKS proxy that curl connects to before it connects to the
-HTTP(S) proxy specified in the \fICURLOPT_PROXY(3)\fP option. The pre proxy
-can only be a SOCKS proxy.
-
-The pre proxy string should be prefixed with [scheme]:// to specify which kind
-of socks is used. Use socks4://, socks4a://, socks5:// or socks5h:// (the last
-one to enable socks5 and asking the proxy to do the resolving, also known as
-\fICURLPROXY_SOCKS5_HOSTNAME\fP type) to request the specific SOCKS version to
-be used. Otherwise SOCKS4 is used as default.
-
-Setting the pre proxy string to "" (an empty string) explicitly disables the
-use of a pre proxy.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-Default is NULL, meaning no pre proxy is used.
-
-When you set a host name to use, do not assume that there is any particular
-single port number used widely for proxies. Specify it!
-.SH PROTOCOLS
-All except file://. Note that some protocols do not work well over proxy.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/file.txt");
- curl_easy_setopt(curl, CURLOPT_PRE_PROXY, "socks4://socks-proxy:1080");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80");
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.SH RETURN VALUE
-Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_HTTPPROXYTUNNEL (3)
diff --git a/docs/libcurl/opts/CURLOPT_PRE_PROXY.md b/docs/libcurl/opts/CURLOPT_PRE_PROXY.md
new file mode 100644
index 000000000..1afe831e3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PRE_PROXY.md
@@ -0,0 +1,84 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PRE_PROXY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPPROXYTUNNEL (3)
+ - CURLOPT_PROXY (3)
+---
+
+# NAME
+
+CURLOPT_PRE_PROXY - pre-proxy host to use
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRE_PROXY, char *preproxy);
+~~~
+
+# DESCRIPTION
+
+Set the *preproxy* to use for the upcoming request. The parameter should be a
+char * to a null-terminated string holding the hostname 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
+name. The proxy's port number may optionally be specified with the separate
+option CURLOPT_PROXYPORT(3). If not specified, libcurl defaults to using
+port 1080 for proxies.
+
+A pre proxy is a SOCKS proxy that curl connects to before it connects to the
+HTTP(S) proxy specified in the CURLOPT_PROXY(3) option. The pre proxy
+can only be a SOCKS proxy.
+
+The pre proxy string should be prefixed with [scheme]:// to specify which kind
+of socks is used. Use socks4://, socks4a://, socks5:// or socks5h:// (the last
+one to enable socks5 and asking the proxy to do the resolving, also known as
+*CURLPROXY_SOCKS5_HOSTNAME* type) to request the specific SOCKS version to
+be used. Otherwise SOCKS4 is used as default.
+
+Setting the pre proxy string to "" (an empty string) explicitly disables the
+use of a pre proxy.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+Default is NULL, meaning no pre proxy is used.
+
+When you set a hostname to use, do not assume that there is any particular
+single port number used widely for proxies. Specify it!
+
+# PROTOCOLS
+
+All except file://. Note that some protocols do not work well over proxy.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/file.txt");
+ curl_easy_setopt(curl, CURLOPT_PRE_PROXY, "socks4://socks-proxy:1080");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PRIVATE.3 b/docs/libcurl/opts/CURLOPT_PRIVATE.3
deleted file mode 100644
index 20da94775..000000000
--- a/docs/libcurl/opts/CURLOPT_PRIVATE.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PRIVATE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PRIVATE \- store a private pointer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRIVATE, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a void * as parameter, pointing to data that should be associated with
-this curl handle. The pointer can subsequently be retrieved using
-\fIcurl_easy_getinfo(3)\fP with the \fICURLINFO_PRIVATE(3)\fP option. libcurl
-itself never does anything with this data.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-struct private secrets;
-if(curl) {
- struct private *extracted;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* store a pointer to our private struct */
- curl_easy_setopt(curl, CURLOPT_PRIVATE, &secrets);
-
- curl_easy_perform(curl);
-
- /* we can extract the private pointer again too */
- curl_easy_getinfo(curl, CURLINFO_PRIVATE, &extracted);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.3
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_PRIVATE (3),
-.BR CURLOPT_STDERR (3),
-.BR CURLOPT_VERBOSE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PRIVATE.md b/docs/libcurl/opts/CURLOPT_PRIVATE.md
new file mode 100644
index 000000000..571a681b9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PRIVATE.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PRIVATE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PRIVATE (3)
+ - CURLOPT_STDERR (3)
+ - CURLOPT_VERBOSE (3)
+---
+
+# NAME
+
+CURLOPT_PRIVATE - store a private pointer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRIVATE, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a void * as parameter, pointing to data that should be associated with
+this curl handle. The pointer can subsequently be retrieved using
+curl_easy_getinfo(3) with the CURLINFO_PRIVATE(3) option. libcurl itself
+never does anything with this data.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct private {
+ void *custom;
+};
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ struct private secrets;
+ if(curl) {
+ struct private *extracted;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* store a pointer to our private struct */
+ curl_easy_setopt(curl, CURLOPT_PRIVATE, &secrets);
+
+ curl_easy_perform(curl);
+
+ /* we can extract the private pointer again too */
+ curl_easy_getinfo(curl, CURLINFO_PRIVATE, &extracted);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.3
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3 b/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3
deleted file mode 100644
index b83c1d923..000000000
--- a/docs/libcurl/opts/CURLOPT_PROGRESSDATA.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROGRESSDATA 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROGRESSDATA \- pointer passed to the progress callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP that is untouched by libcurl and passed as the first
-argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION(3)\fP.
-.SH DEFAULT
-The default value of this parameter is NULL.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- struct progress {
- char *private;
- size_t size;
- };
-
- static size_t progress_callback(void *clientp,
- double dltotal,
- double dlnow,
- double ultotal,
- double ulnow)
- {
- struct memory *progress = (struct progress *)clientp;
-
- /* use the values */
-
- return 0; /* all is good */
- }
-
- struct progress data;
-
- /* pass struct to callback */
- curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, &data);
-
- curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, progress_callback);
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_PROGRESSFUNCTION (3),
-.BR CURLOPT_XFERINFOFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROGRESSDATA.md b/docs/libcurl/opts/CURLOPT_PROGRESSDATA.md
new file mode 100644
index 000000000..276bee827
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROGRESSDATA.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROGRESSDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROGRESSFUNCTION (3)
+ - CURLOPT_XFERINFOFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_PROGRESSDATA - pointer passed to the progress callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* that is untouched by libcurl and passed as the first
+argument in the progress callback set with CURLOPT_PROGRESSFUNCTION(3).
+
+# DEFAULT
+
+The default value of this parameter is NULL.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct progress {
+ char *private;
+ size_t size;
+};
+
+static size_t progress_callback(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow)
+{
+ struct progress *memory = clientp;
+ printf("private: %p\n", memory->private);
+
+ /* use the values */
+
+ return 0; /* all is good */
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct progress data;
+
+ /* pass struct to callback */
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3 b/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3
deleted file mode 100644
index 809cf387d..000000000
--- a/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.3
+++ /dev/null
@@ -1,119 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROGRESSFUNCTION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROGRESSFUNCTION \- progress meter callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int progress_callback(void *clientp,
- double dltotal,
- double dlnow,
- double ultotal,
- double ulnow);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSFUNCTION,
- progress_callback);
-.fi
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This option is deprecated and we encourage users to use the
-newer \fICURLOPT_XFERINFOFUNCTION(3)\fP instead, if you can.
-
-This function gets called by libcurl instead of its internal equivalent with a
-frequent interval. While data is being transferred it is invoked frequently,
-and during slow periods like when nothing is being transferred it can slow
-down to about one call per second.
-
-\fIclientp\fP is the pointer set with \fICURLOPT_PROGRESSDATA(3)\fP, it is not
-used by libcurl but is only passed along from the application to the callback.
-
-The callback gets told how much data libcurl is about to transfer and has
-transferred, in number of bytes. \fIdltotal\fP is the total number of bytes
-libcurl expects to download in this transfer. \fIdlnow\fP is the number of
-bytes downloaded so far. \fIultotal\fP is the total number of bytes libcurl
-expects to upload in this transfer. \fIulnow\fP is the number of bytes
-uploaded so far.
-
-Unknown/unused argument values passed to the callback are be set to zero (like
-if you only download data, the upload size remains 0). Many times the callback
-is called one or more times first, before it knows the data sizes so a program
-must be made to handle that.
-
-If your callback function returns CURL_PROGRESSFUNC_CONTINUE it causes libcurl
-to continue executing the default progress function.
-
-Returning any other non-zero value from this callback makes libcurl abort the
-transfer and return \fICURLE_ABORTED_BY_CALLBACK\fP.
-
-If you transfer data with the multi interface, this function is not called
-during periods of idleness unless you call the appropriate libcurl function
-that performs transfers.
-
-\fICURLOPT_NOPROGRESS(3)\fP must be set to 0 to make this function actually
-get called.
-.SH DEFAULT
-By default, libcurl has an internal progress meter. That is rarely wanted by
-users.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- struct progress {
- char *private;
- size_t size;
- };
-
- static size_t progress_callback(void *clientp,
- double dltotal,
- double dlnow,
- double ultotal,
- double ulnow)
- {
- struct progress *memory = (struct progress *)clientp;
-
- /* use the values */
-
- return 0; /* all is good */
- }
-
- struct progress data;
-
- /* pass struct to callback */
- curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, &data);
-
- curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, progress_callback);
-.fi
-.SH AVAILABILITY
-Deprecated since 7.32.0.
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_VERBOSE (3),
-.BR CURLOPT_NOPROGRESS (3),
-.BR CURLOPT_XFERINFOFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.md b/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.md
new file mode 100644
index 000000000..19d84c889
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROGRESSFUNCTION.md
@@ -0,0 +1,125 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROGRESSFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_NOPROGRESS (3)
+ - CURLOPT_VERBOSE (3)
+ - CURLOPT_XFERINFOFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_PROGRESSFUNCTION - progress meter callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int progress_callback(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROGRESSFUNCTION,
+ progress_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This option is deprecated and we encourage users to use the
+newer CURLOPT_XFERINFOFUNCTION(3) instead, if you can.
+
+This function gets called by libcurl instead of its internal equivalent with a
+frequent interval. While data is being transferred it is invoked frequently,
+and during slow periods like when nothing is being transferred it can slow
+down to about one call per second.
+
+*clientp* is the pointer set with CURLOPT_PROGRESSDATA(3), it is not
+used by libcurl but is only passed along from the application to the callback.
+
+The callback gets told how much data libcurl is about to transfer and has
+transferred, in number of bytes. *dltotal* is the total number of bytes
+libcurl expects to download in this transfer. *dlnow* is the number of
+bytes downloaded so far. *ultotal* is the total number of bytes libcurl
+expects to upload in this transfer. *ulnow* is the number of bytes
+uploaded so far.
+
+Unknown/unused argument values passed to the callback are be set to zero (like
+if you only download data, the upload size remains 0). Many times the callback
+is called one or more times first, before it knows the data sizes so a program
+must be made to handle that.
+
+If your callback function returns CURL_PROGRESSFUNC_CONTINUE it causes libcurl
+to continue executing the default progress function.
+
+Returning any other non-zero value from this callback makes libcurl abort the
+transfer and return *CURLE_ABORTED_BY_CALLBACK*.
+
+If you transfer data with the multi interface, this function is not called
+during periods of idleness unless you call the appropriate libcurl function
+that performs transfers.
+
+CURLOPT_NOPROGRESS(3) must be set to 0 to make this function actually
+get called.
+
+# DEFAULT
+
+By default, libcurl has an internal progress meter. That is rarely wanted by
+users.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct progress {
+ char *private;
+ size_t size;
+};
+
+static size_t progress_callback(void *clientp,
+ double dltotal,
+ double dlnow,
+ double ultotal,
+ double ulnow)
+{
+ struct progress *memory = clientp;
+ printf("private: %p\n", memory->private);
+
+ /* use the values */
+
+ return 0; /* all is good */
+}
+
+int main(void)
+{
+ struct progress data;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* pass struct to callback */
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Deprecated since 7.32.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_PROTOCOLS.3 b/docs/libcurl/opts/CURLOPT_PROTOCOLS.3
deleted file mode 100644
index f252e98d4..000000000
--- a/docs/libcurl/opts/CURLOPT_PROTOCOLS.3
+++ /dev/null
@@ -1,103 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROTOCOLS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROTOCOLS \- allowed protocols
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS, long bitmask);
-.fi
-.SH DESCRIPTION
-This option is deprecated. We strongly recommend using
-\fICURLOPT_PROTOCOLS_STR(3)\fP instead because this option cannot control all
-available protocols!
-
-Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
-limits what protocols libcurl may use in the transfer. This allows you to have
-a libcurl built to support a wide range of protocols but still limit specific
-transfers to only be allowed to use a subset of them. By default libcurl
-accepts all protocols it supports (\fICURLPROTO_ALL\fP). See also
-\fICURLOPT_REDIR_PROTOCOLS(3)\fP.
-
-These are the available protocol defines:
-.nf
-CURLPROTO_DICT
-CURLPROTO_FILE
-CURLPROTO_FTP
-CURLPROTO_FTPS
-CURLPROTO_GOPHER
-CURLPROTO_HTTP
-CURLPROTO_HTTPS
-CURLPROTO_IMAP
-CURLPROTO_IMAPS
-CURLPROTO_LDAP
-CURLPROTO_LDAPS
-CURLPROTO_POP3
-CURLPROTO_POP3S
-CURLPROTO_RTMP
-CURLPROTO_RTMPE
-CURLPROTO_RTMPS
-CURLPROTO_RTMPT
-CURLPROTO_RTMPTE
-CURLPROTO_RTMPTS
-CURLPROTO_RTSP
-CURLPROTO_SCP
-CURLPROTO_SFTP
-CURLPROTO_SMB
-CURLPROTO_SMBS
-CURLPROTO_SMTP
-CURLPROTO_SMTPS
-CURLPROTO_TELNET
-CURLPROTO_TFTP
-.fi
-.SH DEFAULT
-All protocols built-in.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- /* pass in the URL from an external source */
- curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
-
- /* only allow HTTP, TFTP and SFTP */
- curl_easy_setopt(curl, CURLOPT_PROTOCOLS,
- CURLPROTO_HTTP | CURLPROTO_TFTP | CURLPROTO_SFTP);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.4. Deprecated since 7.85.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DEFAULT_PROTOCOL (3),
-.BR CURLOPT_REDIR_PROTOCOLS (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROTOCOLS.md b/docs/libcurl/opts/CURLOPT_PROTOCOLS.md
new file mode 100644
index 000000000..a4d1a5a7c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROTOCOLS.md
@@ -0,0 +1,104 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROTOCOLS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEFAULT_PROTOCOL (3)
+ - CURLOPT_REDIR_PROTOCOLS (3)
+ - CURLOPT_URL (3)
+---
+
+# NAME
+
+CURLOPT_PROTOCOLS - allowed protocols
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS, long bitmask);
+~~~
+
+# DESCRIPTION
+
+This option is deprecated. We strongly recommend using
+CURLOPT_PROTOCOLS_STR(3) instead because this option cannot control all
+available protocols!
+
+Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
+limits what protocols libcurl may use in the transfer. This allows you to have
+a libcurl built to support a wide range of protocols but still limit specific
+transfers to only be allowed to use a subset of them. By default libcurl
+accepts all protocols it supports (*CURLPROTO_ALL*). See also
+CURLOPT_REDIR_PROTOCOLS(3).
+
+These are the available protocol defines:
+~~~c
+CURLPROTO_DICT
+CURLPROTO_FILE
+CURLPROTO_FTP
+CURLPROTO_FTPS
+CURLPROTO_GOPHER
+CURLPROTO_HTTP
+CURLPROTO_HTTPS
+CURLPROTO_IMAP
+CURLPROTO_IMAPS
+CURLPROTO_LDAP
+CURLPROTO_LDAPS
+CURLPROTO_POP3
+CURLPROTO_POP3S
+CURLPROTO_RTMP
+CURLPROTO_RTMPE
+CURLPROTO_RTMPS
+CURLPROTO_RTMPT
+CURLPROTO_RTMPTE
+CURLPROTO_RTMPTS
+CURLPROTO_RTSP
+CURLPROTO_SCP
+CURLPROTO_SFTP
+CURLPROTO_SMB
+CURLPROTO_SMBS
+CURLPROTO_SMTP
+CURLPROTO_SMTPS
+CURLPROTO_TELNET
+CURLPROTO_TFTP
+~~~
+
+# DEFAULT
+
+All protocols built-in.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(int argc, char **argv)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* pass in the URL from an external source */
+ curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
+
+ /* only allow HTTP, TFTP and SFTP */
+ curl_easy_setopt(curl, CURLOPT_PROTOCOLS,
+ CURLPROTO_HTTP | CURLPROTO_TFTP | CURLPROTO_SFTP);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.4. Deprecated since 7.85.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.3 b/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.3
deleted file mode 100644
index 561020fd7..000000000
--- a/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROTOCOLS_STR 3 "11 Jun 2022" libcurl libcurl
-.SH NAME
-CURLOPT_PROTOCOLS_STR \- allowed protocols
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS_STR, char *spec);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a string that holds a comma-separated list of case
-insensitive protocol names (URL schemes) to allow in the transfer. This
-option allows applications to use libcurl built to support a wide range of
-protocols but still limit specific transfers to only be allowed to use a
-subset of them. By default, libcurl accepts all protocols it was built with
-support for. See also \fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP.
-
-If trying to set a non-existing protocol or if no matching protocol at all is
-set, it returns error.
-
-These are the available protocols:
-
-DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
-MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
-SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
-
-You can set "ALL" as a short-cut to enable all protocols. Note that by setting
-all, you may enable protocols that were not supported the day you write this
-but are introduced in a future libcurl version.
-
-\fIcurl_version_info(3)\fP can be used to get a list of all supported
-protocols in the current libcurl. \fICURLINFO_SCHEME(3)\fP is the recommended
-way to figure out the protocol used in a previous transfer.
-.SH DEFAULT
-All protocols built-in
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- /* pass in the URL from an external source */
- curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
-
- /* only allow HTTP, TFTP and SFTP */
- curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,tftp,sftp");
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.85.0
-.SH RETURN VALUE
-Returns CURLE_UNKNOWN_OPTION if the option is not implemented,
-CURLE_UNSUPPORTED_PROTOCOL if a listed protocol is not supported or disabled,
-CURLE_BAD_FUNCTION_ARGUMENT if no protocol is listed else CURLE_OK.
-.SH "SEE ALSO"
-.BR curl_version_info (3),
-.BR CURLINFO_SCHEME (3),
-.BR CURLOPT_DEFAULT_PROTOCOL (3),
-.BR CURLOPT_REDIR_PROTOCOLS_STR (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.md b/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.md
new file mode 100644
index 000000000..9da056d23
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROTOCOLS_STR.md
@@ -0,0 +1,88 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROTOCOLS_STR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SCHEME (3)
+ - CURLOPT_DEFAULT_PROTOCOL (3)
+ - CURLOPT_REDIR_PROTOCOLS_STR (3)
+ - CURLOPT_URL (3)
+ - curl_version_info (3)
+---
+
+# NAME
+
+CURLOPT_PROTOCOLS_STR - allowed protocols
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROTOCOLS_STR, char *spec);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a string that holds a comma-separated list of case
+insensitive protocol names (URL schemes) to allow in the transfer. This
+option allows applications to use libcurl built to support a wide range of
+protocols but still limit specific transfers to only be allowed to use a
+subset of them. By default, libcurl accepts all protocols it was built with
+support for. See also CURLOPT_REDIR_PROTOCOLS_STR(3).
+
+If trying to set a non-existing protocol or if no matching protocol at all is
+set, it returns error.
+
+These are the available protocols:
+
+DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
+MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
+SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
+
+You can set "ALL" as a short-cut to enable all protocols. Note that by setting
+all, you may enable protocols that were not supported the day you write this
+but are introduced in a future libcurl version.
+
+curl_version_info(3) can be used to get a list of all supported
+protocols in the current libcurl. CURLINFO_SCHEME(3) is the recommended
+way to figure out the protocol used in a previous transfer.
+
+# DEFAULT
+
+All protocols built-in
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(int argc, char **argv)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* pass in the URL from an external source */
+ curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
+
+ /* only allow HTTP, TFTP and SFTP */
+ curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,tftp,sftp");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.85.0
+
+# RETURN VALUE
+
+Returns CURLE_UNKNOWN_OPTION if the option is not implemented,
+CURLE_UNSUPPORTED_PROTOCOL if a listed protocol is not supported or disabled,
+CURLE_BAD_FUNCTION_ARGUMENT if no protocol is listed else CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY.3 b/docs/libcurl/opts/CURLOPT_PROXY.3
deleted file mode 100644
index c645af539..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY.3
+++ /dev/null
@@ -1,134 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY \- proxy to use
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY, char *proxy);
-.fi
-.SH DESCRIPTION
-Set the \fIproxy\fP to use for transfers with this easy handle. The parameter
-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].
-
-To specify port number in this string, append :[port] to the end of the host
-name. The proxy's port number may optionally (but discouraged) be specified
-with the separate option \fICURLOPT_PROXYPORT(3)\fP. If not specified, libcurl
-defaults to using port 1080 for proxies.
-
-The proxy string may be prefixed with [scheme]:// to specify which kind of
-proxy is used.
-
-.RS
-.IP http://
-HTTP Proxy. Default when no scheme or proxy type is specified.
-.IP https://
-HTTPS Proxy. (Added in 7.52.0 for OpenSSL and GnuTLS Since 7.87.0, it
-also works for BearSSL, mbedTLS, rustls, Schannel, Secure Transport and
-wolfSSL.)
-
-This uses HTTP/1 by default. Setting \fICURLOPT_PROXYTYPE(3)\fP to
-\fBCURLPROXY_HTTPS2\fP allows libcurl to negotiate using HTTP/2 with proxy.
-.IP socks4://
-SOCKS4 Proxy.
-.IP socks4a://
-SOCKS4a Proxy. Proxy resolves URL hostname.
-.IP socks5://
-SOCKS5 Proxy.
-.IP socks5h://
-SOCKS5 Proxy. Proxy resolves URL hostname.
-.RE
-
-Without a scheme prefix, \fICURLOPT_PROXYTYPE(3)\fP can be used to specify
-which kind of proxy the string identifies.
-
-When you tell the library to use an HTTP proxy, libcurl transparently converts
-operations to HTTP even if you specify an FTP URL etc. This may have an impact
-on what other features of the library you can use, such as
-\fICURLOPT_QUOTE(3)\fP and similar FTP specifics that do not work unless you
-tunnel through the HTTP proxy. Such tunneling is activated with
-\fICURLOPT_HTTPPROXYTUNNEL(3)\fP.
-
-Setting the proxy string to "" (an empty string) explicitly disables the use
-of a proxy, even if there is an environment variable set for it.
-
-A proxy host string can also include protocol scheme (http://) and embedded
-user + password.
-
-Unix domain sockets are supported for socks proxies since 7.84.0. Set
-localhost for the host part. e.g. socks5h://localhost/path/to/socket.sock
-
-The application does not have to keep the string around after setting this
-option.
-
-When a proxy is used, the active FTP mode as set with \fICUROPT_FTPPORT(3)\fP,
-cannot be used.
-.SH "Environment variables"
-libcurl respects the proxy environment variables named \fBhttp_proxy\fP,
-\fBftp_proxy\fP, \fBsftp_proxy\fP etc. If set, libcurl uses the specified
-proxy for that URL scheme. So for a "FTP://" URL, the \fBftp_proxy\fP is
-considered. \fBall_proxy\fP is used if no protocol specific proxy was set.
-
-If \fBno_proxy\fP (or \fBNO_PROXY\fP) is set, it is the exact equivalent of
-setting the \fICURLOPT_NOPROXY(3)\fP option.
-
-The \fICURLOPT_PROXY(3)\fP and \fICURLOPT_NOPROXY(3)\fP options override
-environment variables.
-.SH DEFAULT
-Default is NULL, meaning no proxy is used.
-
-When you set a host name to use, do not assume that there is any particular
-single port number used widely for proxies. Specify it!
-.SH PROTOCOLS
-All except file://. Note that some protocols do not work well over proxy.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/file.txt");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80");
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Since 7.14.1 the proxy environment variable names can include the protocol
-scheme.
-
-Since 7.21.7 the proxy string supports the socks protocols as "schemes".
-
-Since 7.50.2, unsupported schemes in proxy strings cause libcurl to return
-error.
-.SH RETURN VALUE
-Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPPROXYTUNNEL (3),
-.BR CURLOPT_PRE_PROXY (3),
-.BR CURLOPT_PROXYPORT (3),
-.BR CURLOPT_PROXYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY.md b/docs/libcurl/opts/CURLOPT_PROXY.md
new file mode 100644
index 000000000..89c22df9b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY.md
@@ -0,0 +1,146 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPPROXYTUNNEL (3)
+ - CURLOPT_PRE_PROXY (3)
+ - CURLOPT_PROXYPORT (3)
+ - CURLOPT_PROXYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_PROXY - proxy to use
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY, char *proxy);
+~~~
+
+# DESCRIPTION
+
+Set the *proxy* to use for transfers with this easy handle. The parameter
+should be a char * to a null-terminated string holding the hostname 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
+name. The proxy's port number may optionally (but discouraged) be specified
+with the separate option CURLOPT_PROXYPORT(3). If not specified, libcurl
+defaults to using port 1080 for proxies.
+
+The proxy string may be prefixed with [scheme]:// to specify which kind of
+proxy is used.
+
+## http://
+
+HTTP Proxy. Default when no scheme or proxy type is specified.
+
+## https://
+
+HTTPS Proxy. (Added in 7.52.0 for OpenSSL and GnuTLS Since 7.87.0, it
+also works for BearSSL, mbedTLS, rustls, Schannel, Secure Transport and
+wolfSSL.)
+
+This uses HTTP/1 by default. Setting CURLOPT_PROXYTYPE(3) to
+**CURLPROXY_HTTPS2** allows libcurl to negotiate using HTTP/2 with proxy.
+
+## socks4://
+
+SOCKS4 Proxy.
+
+## socks4a://
+
+SOCKS4a Proxy. Proxy resolves URL hostname.
+
+## socks5://
+
+SOCKS5 Proxy.
+
+## socks5h://
+
+SOCKS5 Proxy. Proxy resolves URL hostname.
+
+Without a scheme prefix, CURLOPT_PROXYTYPE(3) can be used to specify
+which kind of proxy the string identifies.
+
+When you tell the library to use an HTTP proxy, libcurl transparently converts
+operations to HTTP even if you specify an FTP URL etc. This may have an impact
+on what other features of the library you can use, such as
+CURLOPT_QUOTE(3) and similar FTP specifics that do not work unless you
+tunnel through the HTTP proxy. Such tunneling is activated with
+CURLOPT_HTTPPROXYTUNNEL(3).
+
+Setting the proxy string to "" (an empty string) explicitly disables the use
+of a proxy, even if there is an environment variable set for it.
+
+A proxy host string can also include protocol scheme (http://) and embedded
+user + password.
+
+Unix domain sockets are supported for socks proxies since 7.84.0. Set
+localhost for the host part. e.g. socks5h://localhost/path/to/socket.sock
+
+The application does not have to keep the string around after setting this
+option.
+
+When a proxy is used, the active FTP mode as set with *CUROPT_FTPPORT(3)*,
+cannot be used.
+
+# Environment variables
+
+libcurl respects the proxy environment variables named **http_proxy**,
+**ftp_proxy**, **sftp_proxy** etc. If set, libcurl uses the specified proxy
+for that URL scheme. For an "FTP://" URL, the **ftp_proxy** is
+considered. **all_proxy** is used if no protocol specific proxy was set.
+
+If **no_proxy** (or **NO_PROXY**) is set, it is the exact equivalent of
+setting the CURLOPT_NOPROXY(3) option.
+
+The CURLOPT_PROXY(3) and CURLOPT_NOPROXY(3) options override environment
+variables.
+
+# DEFAULT
+
+Default is NULL, meaning no proxy is used.
+
+When you set a hostname to use, do not assume that there is any particular
+single port number used widely for proxies. Specify it!
+
+# PROTOCOLS
+
+All except file://. Note that some protocols do not work well over proxy.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/file.txt");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80");
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Since 7.14.1 the proxy environment variable names can include the protocol
+scheme.
+
+Since 7.21.7 the proxy string supports the socks protocols as "schemes".
+
+Since 7.50.2, unsupported schemes in proxy strings cause libcurl to return
+error.
+
+# RETURN VALUE
+
+Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXYAUTH.3 b/docs/libcurl/opts/CURLOPT_PROXYAUTH.3
deleted file mode 100644
index 309d3699e..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXYAUTH.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXYAUTH 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXYAUTH \- HTTP proxy authentication methods
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYAUTH, long bitmask);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter, which is set to a bitmask, to tell libcurl which
-HTTP authentication method(s) you want it to use for your proxy
-authentication. If more than one bit is set, libcurl first queries the site to
-see what authentication methods it supports and then it picks the best one you
-allow it to use. For some methods, this induces an extra network round-trip.
-Set the actual name and password with the \fICURLOPT_PROXYUSERPWD(3)\fP
-option.
-
-The bitmask can be constructed by the bits listed and described in the
-\fICURLOPT_HTTPAUTH(3)\fP man page.
-.SH DEFAULT
-CURLAUTH_BASIC
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* use this proxy */
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://local.example.com:1080");
- /* allow whatever auth the proxy speaks */
- curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
- /* set the proxy credentials */
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, "james:007");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.7
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_NOT_BUILT_IN if the bitmask specified no supported authentication
-methods.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPAUTH (3),
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_PROXYPORT (3),
-.BR CURLOPT_PROXYTYPE (3),
-.BR CURLOPT_PROXYUSERPWD (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXYAUTH.md b/docs/libcurl/opts/CURLOPT_PROXYAUTH.md
new file mode 100644
index 000000000..8e6dc093b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXYAUTH.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXYAUTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPAUTH (3)
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYPORT (3)
+ - CURLOPT_PROXYTYPE (3)
+ - CURLOPT_PROXYUSERPWD (3)
+---
+
+# NAME
+
+CURLOPT_PROXYAUTH - HTTP proxy authentication methods
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYAUTH, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter, which is set to a bitmask, to tell libcurl which
+HTTP authentication method(s) you want it to use for your proxy
+authentication. If more than one bit is set, libcurl first queries the site to
+see what authentication methods it supports and then it picks the best one you
+allow it to use. For some methods, this induces an extra network round-trip.
+Set the actual name and password with the CURLOPT_PROXYUSERPWD(3)
+option.
+
+The bitmask can be constructed by the bits listed and described in the
+CURLOPT_HTTPAUTH(3) man page.
+
+# DEFAULT
+
+CURLAUTH_BASIC
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* use this proxy */
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://local.example.com:1080");
+ /* allow whatever auth the proxy speaks */
+ curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+ /* set the proxy credentials */
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, "james:007");
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.7
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_NOT_BUILT_IN if the bitmask specified no supported authentication
+methods.
diff --git a/docs/libcurl/opts/CURLOPT_PROXYHEADER.3 b/docs/libcurl/opts/CURLOPT_PROXYHEADER.3
deleted file mode 100644
index 439008201..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXYHEADER.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXYHEADER 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXYHEADER \- set of HTTP headers to pass to proxy
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYHEADER,
- struct curl_slist *headers);
-.SH DESCRIPTION
-Pass a pointer to a linked list of HTTP headers to pass in your HTTP request
-sent to a proxy. The rules for this list is identical to the
-\fICURLOPT_HTTPHEADER(3)\fP option's.
-
-The headers set with this option is only ever used in requests sent to a proxy
-- when there is also a request sent to a host.
-
-The first line in a request (containing the method, usually a GET or POST) is
-NOT a header and cannot be replaced using this option. Only the lines
-following the request-line are headers. Adding this method line in this list
-of headers causes your request to send an invalid header.
-
-Pass a NULL to this to reset back to no custom headers.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-
-struct curl_slist *list;
-
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com:80");
-
- list = curl_slist_append(NULL, "Shoesize: 10");
- list = curl_slist_append(list, "Accept:");
-
- curl_easy_setopt(curl, CURLOPT_PROXYHEADER, list);
-
- curl_easy_perform(curl);
-
- curl_slist_free_all(list); /* free the list again */
-}
-.fi
-.SH AVAILABILITY
-Added in 7.37.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HEADEROPT (3),
-.BR CURLOPT_HTTPHEADER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXYHEADER.md b/docs/libcurl/opts/CURLOPT_PROXYHEADER.md
new file mode 100644
index 000000000..e44afdd18
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXYHEADER.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXYHEADER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADEROPT (3)
+ - CURLOPT_HTTPHEADER (3)
+---
+
+# NAME
+
+CURLOPT_PROXYHEADER - set of HTTP headers to pass to proxy
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYHEADER,
+ struct curl_slist *headers);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of HTTP headers to pass in your HTTP request
+sent to a proxy. The rules for this list is identical to the
+CURLOPT_HTTPHEADER(3) option's.
+
+The headers set with this option is only ever used in requests sent to a proxy
+- when there is also a request sent to a host.
+
+The first line in a request (containing the method, usually a GET or POST) is
+NOT a header and cannot be replaced using this option. Only the lines
+following the request-line are headers. Adding this method line in this list
+of headers causes your request to send an invalid header.
+
+Pass a NULL to this to reset back to no custom headers.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+
+ struct curl_slist *list;
+
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com:80");
+
+ list = curl_slist_append(NULL, "Shoesize: 10");
+ list = curl_slist_append(list, "Accept:");
+
+ curl_easy_setopt(curl, CURLOPT_PROXYHEADER, list);
+
+ curl_easy_perform(curl);
+
+ curl_slist_free_all(list); /* free the list again */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.37.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3 b/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3
deleted file mode 100644
index 766e0b2ad..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXYPASSWORD 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXYPASSWORD \- password to use with proxy authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPASSWORD, char *pwd);
-.fi
-.SH DESCRIPTION
-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
-the \fICURLOPT_PROXYUSERNAME(3)\fP option.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-blank
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
- curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "mrsmith");
- curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "qwerty");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.1
-.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_HTTPAUTH (3),
-.BR CURLOPT_PASSWORD (3),
-.BR CURLOPT_PROXYAUTH (3),
-.BR CURLOPT_PROXYUSERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md b/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md
new file mode 100644
index 000000000..22520ea11
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXYPASSWORD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPAUTH (3)
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_PROXYAUTH (3)
+ - CURLOPT_PROXYUSERNAME (3)
+---
+
+# NAME
+
+CURLOPT_PROXYPASSWORD - password to use with proxy authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPASSWORD, char *pwd);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be pointing to the null-terminated
+password to use for authentication with the proxy.
+
+The CURLOPT_PROXYPASSWORD(3) option should be used in conjunction with
+the CURLOPT_PROXYUSERNAME(3) option.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "mrsmith");
+ curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "qwerty");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.1
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXYPORT.3 b/docs/libcurl/opts/CURLOPT_PROXYPORT.3
deleted file mode 100644
index 1b369ca0a..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXYPORT.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXYPORT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXYPORT \- port number the proxy listens on
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPORT, long port);
-.fi
-.SH DESCRIPTION
-We discourage use of this option.
-
-Pass a long with this option to set the proxy port to connect to unless it is
-specified in the proxy string \fICURLOPT_PROXY(3)\fP or uses 443 for https
-proxies and 1080 for all others as default.
-
-While this accepts a 'long', the port number is 16 bit so it cannot be larger
-than 65535.
-.SH DEFAULT
-0, not specified which makes it use the default port
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_PROXY, "localhost");
- curl_easy_setopt(curl, CURLOPT_PROXYPORT, 8080L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLINFO_PRIMARY_PORT (3),
-.BR CURLOPT_PORT (3),
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_PROXYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXYPORT.md b/docs/libcurl/opts/CURLOPT_PROXYPORT.md
new file mode 100644
index 000000000..0cda8bb8f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXYPORT.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXYPORT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_PRIMARY_PORT (3)
+ - CURLOPT_PORT (3)
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_PROXYPORT - port number the proxy listens on
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPORT, long port);
+~~~
+
+# DESCRIPTION
+
+We discourage use of this option.
+
+Pass a long with this option to set the proxy port to connect to unless it is
+specified in the proxy string CURLOPT_PROXY(3) or uses 443 for https
+proxies and 1080 for all others as default.
+
+While this accepts a 'long', the port number is 16 bit so it cannot be larger
+than 65535.
+
+# DEFAULT
+
+0, not specified which makes it use the default port
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "localhost");
+ curl_easy_setopt(curl, CURLOPT_PROXYPORT, 8080L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_PROXYTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXYTYPE.3
deleted file mode 100644
index 3399e2c20..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXYTYPE.3
+++ /dev/null
@@ -1,85 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXYTYPE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXYTYPE \- proxy protocol type
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYTYPE, long type);
-.fi
-.SH DESCRIPTION
-Pass one of the values below to set the type of the proxy.
-
-.RS
-.IP CURLPROXY_HTTP
-HTTP Proxy. Default.
-.IP CURLPROXY_HTTPS
-HTTPS Proxy using HTTP/1. (Added in 7.52.0 for OpenSSL and GnuTLS. Since
-7.87.0, it also works for BearSSL, mbedTLS, rustls, Schannel, Secure Transport
-and wolfSSL.)
-.IP CURLPROXY_HTTPS2
-HTTPS Proxy and attempt to speak HTTP/2 over it. (Added in 8.1.0)
-.IP CURLPROXY_HTTP_1_0
-HTTP 1.0 Proxy. This is similar to CURLPROXY_HTTP except it uses HTTP/1.0 for
-any CONNECT tunneling. It does not change the HTTP version of the actual HTTP
-requests, controlled by \fICURLOPT_HTTP_VERSION(3)\fP.
-.IP CURLPROXY_SOCKS4
-SOCKS4 Proxy.
-.IP CURLPROXY_SOCKS4A
-SOCKS4a Proxy. Proxy resolves URL hostname.
-.IP CURLPROXY_SOCKS5
-SOCKS5 Proxy.
-.IP CURLPROXY_SOCKS5_HOSTNAME
-SOCKS5 Proxy. Proxy resolves URL hostname.
-.RE
-
-Often it is more convenient to specify the proxy type with the scheme part of
-the \fICURLOPT_PROXY(3)\fP string.
-.SH DEFAULT
-CURLPROXY_HTTP
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "local.example.com:1080");
- /* set the proxy type */
- curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_PROXYPORT (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXYTYPE.md b/docs/libcurl/opts/CURLOPT_PROXYTYPE.md
new file mode 100644
index 000000000..4f06fe550
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXYTYPE.md
@@ -0,0 +1,99 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXYTYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYPORT (3)
+---
+
+# NAME
+
+CURLOPT_PROXYTYPE - proxy protocol type
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYTYPE, long type);
+~~~
+
+# DESCRIPTION
+
+Pass one of the values below to set the type of the proxy.
+
+## CURLPROXY_HTTP
+
+HTTP Proxy. Default.
+
+## CURLPROXY_HTTPS
+
+HTTPS Proxy using HTTP/1. (Added in 7.52.0 for OpenSSL and GnuTLS. Since
+7.87.0, it also works for BearSSL, mbedTLS, rustls, Schannel, Secure Transport
+and wolfSSL.)
+
+## CURLPROXY_HTTPS2
+
+HTTPS Proxy and attempt to speak HTTP/2 over it. (Added in 8.1.0)
+
+## CURLPROXY_HTTP_1_0
+
+HTTP 1.0 Proxy. This is similar to CURLPROXY_HTTP except it uses HTTP/1.0 for
+any CONNECT tunneling. It does not change the HTTP version of the actual HTTP
+requests, controlled by CURLOPT_HTTP_VERSION(3).
+
+## CURLPROXY_SOCKS4
+
+SOCKS4 Proxy.
+
+## CURLPROXY_SOCKS4A
+
+SOCKS4a Proxy. Proxy resolves URL hostname.
+
+## CURLPROXY_SOCKS5
+
+SOCKS5 Proxy.
+
+## CURLPROXY_SOCKS5_HOSTNAME
+
+SOCKS5 Proxy. Proxy resolves URL hostname.
+
+Often it is more convenient to specify the proxy type with the scheme part of
+the CURLOPT_PROXY(3) string.
+
+# DEFAULT
+
+CURLPROXY_HTTP
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "local.example.com:1080");
+ /* set the proxy type */
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3 b/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3
deleted file mode 100644
index c594ca2ea..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXYUSERNAME 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXYUSERNAME \- user name to use for proxy authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYUSERNAME,
- char *username);
-.SH DESCRIPTION
-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
-authentication with the proxy.
-
-To specify the proxy password use the \fICURLOPT_PROXYPASSWORD(3)\fP.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-blank
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
- curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "mrsmith");
- curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "qwerty");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.1
-.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_PROXYPASSWORD (3),
-.BR CURLOPT_USERNAME (3),
-.BR CURLOPT_HTTPAUTH (3),
-.BR CURLOPT_PROXYAUTH (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md b/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md
new file mode 100644
index 000000000..f0d1dfc4d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXYUSERNAME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPAUTH (3)
+ - CURLOPT_PROXYAUTH (3)
+ - CURLOPT_PROXYPASSWORD (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_PROXYUSERNAME - user name to use for proxy authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYUSERNAME,
+ char *username);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be pointing to the
+null-terminated user name to use for the transfer.
+
+CURLOPT_PROXYUSERNAME(3) sets the user name to be used in protocol
+authentication with the proxy.
+
+To specify the proxy password use the CURLOPT_PROXYPASSWORD(3).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "mrsmith");
+ curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "qwerty");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.1
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3 b/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3
deleted file mode 100644
index 76f8bbf20..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXYUSERPWD 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXYUSERPWD \- user name and password to use for proxy authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYUSERPWD, char *userpwd);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter, which should be [user name]:[password] to use for
-the connection to the HTTP proxy. Both the name and the password are URL
-decoded before used, so to include for example a colon in the user name you
-should encode it as %3A. (This is different to how \fICURLOPT_USERPWD(3)\fP is
-used - beware.)
-
-Use \fICURLOPT_PROXYAUTH(3)\fP to specify the authentication method.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-This is NULL by default.
-.SH PROTOCOLS
-Used with all protocols that can use a proxy
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, "clark%20kent:superman");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_PROXYPASSWORD (3),
-.BR CURLOPT_PROXYTYPE (3),
-.BR CURLOPT_PROXYUSERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md b/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md
new file mode 100644
index 000000000..196d587e2
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXYUSERPWD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYPASSWORD (3)
+ - CURLOPT_PROXYTYPE (3)
+ - CURLOPT_PROXYUSERNAME (3)
+---
+
+# NAME
+
+CURLOPT_PROXYUSERPWD - user name and password to use for proxy authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYUSERPWD, char *userpwd);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be [user name]:[password] to
+use for the connection to the HTTP proxy. Both the name and the password are
+URL decoded before used, so to include for example a colon in the user name
+you should encode it as %3A. (This is different to how CURLOPT_USERPWD(3) is
+used - beware.)
+
+Use CURLOPT_PROXYAUTH(3) to specify the authentication method.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+This is NULL by default.
+
+# PROTOCOLS
+
+Used with all protocols that can use a proxy
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
+ curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, "clark%20kent:superman");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK if proxies are supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3
deleted file mode 100644
index fb2c6dca9..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.3
+++ /dev/null
@@ -1,91 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_CAINFO 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_CAINFO \- path to proxy Certificate Authority (CA) bundle
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);
-.fi
-.SH DESCRIPTION
-This option is for connecting to an HTTPS proxy, not an HTTPS server.
-
-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
-server's certificate, \fICURLOPT_PROXY_CAINFO(3)\fP need not even indicate an
-accessible file.
-
-This option is by default set to the system path where libcurl's CA
-certificate bundle is assumed to be stored, as established at build time.
-
-(iOS and macOS only) If curl is built against Secure Transport, then this
-option is supported for backward compatibility with other SSL engines, but it
-should not be set. If the option is not set, then curl uses the certificates
-in the system and user Keychain to verify the peer, which is the preferred
-method of verifying the peer's certificate chain.
-
-The application does not have to keep the string around after setting this
-option.
-
-The default value for this can be figured out with \fICURLINFO_CAINFO(3)\fP.
-.SH DEFAULT
-Built-in system specific
-.SH PROTOCOLS
-Used with HTTPS proxy
-.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_CAINFO, "/etc/certs/cabundle.pem");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-
-For TLS backends that do not support certificate files, the
-\fICURLOPT_PROXY_CAINFO(3)\fP option is ignored. Refer to
-https://curl.se/docs/ssl-compared.html
-.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_CAINFO (3),
-.BR CURLOPT_CAINFO_BLOB (3),
-.BR CURLOPT_CAPATH (3),
-.BR CURLOPT_PROXY_CAINFO_BLOB (3),
-.BR CURLOPT_PROXY_CAPATH (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md
new file mode 100644
index 000000000..473083f35
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md
@@ -0,0 +1,93 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_CAINFO
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_CAINFO_BLOB (3)
+ - CURLOPT_CAPATH (3)
+ - CURLOPT_PROXY_CAINFO_BLOB (3)
+ - CURLOPT_PROXY_CAPATH (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_CAINFO - path to proxy Certificate Authority (CA) bundle
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);
+~~~
+
+# DESCRIPTION
+
+This option is for connecting to an HTTPS proxy, not an HTTPS server.
+
+Pass a char pointer to a null-terminated string naming a file holding one or
+more certificates to verify the HTTPS proxy with.
+
+If CURLOPT_PROXY_SSL_VERIFYPEER(3) is zero and you avoid verifying the
+server's certificate, CURLOPT_PROXY_CAINFO(3) need not even indicate an
+accessible file.
+
+This option is by default set to the system path where libcurl's CA
+certificate bundle is assumed to be stored, as established at build time.
+
+(iOS and macOS only) If curl is built against Secure Transport, then this
+option is supported for backward compatibility with other SSL engines, but it
+should not be set. If the option is not set, then curl uses the certificates
+in the system and user Keychain to verify the peer, which is the preferred
+method of verifying the peer's certificate chain.
+
+The application does not have to keep the string around after setting this
+option.
+
+The default value for this can be figured out with CURLINFO_CAINFO(3).
+
+# DEFAULT
+
+Built-in system specific
+
+# PROTOCOLS
+
+Used with HTTPS proxy
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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_CAINFO, "/etc/certs/cabundle.pem");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+For TLS backends that do not support certificate files, the
+CURLOPT_PROXY_CAINFO(3) option is ignored. Refer to
+https://curl.se/docs/ssl-compared.html
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
deleted file mode 100644
index b2e8be037..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.3
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_CAINFO_BLOB 3 "31 March 2021" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_CAINFO_BLOB \- proxy Certificate Authority (CA) bundle in PEM format
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO_BLOB,
- struct curl_blob *stblob);
-.fi
-.SH DESCRIPTION
-This option is for connecting to an HTTPS proxy, not an HTTPS server.
-
-Pass a pointer to a curl_blob structure, which contains information (pointer
-and size) about a memory block with binary data of PEM encoded content 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
-server's certificate, \fICURLOPT_PROXY_CAINFO_BLOB(3)\fP is not needed.
-
-This option overrides \fICURLOPT_PROXY_CAINFO(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Used with HTTPS proxy
-.SH EXAMPLE
-.nf
-char *strpem; /* strpem must point to a PEM string */
-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 = strpem;
- blob.len = strlen(strpem);
- blob.flags = CURL_BLOB_COPY;
- curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO_BLOB, &blob);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.77.0.
-
-This option is supported by the rustls (since 7.82.0), OpenSSL, Secure
-Transport and Schannel 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_CAINFO (3),
-.BR CURLOPT_CAINFO_BLOB (3),
-.BR CURLOPT_CAPATH (3),
-.BR CURLOPT_PROXY_CAINFO (3),
-.BR CURLOPT_PROXY_CAPATH (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md
new file mode 100644
index 000000000..bbf30cba3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md
@@ -0,0 +1,92 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_CAINFO_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_CAINFO_BLOB (3)
+ - CURLOPT_CAPATH (3)
+ - CURLOPT_PROXY_CAINFO (3)
+ - CURLOPT_PROXY_CAPATH (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_CAINFO_BLOB - proxy Certificate Authority (CA) bundle in PEM format
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO_BLOB,
+ struct curl_blob *stblob);
+~~~
+
+# DESCRIPTION
+
+This option is for connecting to an HTTPS proxy, not an HTTPS server.
+
+Pass a pointer to a curl_blob structure, which contains information (pointer
+and size) about a memory block with binary data of PEM encoded content holding
+one or more certificates to verify the HTTPS proxy with.
+
+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.
+
+If CURLOPT_PROXY_SSL_VERIFYPEER(3) is zero and you avoid verifying the
+server's certificate, CURLOPT_PROXY_CAINFO_BLOB(3) is not needed.
+
+This option overrides CURLOPT_PROXY_CAINFO(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Used with HTTPS proxy
+
+# EXAMPLE
+
+~~~c
+#include <string.h> /* for strlen */
+
+extern char *strpem; /* strpem must point to a PEM string */
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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 = strpem;
+ blob.len = strlen(strpem);
+ blob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO_BLOB, &blob);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.77.0.
+
+This option is supported by the rustls (since 7.82.0), OpenSSL, Secure
+Transport and Schannel backends.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3 b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3
deleted file mode 100644
index 2db652ead..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_CAPATH 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_CAPATH \- directory holding HTTPS proxy CA certificates
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);
-.fi
-.SH DESCRIPTION
-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
-\fBc_rehash\fP utility. This makes sense only when
-\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP is enabled (which it is by default).
-
-The application does not have to keep the string around after setting this
-option.
-
-The default value for this can be figured out with \fICURLINFO_CAPATH(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Everything used over an HTTPS proxy
-.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_CAPATH, "/etc/cert-dir");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-
-This option is supported by the OpenSSL, GnuTLS, and mbedTLS (since 7.56.0)
-backends.
-.SH RETURN VALUE
-CURLE_OK if supported; or an error such as:
-
-CURLE_NOT_BUILT_IN - Not supported by the SSL backend
-
-CURLE_UNKNOWN_OPTION
-
-CURLE_OUT_OF_MEMORY
-.SH "SEE ALSO"
-.BR CURLOPT_CAINFO (3),
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_PROXY_CAINFO (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md
new file mode 100644
index 000000000..2253c9f26
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_CAPATH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_PROXY_CAINFO (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_CAPATH - directory holding HTTPS proxy CA certificates
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer 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
+CURLOPT_PROXY_SSL_VERIFYPEER(3) is enabled (which it is by default).
+
+The application does not have to keep the string around after setting this
+option.
+
+The default value for this can be figured out with CURLINFO_CAPATH(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Everything used over an HTTPS proxy
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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_CAPATH, "/etc/cert-dir");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+This option is supported by the OpenSSL, GnuTLS, and mbedTLS (since 7.56.0)
+backends.
+
+# RETURN VALUE
+
+CURLE_OK if supported; or an error such as:
+
+CURLE_NOT_BUILT_IN - Not supported by the SSL backend
+
+CURLE_UNKNOWN_OPTION
+
+CURLE_OUT_OF_MEMORY
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3 b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3
deleted file mode 100644
index 40fd1cd9d..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.3
+++ /dev/null
@@ -1,81 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_CRLFILE 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_CRLFILE \- HTTPS proxy Certificate Revocation List file
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);
-.fi
-.SH DESCRIPTION
-This option is for connecting to an HTTPS proxy, not an HTTPS server.
-
-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 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.
-
-This option makes sense only when used in combination with the
-\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP option.
-
-A specific error code (\fICURLE_SSL_CRL_BADFILE\fP) is defined with the
-option. It is returned when the SSL exchange fails because the CRL file cannot
-be loaded. A failure in certificate verification due to a revocation
-information found in the CRL does not trigger this specific error.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Used with HTTPS proxy.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://localhost:80");
- curl_easy_setopt(curl, CURLOPT_PROXY_CRLFILE, "/etc/certs/crl.pem");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.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_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md
new file mode 100644
index 000000000..d12c29800
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_CRLFILE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_CRLFILE - HTTPS proxy Certificate Revocation List file
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);
+~~~
+
+# DESCRIPTION
+
+This option is for connecting to an HTTPS proxy, not an HTTPS server.
+
+Pass a char pointer to a null-terminated string naming a *file* 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 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.
+
+This option makes sense only when used in combination with the
+CURLOPT_PROXY_SSL_VERIFYPEER(3) option.
+
+A specific error code (*CURLE_SSL_CRL_BADFILE*) is defined with the option. It
+is returned when the SSL exchange fails because the CRL file cannot be loaded.
+A failure in certificate verification due to a revocation information found in
+the CRL does not trigger this specific error.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Used with HTTPS proxy.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://localhost:80");
+ curl_easy_setopt(curl, CURLOPT_PROXY_CRLFILE, "/etc/certs/crl.pem");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3 b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3
deleted file mode 100644
index af0621ca6..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_ISSUERCERT 3 "24 Jun 2020" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_ISSUERCERT \- proxy issuer SSL certificate filename
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_ISSUERCERT, char *file);
-.fi
-.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 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_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md
new file mode 100644
index 000000000..3b289d2d4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_ISSUERCERT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ISSUERCERT (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_ISSUERCERT - proxy issuer SSL certificate filename
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_ISSUERCERT, char *file);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to a null-terminated string naming a *file* 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 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
+CURLOPT_PROXY_SSL_VERIFYPEER(3) 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
+(CURLOPT_PROXY_SSL_VERIFYPEER(3) has to be set too for the check to
+fail).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.71.0. This option is supported by the OpenSSL backends.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3
deleted file mode 100644
index 32af0cc8e..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3
+++ /dev/null
@@ -1,90 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_ISSUERCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_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 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_BLOB (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md
new file mode 100644
index 000000000..ddd8cf5b4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md
@@ -0,0 +1,95 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_ISSUERCERT_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ISSUERCERT_BLOB (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_ISSUERCERT_BLOB - proxy issuer SSL certificate from memory blob
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_ISSUERCERT_BLOB,
+ struct curl_blob *blob);
+~~~
+
+# 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 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
+CURLOPT_PROXY_SSL_VERIFYPEER(3) 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
+(CURLOPT_PROXY_SSL_VERIFYPEER(3) 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 CURLOPT_PROXY_ISSUERCERT(3) which
+instead expects a filename as input.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+
+extern char *certificateData; /* point to the data */
+size_t filesize; /* size of the data */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.71.0. This option is supported by the OpenSSL backends.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3 b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3
deleted file mode 100644
index 083665fef..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_KEYPASSWD 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_KEYPASSWD \- passphrase for the proxy private key
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);
-.fi
-.SH DESCRIPTION
-This option is for connecting to an HTTPS proxy, not an HTTPS server.
-
-Pass a pointer to a null-terminated string as parameter. It is used as the
-password required to use the \fICURLOPT_PROXY_SSLKEY(3)\fP private key. You
-never need a pass phrase to load a certificate but you need one to load your
-private key.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Used with HTTPS proxy
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443");
- curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "superman");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.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_KEYPASSWD (3),
-.BR CURLOPT_PROXY_SSLKEY (3),
-.BR CURLOPT_SSH_PRIVATE_KEYFILE (3),
-.BR CURLOPT_SSLKEY (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md
new file mode 100644
index 000000000..b29d95f07
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_KEYPASSWD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_KEYPASSWD (3)
+ - CURLOPT_PROXY_SSLKEY (3)
+ - CURLOPT_SSH_PRIVATE_KEYFILE (3)
+ - CURLOPT_SSLKEY (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_KEYPASSWD - passphrase for the proxy private key
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);
+~~~
+
+# DESCRIPTION
+
+This option is for connecting to an HTTPS proxy, not an HTTPS server.
+
+Pass a pointer to a null-terminated string as parameter. It is used as the
+password required to use the CURLOPT_PROXY_SSLKEY(3) private key. You
+never need a pass phrase to load a certificate but you need one to load your
+private key.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Used with HTTPS proxy
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443");
+ curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "superman");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3
deleted file mode 100644
index 05f76515f..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.3
+++ /dev/null
@@ -1,117 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_PINNEDPUBLICKEY 3 "24 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_PINNEDPUBLICKEY \- pinned public key for https proxy
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY, char *pinnedpubkey);
-.fi
-.SH DESCRIPTION
-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 ";"
-
-When negotiating a TLS or SSL connection, the https proxy sends a certificate
-indicating its identity. A public key is extracted from this certificate and
-if it does not exactly match the public key provided to this option, libcurl
-aborts the connection before sending or receiving any data.
-
-On mismatch, \fICURLE_SSL_PINNEDPUBKEYNOTMATCH\fP is returned.
-
-The application does not have to keep the string around after setting this
-option.
-.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) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443");
- curl_easy_setopt(curl, CURLOPT_PROXY_PINNEDPUBLICKEY,
- "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjAa3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74Gxa2eg7fRbEgoChTociMee9wno=");
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH PUBLIC KEY EXTRACTION
-If you do not have the https proxy server's public key file you can extract it
-from the https proxy server's certificate.
-.nf
-# retrieve the server's certificate if you do not already have it
-#
-# be sure to examine the certificate to see if it is what you expected
-#
-# Windows-specific:
-# - Use NUL instead of /dev/null.
-# - OpenSSL may wait for input instead of disconnecting. Hit enter.
-# - If you do not have sed, then just copy the certificate into a file:
-# Lines from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----.
-#
-openssl s_client -servername www.example.com -connect www.example.com:443 < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem
-
-# extract public key in pem format from certificate
-openssl x509 -in www.example.com.pem -pubkey -noout > www.example.com.pubkey.pem
-
-# convert public key from pem to der
-openssl asn1parse -noout -inform pem -in www.example.com.pubkey.pem -out www.example.com.pubkey.der
-
-# sha256 hash and base64 encode der to string for use
-openssl dgst -sha256 -binary www.example.com.pubkey.der | openssl base64
-.fi
-The public key in PEM format contains a header, base64 data and a
-footer:
-.nf
------BEGIN PUBLIC KEY-----
-[BASE 64 DATA]
------END PUBLIC KEY-----
-.fi
-.SH AVAILABILITY
-PEM/DER support:
-
- 7.52.0: GnuTLS, OpenSSL, mbedTLS, wolfSSL
-
-sha256 support:
-
- 7.52.0: GnuTLS, OpenSSL, mbedTLS, wolfSSL
-
-Other SSL backends not supported.
-.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_PINNEDPUBLICKEY (3),
-.BR CURLOPT_PROXY_CAINFO (3),
-.BR CURLOPT_PROXY_CAPATH (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md b/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md
new file mode 100644
index 000000000..4db13652d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md
@@ -0,0 +1,124 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_PINNEDPUBLICKEY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PINNEDPUBLICKEY (3)
+ - CURLOPT_PROXY_CAINFO (3)
+ - CURLOPT_PROXY_CAPATH (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_PINNEDPUBLICKEY - pinned public key for https proxy
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY,
+ char *pinnedpubkey);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. The string can be the
+filename 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 ";"
+
+When negotiating a TLS or SSL connection, the https proxy sends a certificate
+indicating its identity. A public key is extracted from this certificate and
+if it does not exactly match the public key provided to this option, libcurl
+aborts the connection before sending or receiving any data.
+
+On mismatch, *CURLE_SSL_PINNEDPUBKEYNOTMATCH* is returned.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443");
+ curl_easy_setopt(curl, CURLOPT_PROXY_PINNEDPUBLICKEY,
+ "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjA"
+ "a3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74"
+ "Gxa2eg7fRbEgoChTociMee9wno=");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# PUBLIC KEY EXTRACTION
+
+If you do not have the https proxy server's public key file you can extract it
+from the https proxy server's certificate.
+~~~c
+# retrieve the server's certificate if you do not already have it
+#
+# be sure to examine the certificate to see if it is what you expected
+#
+# Windows-specific:
+# - Use NUL instead of /dev/null.
+# - OpenSSL may wait for input instead of disconnecting. Hit enter.
+# - If you do not have sed, then just copy the certificate into a file:
+# Lines from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----.
+#
+openssl s_client -servername www.example.com -connect www.example.com:443 \
+ < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem
+
+# extract public key in pem format from certificate
+openssl x509 -in www.example.com.pem -pubkey -noout > www.example.com.pubkey.pem
+
+# convert public key from pem to der
+openssl asn1parse -noout -inform pem -in www.example.com.pubkey.pem \
+ -out www.example.com.pubkey.der
+
+# sha256 hash and base64 encode der to string for use
+openssl dgst -sha256 -binary www.example.com.pubkey.der | openssl base64
+~~~
+The public key in PEM format contains a header, base64 data and a
+footer:
+~~~c
+-----BEGIN PUBLIC KEY-----
+[BASE 64 DATA]
+-----END PUBLIC KEY-----
+~~~
+
+# AVAILABILITY
+
+PEM/DER support:
+
+ 7.52.0: GnuTLS, OpenSSL, mbedTLS, wolfSSL
+
+sha256 support:
+
+ 7.52.0: GnuTLS, OpenSSL, mbedTLS, wolfSSL
+
+Other SSL backends not supported.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3 b/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3
deleted file mode 100644
index 31f7805fa..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SERVICE_NAME 3 "17 Jun 2015" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SERVICE_NAME \- proxy authentication service name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SERVICE_NAME,
- char *name);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter to a string holding the \fIname\fP of the
-service. The default service name is \fB"HTTP"\fP for HTTP based proxies and
-\fB"rcmd"\fP for SOCKS5. This option allows you to change it.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-See above
-.SH PROTOCOLS
-All network protocols
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY_SERVICE_NAME, "custom");
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.43.0 for HTTP proxies, 7.49.0 for SOCKS5 proxies.
-.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 (3),
-.BR CURLOPT_PROXYTYPE (3),
-.BR CURLOPT_SERVICE_NAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md b/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md
new file mode 100644
index 000000000..73e5cb72a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SERVICE_NAME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYTYPE (3)
+ - CURLOPT_SERVICE_NAME (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SERVICE_NAME - proxy authentication service name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SERVICE_NAME,
+ char *name);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter to a string holding the *name* of the
+service. The default service name is **"HTTP"** for HTTP based proxies and
+**"rcmd"** for SOCKS5. This option allows you to change it.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+See above
+
+# PROTOCOLS
+
+All network protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SERVICE_NAME, "custom");
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.43.0 for HTTP proxies, 7.49.0 for SOCKS5 proxies.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3
deleted file mode 100644
index 0a1c45eb0..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSLCERT 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSLCERT \- HTTPS proxy client certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);
-.fi
-.SH DESCRIPTION
-This option is for connecting to an HTTPS proxy, not an HTTPS server.
-
-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.
-
-With Secure Transport, this can also be the nickname of the certificate 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.
-
-When using a client certificate, you most likely also need to provide a
-private key with \fICURLOPT_PROXY_SSLKEY(3)\fP.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Used with HTTPS proxy
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.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),
-.BR CURLOPT_PROXY_SSLKEY (3),
-.BR CURLOPT_SSLCERT (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md
new file mode 100644
index 000000000..debc7ea8e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md
@@ -0,0 +1,79 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSLCERT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLCERTTYPE (3)
+ - CURLOPT_PROXY_SSLKEY (3)
+ - CURLOPT_SSLCERT (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSLCERT - HTTPS proxy client certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);
+~~~
+
+# DESCRIPTION
+
+This option is for connecting to an HTTPS proxy, not an HTTPS server.
+
+Pass a pointer to a null-terminated string as parameter. The string should be
+the filename 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 CURLOPT_PROXY_SSLCERTTYPE(3).
+
+With Secure Transport, this can also be the nickname of the certificate 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.
+
+When using a client certificate, you most likely also need to provide a
+private key with CURLOPT_PROXY_SSLKEY(3).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Used with HTTPS proxy
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3
deleted file mode 100644
index c1ef518c2..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSLCERTTYPE 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSLCERTTYPE \- type of the proxy client SSL certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);
-.fi
-.SH DESCRIPTION
-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 or
-Schannel. OpenSSL (versions 0.9.3 and later), Secure Transport (on iOS 5 or
-later, or OS X 10.7 or later) and Schannel support "P12" for PKCS#12-encoded
-files.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-"PEM"
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERTTYPE, "PEM");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSLCERT (3),
-.BR CURLOPT_PROXY_SSLKEY (3),
-.BR CURLOPT_SSLCERTTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md
new file mode 100644
index 000000000..ce6c50887
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSLCERTTYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLCERT (3)
+ - CURLOPT_PROXY_SSLKEY (3)
+ - CURLOPT_SSLCERTTYPE (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSLCERTTYPE - type of the proxy client SSL certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);
+~~~
+
+# DESCRIPTION
+
+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 or
+Schannel. OpenSSL (versions 0.9.3 and later), Secure Transport (on iOS 5 or
+later, or OS X 10.7 or later) and Schannel support "P12" for PKCS#12-encoded
+files.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+"PEM"
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERTTYPE, "PEM");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3
deleted file mode 100644
index 3b8412626..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSLCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSLCERT_BLOB \- SSL proxy client certificate from memory blob
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT_BLOB,
- struct curl_blob *blob);
-.fi
-.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
-Used with HTTPS proxy
-.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 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_SSLCERT (3),
-.BR CURLOPT_PROXY_SSLCERTTYPE (3),
-.BR CURLOPT_PROXY_SSLKEY (3),
-.BR CURLOPT_SSLCERT_BLOB (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md
new file mode 100644
index 000000000..e880d38e0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md
@@ -0,0 +1,85 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSLCERT_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLCERT (3)
+ - CURLOPT_PROXY_SSLCERTTYPE (3)
+ - CURLOPT_PROXY_SSLKEY (3)
+ - CURLOPT_SSLCERT_BLOB (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSLCERT_BLOB - SSL proxy client certificate from memory blob
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT_BLOB,
+ struct curl_blob *blob);
+~~~
+
+# 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 CURLOPT_PROXY_SSLCERTTYPE(3).
+
+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 CURLOPT_PROXY_SSLCERT(3) which instead
+expects a filename as input.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Used with HTTPS proxy
+
+# EXAMPLE
+
+~~~c
+
+extern char *certificateData; /* point to data */
+extern size_t filesize; /* size of the data */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.71.0. This option is supported by the OpenSSL, Secure Transport and
+Schannel backends.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3
deleted file mode 100644
index e24e0cd3b..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSLKEY 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSLKEY \- private key file for HTTPS proxy client cert
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);
-.fi
-.SH DESCRIPTION
-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.
-
-(Windows, iOS and Mac OS X) This option is ignored by Secure Transport and
-Schannel SSL backends because they expect the private key to be already
-present in the key chain or PKCS#12 file containing the certificate.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSLCERT (3),
-.BR CURLOPT_PROXY_SSLKEYTYPE (3),
-.BR CURLOPT_SSLCERT (3),
-.BR CURLOPT_SSLKEY (3),
-.BR CURLOPT_SSLKEYTYPE (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md
new file mode 100644
index 000000000..c8400db44
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSLKEY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLCERT (3)
+ - CURLOPT_PROXY_SSLKEYTYPE (3)
+ - CURLOPT_SSLCERT (3)
+ - CURLOPT_SSLKEY (3)
+ - CURLOPT_SSLKEYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSLKEY - private key file for HTTPS proxy client cert
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. The string should be
+the filename of your private key used for connecting to the HTTPS proxy. The
+default format is "PEM" and can be changed with
+CURLOPT_PROXY_SSLKEYTYPE(3).
+
+(Windows, iOS and Mac OS X) This option is ignored by Secure Transport and
+Schannel SSL backends because they expect the private key to be already
+present in the key chain or PKCS#12 file containing the certificate.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3
deleted file mode 100644
index c30e832eb..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSLKEYTYPE 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSLKEYTYPE \- type of the proxy private key file
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);
-.fi
-.SH DESCRIPTION
-This option is for connecting to an HTTPS proxy, not an HTTPS server.
-
-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
-option.
-.SH PROTOCOLS
-Used with HTTPS proxy
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEYTYPE, "PEM");
- curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSLCERT (3),
-.BR CURLOPT_PROXY_SSLKEY (3),
-.BR CURLOPT_SSLKEYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md
new file mode 100644
index 000000000..97960f437
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSLKEYTYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLCERT (3)
+ - CURLOPT_PROXY_SSLKEY (3)
+ - CURLOPT_SSLKEYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSLKEYTYPE - type of the proxy private key file
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);
+~~~
+
+# DESCRIPTION
+
+This option is for connecting to an HTTPS proxy, not an HTTPS server.
+
+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
+option.
+
+# PROTOCOLS
+
+Used with HTTPS proxy
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEYTYPE, "PEM");
+ curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3
deleted file mode 100644
index 9b2385d07..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSLKEY_BLOB 3 "24 Jun 2020" libcurl libcurl
-.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 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_SSLKEY (3),
-.BR CURLOPT_SSLKEY_BLOB (3),
-.BR CURLOPT_SSLKEYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md
new file mode 100644
index 000000000..48bb2e88a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md
@@ -0,0 +1,86 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSLKEY_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSLKEY (3)
+ - CURLOPT_SSLKEYTYPE (3)
+ - CURLOPT_SSLKEY_BLOB (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSLKEY_BLOB - private key for proxy cert from memory blob
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY_BLOB,
+ struct curl_blob *blob);
+~~~
+
+# 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
+CURLOPT_PROXY_SSLKEYTYPE(3).
+
+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.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+
+extern char *certificateData; /* point to data */
+extern size_t filesize; /* size of data */
+
+extern char *privateKeyData; /* point to data */
+extern size_t privateKeySize; /* size */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.71.0. This option is supported by the OpenSSL backends.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3
deleted file mode 100644
index abc173557..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.3
+++ /dev/null
@@ -1,107 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSLVERSION 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSLVERSION \- preferred HTTPS proxy TLS version
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLVERSION,
- long version);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter to control which version of SSL/TLS to attempt to use
-when connecting to an HTTPS proxy.
-
-Use one of the available defines for this purpose. The available options are:
-.RS
-.IP CURL_SSLVERSION_DEFAULT
-The default action. This attempts to figure out the remote SSL protocol
-version.
-.IP CURL_SSLVERSION_TLSv1
-TLSv1.x
-.IP CURL_SSLVERSION_TLSv1_0
-TLSv1.0
-.IP CURL_SSLVERSION_TLSv1_1
-TLSv1.1
-.IP CURL_SSLVERSION_TLSv1_2
-TLSv1.2
-.IP CURL_SSLVERSION_TLSv1_3
-TLSv1.3
-.RE
-The maximum TLS version can be set by using \fIone\fP of the
-CURL_SSLVERSION_MAX_ macros below. It is also possible to OR \fIone\fP of the
-CURL_SSLVERSION_ macros with \fIone\fP of the CURL_SSLVERSION_MAX_ macros.
-The MAX macros are not supported for WolfSSL.
-.RS
-.IP CURL_SSLVERSION_MAX_DEFAULT
-The flag defines the maximum supported TLS version as TLSv1.2, or the default
-value from the SSL library.
-(Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_0
-The flag defines maximum supported TLS version as TLSv1.0.
-(Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_1
-The flag defines maximum supported TLS version as TLSv1.1.
-(Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_2
-The flag defines maximum supported TLS version as TLSv1.2.
-(Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_3
-The flag defines maximum supported TLS version as TLSv1.3.
-(Added in 7.54.0)
-.RE
-
-In versions of curl prior to 7.54 the CURL_SSLVERSION_TLS options were
-documented to allow \fIonly\fP the specified TLS version, but behavior was
-inconsistent depending on the TLS library.
-
-.SH DEFAULT
-CURL_SSLVERSION_DEFAULT
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* ask libcurl to use TLS version 1.0 or later */
- curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTP_VERSION (3),
-.BR CURLOPT_IPRESOLVE (3),
-.BR CURLOPT_SSLVERSION (3),
-.BR CURLOPT_USE_SSL (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.md
new file mode 100644
index 000000000..6f159e87d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLVERSION.md
@@ -0,0 +1,125 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSLVERSION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTP_VERSION (3)
+ - CURLOPT_IPRESOLVE (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_USE_SSL (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSLVERSION - preferred HTTPS proxy TLS version
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLVERSION,
+ long version);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter to control which version of SSL/TLS to attempt to use
+when connecting to an HTTPS proxy.
+
+Use one of the available defines for this purpose. The available options are:
+
+## CURL_SSLVERSION_DEFAULT
+
+The default action. This attempts to figure out the remote SSL protocol
+version.
+
+## CURL_SSLVERSION_TLSv1
+
+TLSv1.x
+
+## CURL_SSLVERSION_TLSv1_0
+
+TLSv1.0
+
+## CURL_SSLVERSION_TLSv1_1
+
+TLSv1.1
+
+## CURL_SSLVERSION_TLSv1_2
+
+TLSv1.2
+
+## CURL_SSLVERSION_TLSv1_3
+
+TLSv1.3
+The maximum TLS version can be set by using *one* of the
+CURL_SSLVERSION_MAX_ macros below. It is also possible to OR *one* of the
+CURL_SSLVERSION_ macros with *one* of the CURL_SSLVERSION_MAX_ macros.
+The MAX macros are not supported for WolfSSL.
+
+## CURL_SSLVERSION_MAX_DEFAULT
+
+The flag defines the maximum supported TLS version as TLSv1.2, or the default
+value from the SSL library.
+(Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_0
+
+The flag defines maximum supported TLS version as TLSv1.0.
+(Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_1
+
+The flag defines maximum supported TLS version as TLSv1.1.
+(Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_2
+
+The flag defines maximum supported TLS version as TLSv1.2.
+(Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_3
+
+The flag defines maximum supported TLS version as TLSv1.3.
+(Added in 7.54.0)
+
+In versions of curl prior to 7.54 the CURL_SSLVERSION_TLS options were
+documented to allow *only* the specified TLS version, but behavior was
+inconsistent depending on the TLS library.
+
+# DEFAULT
+
+CURL_SSLVERSION_DEFAULT
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* ask libcurl to use TLS version 1.0 or later */
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3
deleted file mode 100644
index 6539a2a9a..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.3
+++ /dev/null
@@ -1,89 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSL_CIPHER_LIST 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSL_CIPHER_LIST \- ciphers to use for HTTPS proxy
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST,
- char *list);
-.fi
-.SH DESCRIPTION
-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
-normally used, \&!, \&- and \&+ can be used as operators.
-
-For OpenSSL and GnuTLS valid examples of cipher lists include \fBRC4-SHA\fP,
-\fBSHA1+DES\fP, \fBTLSv1\fP and \fBDEFAULT\fP. The default list is normally
-set when you compile OpenSSL.
-
-For WolfSSL, valid examples of cipher lists include \fBECDHE-RSA-RC4-SHA\fP,
-\fBAES256-SHA:AES256-SHA256\fP, etc.
-
-For BearSSL, valid examples of cipher lists include
-\fBECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256\fP, or when using IANA names
-\fBTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\fP,
-etc.
-With BearSSL you do not add/remove ciphers. If one uses this option then all
-known ciphers are disabled and only those passed in are enabled.
-
-Find more details about cipher lists on this URL:
-
- https://curl.se/docs/ssl-ciphers.html
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL, use internal default
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://localhost");
- curl_easy_setopt(curl, CURLOPT_PROXY_SSL_CIPHER_LIST, "TLSv1");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0, in 7.83.0 for BearSSL
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSLVERSION (3),
-.BR CURLOPT_PROXY_TLS13_CIPHERS (3),
-.BR CURLOPT_SSL_CIPHER_LIST (3),
-.BR CURLOPT_SSLVERSION (3),
-.BR CURLOPT_TLS13_CIPHERS (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md
new file mode 100644
index 000000000..d7626c376
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md
@@ -0,0 +1,91 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSL_CIPHER_LIST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLVERSION (3)
+ - CURLOPT_PROXY_TLS13_CIPHERS (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_SSL_CIPHER_LIST (3)
+ - CURLOPT_TLS13_CIPHERS (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSL_CIPHER_LIST - ciphers to use for HTTPS proxy
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST,
+ char *list);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer, 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
+normally used, &!, &- and &+ can be used as operators.
+
+For OpenSSL and GnuTLS valid examples of cipher lists include **RC4-SHA**,
+**SHA1+DES**, **TLSv1** and **DEFAULT**. The default list is normally
+set when you compile OpenSSL.
+
+For WolfSSL, valid examples of cipher lists include **ECDHE-RSA-RC4-SHA**,
+**AES256-SHA:AES256-SHA256**, etc.
+
+For BearSSL, valid examples of cipher lists include
+**ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256**, or when using IANA names
+**TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256**,
+etc.
+With BearSSL you do not add/remove ciphers. If one uses this option then all
+known ciphers are disabled and only those passed in are enabled.
+
+Find more details about cipher lists on this URL:
+
+ https://curl.se/docs/ssl-ciphers.html
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL, use internal default
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://localhost");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSL_CIPHER_LIST, "TLSv1");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0, in 7.83.0 for BearSSL
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
deleted file mode 100644
index 3611dbc8c..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
+++ /dev/null
@@ -1,104 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSL_OPTIONS 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSL_OPTIONS \- HTTPS proxy SSL behavior options
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS,
- long bitmask);
-.fi
-.SH DESCRIPTION
-Pass a long with a bitmask to tell libcurl about specific SSL
-behaviors. Available bits:
-.IP CURLSSLOPT_ALLOW_BEAST
-Tells libcurl to not attempt to use any workarounds for a security flaw in the
-SSL3 and TLS1.0 protocols. If this option is not used or this bit is set to 0,
-the SSL layer libcurl uses may use a work-around for this flaw although it
-might cause interoperability problems with some (older) SSL implementations.
-WARNING: avoiding this work-around lessens the security, and by setting this
-option to 1 you ask for exactly that. This option is only supported for
-Secure Transport and OpenSSL.
-.IP CURLSSLOPT_NO_REVOKE
-Tells libcurl to disable certificate revocation checks for those SSL backends
-where such behavior is present. This option is only supported for Schannel
-(the native Windows SSL library), with an exception in the case of Windows'
-Untrusted Publishers block list which it seems cannot be bypassed. (Added in
-7.44.0)
-.IP CURLSSLOPT_NO_PARTIALCHAIN
-Tells libcurl to not accept "partial" certificate chains, which it otherwise
-does by default. This option is only supported for OpenSSL and fails the
-certificate verification if the chain ends with an intermediate certificate
-and not with a root cert. (Added in 7.68.0)
-.IP CURLSSLOPT_REVOKE_BEST_EFFORT
-Tells libcurl to ignore certificate revocation checks in case of missing or
-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, Linux (Debian, Ubuntu, Gentoo, Fedora,
-RHEL), macOS, Android and iOS when built to use wolfSSL (since 8.3.0) or on
-Windows when built to use OpenSSL. If you set this option and also set a CA
-certificate file or directory then during verification those certificates
-are searched in addition to the native CA store.
-(Added in 7.71.0)
-.IP CURLSSLOPT_AUTO_CLIENT_CERT
-Tell libcurl to automatically locate and use a client certificate for
-authentication, when requested by the server. This option is only supported
-for Schannel (the native Windows SSL library). Prior to 7.77.0 this was the
-default behavior in libcurl with Schannel. Since the server can request any
-certificate that supports client authentication in the OS certificate store it
-could be a privacy violation and unexpected.
-(Added in 7.77.0)
-.SH DEFAULT
-0
-.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/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- /* weaken TLS only for use with silly proxies */
- curl_easy_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST |
- CURLSSLOPT_NO_REVOKE);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSL_CIPHER_LIST (3),
-.BR CURLOPT_PROXY_SSLVERSION (3),
-.BR CURLOPT_SSL_CIPHER_LIST (3),
-.BR CURLOPT_SSLVERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md
new file mode 100644
index 000000000..30d6935a1
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md
@@ -0,0 +1,119 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSL_OPTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLVERSION (3)
+ - CURLOPT_PROXY_SSL_CIPHER_LIST (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_SSL_CIPHER_LIST (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSL_OPTIONS - HTTPS proxy SSL behavior options
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS,
+ long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long with a bitmask to tell libcurl about specific SSL
+behaviors. Available bits:
+
+## CURLSSLOPT_ALLOW_BEAST
+
+Tells libcurl to not attempt to use any workarounds for a security flaw in the
+SSL3 and TLS1.0 protocols. If this option is not used or this bit is set to 0,
+the SSL layer libcurl uses may use a work-around for this flaw although it
+might cause interoperability problems with some (older) SSL implementations.
+WARNING: avoiding this work-around lessens the security, and by setting this
+option to 1 you ask for exactly that. This option is only supported for Secure
+Transport and OpenSSL.
+
+## CURLSSLOPT_NO_REVOKE
+
+Tells libcurl to disable certificate revocation checks for those SSL backends
+where such behavior is present. This option is only supported for Schannel
+(the native Windows SSL library), with an exception in the case of Windows'
+Untrusted Publishers block list which it seems cannot be bypassed. (Added in
+7.44.0)
+
+## CURLSSLOPT_NO_PARTIALCHAIN
+
+Tells libcurl to not accept "partial" certificate chains, which it otherwise
+does by default. This option is only supported for OpenSSL and fails the
+certificate verification if the chain ends with an intermediate certificate
+and not with a root cert. (Added in 7.68.0)
+
+## CURLSSLOPT_REVOKE_BEST_EFFORT
+
+Tells libcurl to ignore certificate revocation checks in case of missing or
+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 *CURLSSLOPT_NO_REVOKE*, the latter takes
+precedence. (Added in 7.70.0)
+
+## CURLSSLOPT_NATIVE_CA
+
+Tell libcurl to use the operating system's native CA store for certificate
+verification. If you set this option and also set a CA certificate file or
+directory then during verification those certificates are searched in addition
+to the native CA store.
+
+Works with wolfSSL on Windows, Linux (Debian, Ubuntu, Gentoo, Fedora, RHEL),
+macOS, Android and iOS (added in 8.3.0), with GnuTLS (added in 8.5.0) or on
+Windows when built to use OpenSSL (Added in 7.71.0).
+
+## CURLSSLOPT_AUTO_CLIENT_CERT
+
+Tell libcurl to automatically locate and use a client certificate for
+authentication, when requested by the server. This option is only supported
+for Schannel (the native Windows SSL library). Prior to 7.77.0 this was the
+default behavior in libcurl with Schannel. Since the server can request any
+certificate that supports client authentication in the OS certificate store it
+could be a privacy violation and unexpected.
+(Added in 7.77.0)
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ /* weaken TLS only for use with silly proxies */
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST |
+ CURLSSLOPT_NO_REVOKE);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3
deleted file mode 100644
index 83962d7c2..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.3
+++ /dev/null
@@ -1,93 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSL_VERIFYHOST 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSL_VERIFYHOST \- verify the proxy certificate's name against host
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYHOST,
- long verify);
-.fi
-.SH DESCRIPTION
-Pass a long set to 2L as asking curl to \fIverify\fP in the HTTPS proxy's
-certificate name fields against the proxy name.
-
-This option determines whether libcurl verifies that the proxy cert contains
-the correct name for the name it is known as.
-
-When \fICURLOPT_PROXY_SSL_VERIFYHOST(3)\fP is 2, the proxy certificate must
-indicate that the server is the proxy to which you meant to connect to, or the
-connection fails.
-
-Curl considers the proxy the intended one when the Common Name field or a
-Subject Alternate Name field in the certificate matches the host name in the
-proxy string which you told curl to use.
-
-If \fIverify\fP value is set to 1:
-
-In 7.28.0 and earlier: treated as a debug option of some sorts, not supported
-anymore due to frequently leading to programmer mistakes.
-
-From 7.28.1 to 7.65.3: setting it to 1 made \fIcurl_easy_setopt(3)\fP return
-an error and leaving the flag untouched.
-
-From 7.66.0: treats 1 and 2 the same.
-
-When the \fIverify\fP value is 0L, the connection succeeds regardless of the
-names used in the certificate. Use that ability with caution!
-
-See also \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP to verify the digital signature
-of the proxy certificate.
-.SH DEFAULT
-2
-.SH PROTOCOLS
-All protocols when used over an HTTPS proxy.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Set the default value: strict name check please */
- curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0.
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, and CURLE_UNKNOWN_OPTION if not.
-
-If 1 is set as argument, \fICURLE_BAD_FUNCTION_ARGUMENT\fP is returned.
-.SH "SEE ALSO"
-.BR CURLOPT_CAINFO (3),
-.BR CURLOPT_PROXY_CAINFO (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.md b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.md
new file mode 100644
index 000000000..fdb8249ff
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYHOST.md
@@ -0,0 +1,94 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSL_VERIFYHOST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_PROXY_CAINFO (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSL_VERIFYHOST - verify the proxy certificate's name against host
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYHOST,
+ long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 2L as asking curl to *verify* in the HTTPS proxy's
+certificate name fields against the proxy name.
+
+This option determines whether libcurl verifies that the proxy cert contains
+the correct name for the name it is known as.
+
+When CURLOPT_PROXY_SSL_VERIFYHOST(3) is 2, the proxy certificate must
+indicate that the server is the proxy to which you meant to connect to, or the
+connection fails.
+
+Curl considers the proxy the intended one when the Common Name field or a
+Subject Alternate Name field in the certificate matches the hostname in the
+proxy string which you told curl to use.
+
+If *verify* value is set to 1:
+
+In 7.28.0 and earlier: treated as a debug option of some sorts, not supported
+anymore due to frequently leading to programmer mistakes.
+
+From 7.28.1 to 7.65.3: setting it to 1 made curl_easy_setopt(3) return
+an error and leaving the flag untouched.
+
+From 7.66.0: treats 1 and 2 the same.
+
+When the *verify* value is 0L, the connection succeeds regardless of the
+names used in the certificate. Use that ability with caution!
+
+See also CURLOPT_PROXY_SSL_VERIFYPEER(3) to verify the digital signature
+of the proxy certificate.
+
+# DEFAULT
+
+2
+
+# PROTOCOLS
+
+All protocols when used over an HTTPS proxy.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the default value: strict name check please */
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0.
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, and CURLE_UNKNOWN_OPTION if not.
+
+If 1 is set as argument, *CURLE_BAD_FUNCTION_ARGUMENT* is returned.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3
deleted file mode 100644
index c6d46029a..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_SSL_VERIFYPEER 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_SSL_VERIFYPEER \- verify the proxy's SSL certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYPEER,
- long verify);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter set to 1L to enable or 0L to disable.
-
-This option tells curl to verify the authenticity of the HTTPS proxy's
-certificate. A value of 1 means curl verifies; 0 (zero) means it does not.
-
-This is the proxy version of \fICURLOPT_SSL_VERIFYPEER(3)\fP that is used for
-ordinary HTTPS servers.
-
-When negotiating a TLS or SSL connection, the server sends a certificate
-indicating its identity. Curl verifies whether the certificate is authentic,
-i.e. that you can trust that the server is who the certificate says it is.
-This trust is based on a chain of digital signatures, rooted in certification
-authority (CA) certificates you supply. curl uses a default bundle of CA
-certificates (the path for that is determined at build time) and you can
-specify alternate certificates with the \fICURLOPT_PROXY_CAINFO(3)\fP option
-or the \fICURLOPT_PROXY_CAPATH(3)\fP option.
-
-When \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP is enabled, and the verification
-fails to prove that the certificate is authentic, the connection fails. When
-the option is zero, the peer certificate verification succeeds regardless.
-
-Authenticating the certificate is not enough to be sure about the server. You
-typically also want to ensure that the server is the server you mean to be
-talking to. Use \fICURLOPT_PROXY_SSL_VERIFYHOST(3)\fP for that. The check
-that the host name in the certificate is valid for the host name you are
-connecting to is done independently of the
-\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP option.
-
-WARNING: disabling verification of the certificate allows bad guys to
-man-in-the-middle the communication without you knowing it. Disabling
-verification makes the communication insecure. Just having encryption on a
-transfer is not enough as you cannot be sure that you are communicating with
-the correct end-point.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Set the default value: strict certificate check please */
- curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3),
-.BR CURLOPT_SSL_VERIFYHOST (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.md b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.md
new file mode 100644
index 000000000..f934ddeb7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_VERIFYPEER.md
@@ -0,0 +1,94 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_SSL_VERIFYPEER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_SSL_VERIFYPEER - verify the proxy's SSL certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYPEER,
+ long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter set to 1L to enable or 0L to disable.
+
+This option tells curl to verify the authenticity of the HTTPS proxy's
+certificate. A value of 1 means curl verifies; 0 (zero) means it does not.
+
+This is the proxy version of CURLOPT_SSL_VERIFYPEER(3) that is used for
+ordinary HTTPS servers.
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. Curl verifies whether the certificate is authentic,
+i.e. that you can trust that the server is who the certificate says it is.
+This trust is based on a chain of digital signatures, rooted in certification
+authority (CA) certificates you supply. curl uses a default bundle of CA
+certificates (the path for that is determined at build time) and you can
+specify alternate certificates with the CURLOPT_PROXY_CAINFO(3) option or
+the CURLOPT_PROXY_CAPATH(3) option.
+
+When CURLOPT_PROXY_SSL_VERIFYPEER(3) is enabled, and the verification
+fails to prove that the certificate is authentic, the connection fails. When
+the option is zero, the peer certificate verification succeeds regardless.
+
+Authenticating the certificate is not enough to be sure about the server. You
+typically also want to ensure that the server is the server you mean to be
+talking to. Use CURLOPT_PROXY_SSL_VERIFYHOST(3) for that. The check that the
+hostname in the certificate is valid for the hostname you are connecting to is
+done independently of the CURLOPT_PROXY_SSL_VERIFYPEER(3) option.
+
+WARNING: disabling verification of the certificate allows bad guys to
+man-in-the-middle the communication without you knowing it. Disabling
+verification makes the communication insecure. Just having encryption on a
+transfer is not enough as you cannot be sure that you are communicating with
+the correct end-point.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the default value: strict certificate check please */
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3
deleted file mode 100644
index f34f37ccf..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_TLS13_CIPHERS 3 "25 May 2018" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_TLS13_CIPHERS \- ciphers suites for proxy TLS 1.3
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLS13_CIPHERS,
- char *list);
-.fi
-.SH DESCRIPTION
-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.
-
-Find more details about cipher lists on this URL:
-
- https://curl.se/docs/ssl-ciphers.html
-
-This option is currently used only when curl is built to use OpenSSL 1.1.1 or
-later. If you are using a different SSL backend you can try setting TLS 1.3
-cipher suites by using the \fICURLOPT_PROXY_SSL_CIPHER_LIST(3)\fP option.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL, use internal default
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLS13_CIPHERS,
- "TLS_CHACHA20_POLY1305_SHA256");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0.
-Available when built with OpenSSL >= 1.1.1.
-.SH RETURN VALUE
-Returns CURLE_OK if supported, CURLE_NOT_BUILT_IN otherwise.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSL_CIPHER_LIST (3),
-.BR CURLOPT_PROXY_SSLVERSION (3),
-.BR CURLOPT_SSL_CIPHER_LIST (3),
-.BR CURLOPT_SSLVERSION (3),
-.BR CURLOPT_TLS13_CIPHERS (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md
new file mode 100644
index 000000000..f3c5448f0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_TLS13_CIPHERS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLVERSION (3)
+ - CURLOPT_PROXY_SSL_CIPHER_LIST (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_SSL_CIPHER_LIST (3)
+ - CURLOPT_TLS13_CIPHERS (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_TLS13_CIPHERS - ciphers suites for proxy TLS 1.3
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLS13_CIPHERS,
+ char *list);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer, 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.
+
+Find more details about cipher lists on this URL:
+
+ https://curl.se/docs/ssl-ciphers.html
+
+This option is currently used only when curl is built to use OpenSSL 1.1.1 or
+later. If you are using a different SSL backend you can try setting TLS 1.3
+cipher suites by using the CURLOPT_PROXY_SSL_CIPHER_LIST(3) option.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL, use internal default
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLS13_CIPHERS,
+ "TLS_CHACHA20_POLY1305_SHA256");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0.
+Available when built with OpenSSL >= 1.1.1.
+
+# RETURN VALUE
+
+Returns CURLE_OK if supported, CURLE_NOT_BUILT_IN otherwise.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3
deleted file mode 100644
index f5990dd4d..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_TLSAUTH_PASSWORD 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD,
- char *pwd);
-.fi
-.SH DESCRIPTION
-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.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_TYPE, "SRP");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, "user");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, "secret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0, with the OpenSSL and GnuTLS backends only
-.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_TLSAUTH_TYPE (3),
-.BR CURLOPT_PROXY_TLSAUTH_USERNAME (3),
-.BR CURLOPT_TLSAUTH_TYPE (3),
-.BR CURLOPT_TLSAUTH_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md
new file mode 100644
index 000000000..778d1b79c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_TLSAUTH_PASSWORD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_TLSAUTH_TYPE (3)
+ - CURLOPT_PROXY_TLSAUTH_USERNAME (3)
+ - CURLOPT_TLSAUTH_TYPE (3)
+ - CURLOPT_TLSAUTH_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_TLSAUTH_PASSWORD - password to use for proxy TLS authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD,
+ char *pwd);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should point to the null-terminated
+password to use for the TLS authentication method specified with the
+CURLOPT_PROXY_TLSAUTH_TYPE(3) option. Requires that the
+CURLOPT_PROXY_TLSAUTH_USERNAME(3) option also be set.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_TYPE, "SRP");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, "user");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, "secret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0, with the OpenSSL and GnuTLS backends only
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3
deleted file mode 100644
index 0b4154422..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_TLSAUTH_TYPE 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_TLSAUTH_TYPE \- HTTPS proxy TLS authentication methods
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE,
- char *type);
-.fi
-.SH DESCRIPTION
-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".
-
-.IP SRP
-TLS-SRP authentication. Secure Remote Password authentication for TLS is
-defined in RFC 5054 and provides mutual authentication if both sides have a
-shared secret. To use TLS-SRP, you must also set the
-\fICURLOPT_PROXY_TLSAUTH_USERNAME(3)\fP and
-\fICURLOPT_PROXY_TLSAUTH_PASSWORD(3)\fP options.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-blank
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_TYPE, "SRP");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, "user");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, "secret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0
-
-You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this
-to work.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_TLSAUTH_PASSWORD (3),
-.BR CURLOPT_PROXY_TLSAUTH_USERNAME (3),
-.BR CURLOPT_TLSAUTH_PASSWORD (3),
-.BR CURLOPT_TLSAUTH_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md
new file mode 100644
index 000000000..d4389188b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_TLSAUTH_TYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_TLSAUTH_PASSWORD (3)
+ - CURLOPT_PROXY_TLSAUTH_USERNAME (3)
+ - CURLOPT_TLSAUTH_PASSWORD (3)
+ - CURLOPT_TLSAUTH_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_TLSAUTH_TYPE - HTTPS proxy TLS authentication methods
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE,
+ char *type);
+~~~
+
+# DESCRIPTION
+
+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".
+
+## SRP
+
+TLS-SRP authentication. Secure Remote Password authentication for TLS is
+defined in RFC 5054 and provides mutual authentication if both sides have a
+shared secret. To use TLS-SRP, you must also set the
+CURLOPT_PROXY_TLSAUTH_USERNAME(3) and
+CURLOPT_PROXY_TLSAUTH_PASSWORD(3) options.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_TYPE, "SRP");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, "user");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, "secret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0
+
+You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this
+to work.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3
deleted file mode 100644
index 8cc73fe7a..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_TLSAUTH_USERNAME 3 "16 Nov 2016" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME,
- char *user);
-.fi
-.SH DESCRIPTION
-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.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_TYPE, "SRP");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, "user");
- curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, "secret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.52.0, with the OpenSSL and GnuTLS backends only.
-.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_TLSAUTH_PASSWORD (3),
-.BR CURLOPT_PROXY_TLSAUTH_TYPE (3),
-.BR CURLOPT_TLSAUTH_PASSWORD (3),
-.BR CURLOPT_TLSAUTH_TYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md
new file mode 100644
index 000000000..612ff4f92
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_TLSAUTH_USERNAME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_TLSAUTH_PASSWORD (3)
+ - CURLOPT_PROXY_TLSAUTH_TYPE (3)
+ - CURLOPT_TLSAUTH_PASSWORD (3)
+ - CURLOPT_TLSAUTH_TYPE (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_TLSAUTH_USERNAME - user name to use for proxy TLS authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME,
+ char *user);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should point to the null-terminated
+username to use for the HTTPS proxy TLS authentication method specified with
+the CURLOPT_PROXY_TLSAUTH_TYPE(3) option. Requires that the
+CURLOPT_PROXY_TLSAUTH_PASSWORD(3) option also be set.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_TYPE, "SRP");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, "user");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, "secret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.52.0, with the OpenSSL and GnuTLS backends only.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3 b/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3
deleted file mode 100644
index 495133e7f..000000000
--- a/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PROXY_TRANSFER_MODE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PROXY_TRANSFER_MODE \- append FTP transfer mode to URL for proxy
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TRANSFER_MODE,
- long enabled);
-.fi
-.SH DESCRIPTION
-Pass a long. If the value is set to 1 (one), it tells libcurl to set the
-transfer mode (binary or ASCII) for FTP transfers done via an HTTP proxy, by
-appending ;type=a or ;type=i to the URL. Without this setting, or it being set
-to 0 (zero, the default), \fICURLOPT_TRANSFERTEXT(3)\fP has no effect when
-doing FTP via a proxy. Beware that not all proxies support this feature.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-FTP over proxy
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/old-server/file.txt");
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:80");
- curl_easy_setopt(curl, CURLOPT_PROXY_TRANSFER_MODE, 1L);
- curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.18.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if the
-enabled value is not supported.
-.SH "SEE ALSO"
-.BN CURLOPT_CRLF (3),
-.BN CURLOPT_TRANSFERTEXT (3),
-.BR CURLOPT_HTTPPROXYTUNNEL (3),
-.BR CURLOPT_PROXY (3)
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md b/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md
new file mode 100644
index 000000000..c0fed8b21
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PROXY_TRANSFER_MODE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CRLF (3)
+ - CURLOPT_HTTPPROXYTUNNEL (3)
+ - CURLOPT_PROXY (3)
+ - CURLOPT_TRANSFERTEXT (3)
+---
+
+# NAME
+
+CURLOPT_PROXY_TRANSFER_MODE - append FTP transfer mode to URL for proxy
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TRANSFER_MODE,
+ long enabled);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If the value is set to 1 (one), it tells libcurl to set the
+transfer mode (binary or ASCII) for FTP transfers done via an HTTP proxy, by
+appending ;type=a or ;type=i to the URL. Without this setting, or it being set
+to 0 (zero, the default), CURLOPT_TRANSFERTEXT(3) has no effect when
+doing FTP via a proxy. Beware that not all proxies support this feature.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+FTP over proxy
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL,
+ "ftp://example.com/old-server/file.txt");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:80");
+ curl_easy_setopt(curl, CURLOPT_PROXY_TRANSFER_MODE, 1L);
+ curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.18.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if the
+enabled value is not supported.
diff --git a/docs/libcurl/opts/CURLOPT_PUT.3 b/docs/libcurl/opts/CURLOPT_PUT.3
deleted file mode 100644
index 0330878f8..000000000
--- a/docs/libcurl/opts/CURLOPT_PUT.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_PUT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_PUT \- make an HTTP PUT request
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PUT, long put);
-.fi
-.SH DESCRIPTION
-A parameter set to 1 tells the library to use HTTP PUT to transfer data. The
-data should be set with \fICURLOPT_READDATA(3)\fP and
-\fICURLOPT_INFILESIZE(3)\fP.
-
-This option is \fBdeprecated\fP since version 7.12.1. Use
-\fICURLOPT_UPLOAD(3)\fP!
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- /* we want to use our own read function */
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
-
- /* enable PUT */
- curl_easy_setopt(curl, CURLOPT_PUT, 1L);
-
- /* specify target */
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/to/newfile");
-
- /* now specify which pointer to pass to our callback */
- curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
-
- /* Set the size of the file to upload */
- curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize);
-
- /* Now run off and do what you have been told! */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Deprecated since 7.12.1. Do not use.
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPGET (3),
-.BR CURLOPT_MIMEPOST (3),
-.BR CURLOPT_POSTFIELDS (3),
-.BR CURLOPT_UPLOAD (3)
diff --git a/docs/libcurl/opts/CURLOPT_PUT.md b/docs/libcurl/opts/CURLOPT_PUT.md
new file mode 100644
index 000000000..117eaedd7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PUT.md
@@ -0,0 +1,89 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_PUT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPGET (3)
+ - CURLOPT_MIMEPOST (3)
+ - CURLOPT_POSTFIELDS (3)
+ - CURLOPT_UPLOAD (3)
+---
+
+# NAME
+
+CURLOPT_PUT - make an HTTP PUT request
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PUT, long put);
+~~~
+
+# DESCRIPTION
+
+A parameter set to 1 tells the library to use HTTP PUT to transfer data. The
+data should be set with CURLOPT_READDATA(3) and
+CURLOPT_INFILESIZE(3).
+
+This option is **deprecated** since version 7.12.1. Use CURLOPT_UPLOAD(3).
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ FILE *src = userdata;
+ /* copy as much data as possible into the 'ptr' buffer, but no more than
+ 'size' * 'nmemb' bytes */
+ size_t retcode = fread(ptr, size, nmemb, src);
+
+ return retcode;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ FILE *src = fopen("local-file", "r");
+ curl_off_t fsize; /* set this to the size of the input file */
+
+ /* we want to use our own read function */
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb);
+
+ /* enable PUT */
+ curl_easy_setopt(curl, CURLOPT_PUT, 1L);
+
+ /* specify target */
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/to/newfile");
+
+ /* now specify which pointer to pass to our callback */
+ curl_easy_setopt(curl, CURLOPT_READDATA, src);
+
+ /* Set the size of the file to upload */
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize);
+
+ /* Now run off and do what you have been told */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Deprecated since 7.12.1. Do not use.
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_QUICK_EXIT.3 b/docs/libcurl/opts/CURLOPT_QUICK_EXIT.3
deleted file mode 100644
index 11fa0edcb..000000000
--- a/docs/libcurl/opts/CURLOPT_QUICK_EXIT.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_QUICK_EXIT 3 "30 Sep 2022" libcurl libcurl
-.SH NAME
-CURLOPT_QUICK_EXIT \- allow to exit quickly
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_QUICK_EXIT,
- long value);
-.SH DESCRIPTION
-Pass a long as a parameter, 1L meaning that when recovering from a timeout,
-libcurl should skip lengthy cleanups that are intended to avoid all kinds of
-leaks (threads etc.), as the caller program is about to call exit() anyway.
-This allows for a swift termination after a DNS timeout for example, by
-canceling and/or forgetting about a resolver thread, at the expense of a
-possible (though short-lived) leak of associated resources.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.87.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FAILONERROR (3),
-.BR CURLOPT_RESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_QUICK_EXIT.md b/docs/libcurl/opts/CURLOPT_QUICK_EXIT.md
new file mode 100644
index 000000000..4159c02fb
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_QUICK_EXIT.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_QUICK_EXIT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_FAILONERROR (3)
+ - CURLOPT_RESOLVE (3)
+---
+
+# NAME
+
+CURLOPT_QUICK_EXIT - allow to exit quickly
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_QUICK_EXIT,
+ long value);
+~~~
+
+# DESCRIPTION
+
+Pass a long as a parameter, 1L meaning that when recovering from a timeout,
+libcurl should skip lengthy cleanups that are intended to avoid all kinds of
+leaks (threads etc.), as the caller program is about to call exit() anyway.
+This allows for a swift termination after a DNS timeout for example, by
+canceling and/or forgetting about a resolver thread, at the expense of a
+possible (though short-lived) leak of associated resources.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.87.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_QUOTE.3 b/docs/libcurl/opts/CURLOPT_QUOTE.3
deleted file mode 100644
index 83f2c50fb..000000000
--- a/docs/libcurl/opts/CURLOPT_QUOTE.3
+++ /dev/null
@@ -1,129 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_QUOTE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_QUOTE \- (S)FTP commands to run before transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_QUOTE,
- struct curl_slist *cmds);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a linked list of FTP or SFTP commands to pass to the server
-prior to your request. This is done before any other commands are issued (even
-before the CWD command for FTP). The linked list should be a fully valid list
-of 'struct curl_slist' structs properly filled in with text strings. Use
-\fIcurl_slist_append(3)\fP to append strings (commands) to the list, and clear
-the entire list afterwards with \fIcurl_slist_free_all(3)\fP.
-
-Disable this operation again by setting a NULL to this option.
-
-When speaking to an FTP server, prefix the command with an asterisk (*) to
-make libcurl continue even if the command fails as by default libcurl stops at
-first failure.
-
-The set of valid FTP commands depends on the server (see RFC 959 for a list of
-mandatory commands).
-
-libcurl does not inspect, parse or "understand" the commands passed to the
-server using this option. If you change connection state, working directory or
-similar using quote commands, libcurl does not know about it.
-
-The valid SFTP commands are:
-.RS
-.IP "atime date file"
-The atime command sets the last access time of the file named by the file
-operand. The <date expression> can be all sorts of date strings, see the
-\fIcurl_getdate(3)\fP man page for date expression details. (Added in 7.73.0)
-.IP "chgrp group file"
-The chgrp command sets the group ID of the file named by the file operand to
-the group ID specified by the group operand. The group operand is a decimal
-integer group ID.
-.IP "chmod mode file"
-The chmod command modifies the file mode bits of the specified file. The
-mode operand is an octal integer mode number.
-.IP "chown user file"
-The chown command sets the owner of the file named by the file operand to the
-user ID specified by the user operand. The user operand is a decimal
-integer user ID.
-.IP "ln source_file target_file"
-The \fBln\fP and \fBsymlink\fP commands create a symbolic link at the
-target_file location pointing to the source_file location.
-.IP "mkdir directory_name"
-The mkdir command creates the directory named by the directory_name operand.
-.IP "mtime date file"
-The mtime command sets the last modification time of the file named by the
-file operand. The <date expression> can be all sorts of date strings, see the
-\fIcurl_getdate(3)\fP man page for date expression details. (Added in 7.73.0)
-.IP "pwd"
-The \fBpwd\fP command returns the absolute path of the current working
-directory.
-.IP "rename source target"
-The rename command renames the file or directory named by the source
-operand to the destination path named by the target operand.
-.IP "rm file"
-The rm command removes the file specified by the file operand.
-.IP "rmdir directory"
-The rmdir command removes the directory entry specified by the directory
-operand, provided it is empty.
-.IP "statvfs file"
-The statvfs command returns statistics on the file system in which specified
-file resides. (Added in 7.49.0)
-.IP "symlink source_file target_file"
-See ln.
-.RE
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SFTP and FTP
-.SH EXAMPLE
-.nf
-struct curl_slist *cmdlist = NULL;
-cmdlist = curl_slist_append(cmdlist, "RNFR source-name");
-cmdlist = curl_slist_append(cmdlist, "RNTO new-name");
-
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
-
- /* pass in the FTP commands to run before the transfer */
- curl_easy_setopt(curl, CURLOPT_QUOTE, cmdlist);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-SFTP support added in 7.16.3. *-prefix for SFTP added in 7.24.0
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_CUSTOMREQUEST (3),
-.BR CURLOPT_DIRLISTONLY (3),
-.BR CURLOPT_POSTQUOTE (3),
-.BR CURLOPT_PREQUOTE (3)
diff --git a/docs/libcurl/opts/CURLOPT_QUOTE.md b/docs/libcurl/opts/CURLOPT_QUOTE.md
new file mode 100644
index 000000000..f57b45eec
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_QUOTE.md
@@ -0,0 +1,161 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_QUOTE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CUSTOMREQUEST (3)
+ - CURLOPT_DIRLISTONLY (3)
+ - CURLOPT_POSTQUOTE (3)
+ - CURLOPT_PREQUOTE (3)
+---
+
+# NAME
+
+CURLOPT_QUOTE - (S)FTP commands to run before transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_QUOTE,
+ struct curl_slist *cmds);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of FTP or SFTP commands to pass to the server
+prior to your request. This is done before any other commands are issued (even
+before the CWD command for FTP). The linked list should be a fully valid list
+of 'struct curl_slist' structs properly filled in with text strings. Use
+curl_slist_append(3) to append strings (commands) to the list, and clear
+the entire list afterwards with curl_slist_free_all(3).
+
+Disable this operation again by setting a NULL to this option.
+
+When speaking to an FTP server, prefix the command with an asterisk (*) to
+make libcurl continue even if the command fails as by default libcurl stops at
+first failure.
+
+The set of valid FTP commands depends on the server (see RFC 959 for a list of
+mandatory commands).
+
+libcurl does not inspect, parse or "understand" the commands passed to the
+server using this option. If you change connection state, working directory or
+similar using quote commands, libcurl does not know about it.
+
+The path arguments for FTP or SFTP can use single or double quotes to
+distinguish a space from being the parameter separator or being a part of the
+path. e.g. rename with sftp using a quote command like this:
+
+ "rename 'test/_upload.txt' 'test/Hello World.txt'"
+
+# SFTP commands
+
+## atime date file
+
+The atime command sets the last access time of the file named by the file
+operand. The <date expression> can be all sorts of date strings, see the
+curl_getdate(3) man page for date expression details. (Added in 7.73.0)
+
+## chgrp group file
+
+The chgrp command sets the group ID of the file named by the file operand to
+the group ID specified by the group operand. The group operand is a decimal
+integer group ID.
+
+## chmod mode file
+
+The chmod command modifies the file mode bits of the specified file. The
+mode operand is an octal integer mode number.
+
+## chown user file
+
+The chown command sets the owner of the file named by the file operand to the
+user ID specified by the user operand. The user operand is a decimal
+integer user ID.
+
+## ln source_file target_file
+
+The **ln** and **symlink** commands create a symbolic link at the
+target_file location pointing to the source_file location.
+
+## mkdir directory_name
+
+The mkdir command creates the directory named by the directory_name operand.
+
+## mtime date file
+
+The mtime command sets the last modification time of the file named by the
+file operand. The <date expression> can be all sorts of date strings, see the
+curl_getdate(3) man page for date expression details. (Added in 7.73.0)
+
+## pwd
+
+The **pwd** command returns the absolute path of the current working
+directory.
+
+## rename source target
+
+The rename command renames the file or directory named by the source
+operand to the destination path named by the target operand.
+
+## rm file
+
+The rm command removes the file specified by the file operand.
+
+## rmdir directory
+
+The rmdir command removes the directory entry specified by the directory
+operand, provided it is empty.
+
+## statvfs file
+
+The statvfs command returns statistics on the file system in which specified
+file resides. (Added in 7.49.0)
+
+## symlink source_file target_file
+
+See ln.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SFTP and FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ struct curl_slist *cmdlist = NULL;
+ cmdlist = curl_slist_append(cmdlist, "RNFR source-name");
+ cmdlist = curl_slist_append(cmdlist, "RNTO new-name");
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin");
+
+ /* pass in the FTP commands to run before the transfer */
+ curl_easy_setopt(curl, CURLOPT_QUOTE, cmdlist);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+SFTP support added in 7.16.3. *-prefix for SFTP added in 7.24.0
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3 b/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3
deleted file mode 100644
index da5196d1d..000000000
--- a/docs/libcurl/opts/CURLOPT_RANDOM_FILE.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RANDOM_FILE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RANDOM_FILE \- file to read random data from
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANDOM_FILE, char *path);
-.fi
-.SH DESCRIPTION
-Deprecated option. It serves no purpose anymore.
-
-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
-option.
-.SH DEFAULT
-NULL, not used
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_RANDOM_FILE, "junk.txt");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If built with TLS enabled. Only the OpenSSL backend uses this, and only with
-OpenSSL versions before 1.1.0.
-
-This option was deprecated in 7.84.0.
-.SH RETURN VALUE
-Returns CURLE_OK on success or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_EGDSOCKET (3)
diff --git a/docs/libcurl/opts/CURLOPT_RANDOM_FILE.md b/docs/libcurl/opts/CURLOPT_RANDOM_FILE.md
new file mode 100644
index 000000000..7675461a2
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RANDOM_FILE.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RANDOM_FILE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_EGDSOCKET (3)
+---
+
+# NAME
+
+CURLOPT_RANDOM_FILE - file to read random data from
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANDOM_FILE, char *path);
+~~~
+
+# DESCRIPTION
+
+Deprecated option. It serves no purpose anymore.
+
+Pass a char pointer to a null-terminated filename. 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
+option.
+
+# DEFAULT
+
+NULL, not used
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_RANDOM_FILE, "junk.txt");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built with TLS enabled. Only the OpenSSL backend uses this, and only with
+OpenSSL versions before 1.1.0.
+
+This option was deprecated in 7.84.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK on success or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_RANGE.3 b/docs/libcurl/opts/CURLOPT_RANGE.3
deleted file mode 100644
index 3b20a5206..000000000
--- a/docs/libcurl/opts/CURLOPT_RANGE.3
+++ /dev/null
@@ -1,83 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RANGE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RANGE \- byte range to request
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANGE, char *range);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter, which should contain the specified range you want
-to retrieve. It should be in the format "X-Y", where either X or Y may be left
-out and X and Y are byte indexes.
-
-HTTP transfers also support several intervals, separated with commas as in
-\fI"X-Y,N-M"\fP. Using this kind of multiple intervals causes the HTTP server
-to send the response document in pieces (using standard MIME separation
-techniques). Unfortunately, the HTTP standard (RFC 7233 section 3.1) allows
-servers to ignore range requests so even when you set \fICURLOPT_RANGE(3)\fP
-for a request, you may end up getting the full response sent back.
-
-For RTSP, the formatting of a range should follow RFC 2326 Section 12.29. For
-RTSP, byte ranges are \fBnot\fP permitted. Instead, ranges should be given in
-\fBnpt\fP, \fButc\fP, or \fBsmpte\fP formats.
-
-For HTTP PUT uploads this option should not be used, since it may conflict with
-other options.
-
-Pass a NULL to this option to disable the use of ranges.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP, FTP, FILE, RTSP and SFTP.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* get the first 200 bytes */
- curl_easy_setopt(curl, CURLOPT_RANGE, "0-199");
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-FILE since 7.18.0, RTSP since 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK on success or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3),
-.BR CURLOPT_MAXFILESIZE_LARGE (3),
-.BR CURLOPT_RESUME_FROM (3)
diff --git a/docs/libcurl/opts/CURLOPT_RANGE.md b/docs/libcurl/opts/CURLOPT_RANGE.md
new file mode 100644
index 000000000..3f765bc61
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RANGE.md
@@ -0,0 +1,84 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RANGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_MAXFILESIZE_LARGE (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+ - CURLOPT_RESUME_FROM (3)
+---
+
+# NAME
+
+CURLOPT_RANGE - byte range to request
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANGE, char *range);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should contain the specified range you
+want to retrieve. It should be in the format "X-Y", where either X or Y may be
+left out and X and Y are byte indexes.
+
+HTTP transfers also support several intervals, separated with commas as in
+*"X-Y,N-M"*. Using this kind of multiple intervals causes the HTTP server
+to send the response document in pieces (using standard MIME separation
+techniques). Unfortunately, the HTTP standard (RFC 7233 section 3.1) allows
+servers to ignore range requests so even when you set CURLOPT_RANGE(3)
+for a request, you may end up getting the full response sent back.
+
+For RTSP, the formatting of a range should follow RFC 2326 Section 12.29. For
+RTSP, byte ranges are **not** permitted. Instead, ranges should be given in
+**npt**, **utc**, or **smpte** formats.
+
+For HTTP PUT uploads this option should not be used, since it may conflict with
+other options.
+
+Pass a NULL to this option to disable the use of ranges.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP, FTP, FILE, RTSP and SFTP.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* get the first 200 bytes */
+ curl_easy_setopt(curl, CURLOPT_RANGE, "0-199");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+FILE since 7.18.0, RTSP since 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK on success or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_READDATA.3 b/docs/libcurl/opts/CURLOPT_READDATA.3
deleted file mode 100644
index f8ab7940a..000000000
--- a/docs/libcurl/opts/CURLOPT_READDATA.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_READDATA 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_READDATA \- pointer passed to the read callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_READDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Data \fIpointer\fP to pass to the file read function. If you use the
-\fICURLOPT_READFUNCTION(3)\fP option, this is the pointer you get as input in
-the fourth argument to the callback.
-
-If you do not specify a read callback but instead rely on the default internal
-read function, this data must be a valid readable FILE * (cast to 'void *').
-
-If you are using libcurl as a DLL on Windows, you must use the
-\fICURLOPT_READFUNCTION(3)\fP callback if you set this option, otherwise you
-might experience crashes.
-.SH DEFAULT
-By default, this is a FILE * to stdin.
-.SH PROTOCOLS
-This is used for all protocols when sending data.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-struct MyData this;
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* pass pointer that gets passed in to the
- CURLOPT_READFUNCTION callback */
- curl_easy_setopt(curl, CURLOPT_READDATA, &this);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-This option was once known by the older name CURLOPT_INFILE, the name
-\fICURLOPT_READDATA(3)\fP was introduced in 7.9.7.
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_HEADERDATA (3),
-.BR CURLOPT_READFUNCTION (3),
-.BR CURLOPT_WRITEDATA (3),
-.BR CURLOPT_WRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_READDATA.md b/docs/libcurl/opts/CURLOPT_READDATA.md
new file mode 100644
index 000000000..d7aa4ff9a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_READDATA.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_READDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERDATA (3)
+ - CURLOPT_READFUNCTION (3)
+ - CURLOPT_WRITEDATA (3)
+ - CURLOPT_WRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_READDATA - pointer passed to the read callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_READDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Data *pointer* to pass to the file read function. If you use the
+CURLOPT_READFUNCTION(3) option, this is the pointer you get as input in
+the fourth argument to the callback.
+
+If you do not specify a read callback but instead rely on the default internal
+read function, this data must be a valid readable FILE * (cast to 'void *').
+
+If you are using libcurl as a DLL on Windows, you must use the
+CURLOPT_READFUNCTION(3) callback if you set this option, otherwise you
+might experience crashes.
+
+# DEFAULT
+
+By default, this is a FILE * to stdin.
+
+# PROTOCOLS
+
+This is used for all protocols when sending data.
+
+# EXAMPLE
+
+~~~c
+struct MyData {
+ void *custom;
+};
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ struct MyData this;
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* pass pointer that gets passed in to the
+ CURLOPT_READFUNCTION callback */
+ curl_easy_setopt(curl, CURLOPT_READDATA, &this);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was once known by the older name CURLOPT_INFILE, the name
+CURLOPT_READDATA(3) was introduced in 7.9.7.
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_READFUNCTION.3 b/docs/libcurl/opts/CURLOPT_READFUNCTION.3
deleted file mode 100644
index 4aeb6dee0..000000000
--- a/docs/libcurl/opts/CURLOPT_READFUNCTION.3
+++ /dev/null
@@ -1,122 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_READFUNCTION 3 "25 Jun 2020" libcurl libcurl
-.SH NAME
-CURLOPT_READFUNCTION \- read callback for data uploads
-.SH SYNOPSIS
-.nf
-#include <curl/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);
-.fi
-.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. \fIsize\fP is always 1.
-
-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 signals
-end-of-file to the library and causes 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 have said you would 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 is not sent.
-
-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 is considered the final packet by the server
-end and the transfer ends there.
-
-If you set this callback pointer to NULL, or do not set it at all, the default
-internal read function is used. It is doing an fread() on the FILE * userdata
-set with \fICURLOPT_READDATA(3)\fP.
-
-You can set the total size of the data you are sending by using
-\fICURLOPT_INFILESIZE_LARGE(3)\fP or \fICURLOPT_POSTFIELDSIZE_LARGE(3)\fP,
-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
-This is used for all protocols when doing uploads.
-.SH EXAMPLE
-.nf
-size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
-{
- FILE *readhere = (FILE *)userdata;
- curl_off_t nread;
-
- /* copy as much data as possible into the 'ptr' buffer, but no more than
- 'size' * 'nmemb' bytes! */
- size_t retcode = fread(ptr, size, nmemb, readhere);
-
- nread = (curl_off_t)retcode;
-
- fprintf(stderr, "*** We read %" CURL_FORMAT_CURL_OFF_T
- " bytes from file\\n", nread);
- return retcode;
-}
-
-void setup(char *uploadthis)
-{
- FILE *file = fopen(uploadthis, "rb");
- CURLcode result;
-
- /* set callback to use */
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
-
- /* pass in suitable argument to callback */
- curl_easy_setopt(curl, CURLOPT_READDATA, (void *)file);
-
- result = curl_easy_perform(curl);
-}
-.fi
-.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
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_POST (3),
-.BR CURLOPT_READDATA (3),
-.BR CURLOPT_SEEKFUNCTION (3),
-.BR CURLOPT_UPLOAD (3),
-.BR CURLOPT_UPLOAD_BUFFERSIZE (3),
-.BR CURLOPT_WRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_READFUNCTION.md b/docs/libcurl/opts/CURLOPT_READFUNCTION.md
new file mode 100644
index 000000000..978440d13
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_READFUNCTION.md
@@ -0,0 +1,123 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_READFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_POST (3)
+ - CURLOPT_READDATA (3)
+ - CURLOPT_SEEKFUNCTION (3)
+ - CURLOPT_UPLOAD (3)
+ - CURLOPT_UPLOAD_BUFFERSIZE (3)
+ - CURLOPT_WRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_READFUNCTION - read callback for data uploads
+
+# SYNOPSIS
+
+~~~c
+#include <curl/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);
+~~~
+
+# 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 *buffer* should be
+filled up with at most *size* multiplied with *nitems* number of bytes
+by your function. *size* is always 1.
+
+Set the *userdata* argument with the 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 *buffer*. Returning 0 signals
+end-of-file to the library and causes 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 have said you would 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 is not sent.
+
+The read callback may return *CURL_READFUNC_ABORT* to stop the current
+operation immediately, resulting in a *CURLE_ABORTED_BY_CALLBACK* error
+code from the transfer.
+
+The callback can return *CURL_READFUNC_PAUSE* to cause reading from this
+connection to pause. See curl_easy_pause(3) for further details.
+
+**Bugs**: when doing TFTP uploads, you must return the exact amount of data
+that the callback wants, or it is considered the final packet by the server
+end and the transfer ends there.
+
+If you set this callback pointer to NULL, or do not set it at all, the default
+internal read function is used. It is doing an fread() on the FILE * userdata
+set with CURLOPT_READDATA(3).
+
+You can set the total size of the data you are sending by using
+CURLOPT_INFILESIZE_LARGE(3) or 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.
+
+# DEFAULT
+
+The default internal read callback is fread().
+
+# PROTOCOLS
+
+This is used for all protocols when doing uploads.
+
+# EXAMPLE
+
+~~~c
+size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ FILE *readhere = (FILE *)userdata;
+ curl_off_t nread;
+
+ /* copy as much data as possible into the 'ptr' buffer, but no more than
+ 'size' * 'nmemb' bytes! */
+ size_t retcode = fread(ptr, size, nmemb, readhere);
+
+ nread = (curl_off_t)retcode;
+
+ fprintf(stderr, "*** We read %" CURL_FORMAT_CURL_OFF_T
+ " bytes from file\n", nread);
+ return retcode;
+}
+
+int main(int argc, char **argv)
+{
+ FILE *file = fopen(argv[1], "rb");
+ CURLcode result;
+
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* set callback to use */
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
+
+ /* pass in suitable argument to callback */
+ curl_easy_setopt(curl, CURLOPT_READDATA, (void *)file);
+
+ result = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+CURL_READFUNC_PAUSE return code was added in 7.18.0 and CURL_READFUNC_ABORT
+was added in 7.12.1.
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3 b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
deleted file mode 100644
index a0cfb0df4..000000000
--- a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.3
+++ /dev/null
@@ -1,114 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_REDIR_PROTOCOLS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_REDIR_PROTOCOLS \- protocols allowed to redirect to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS, long bitmask);
-.fi
-.SH DESCRIPTION
-This option is deprecated. We strongly recommend using
-\fICURLOPT_REDIR_PROTOCOLS_STR(3)\fP instead because this option cannot
-control all available protocols!
-
-Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
-limits what protocols libcurl may use in a transfer that it follows to in a
-redirect when \fICURLOPT_FOLLOWLOCATION(3)\fP is enabled. This allows you to
-limit specific transfers to only be allowed to use a subset of protocols in
-redirections.
-
-Protocols denied by \fICURLOPT_PROTOCOLS(3)\fP are not overridden by this
-option.
-
-By default libcurl allows HTTP, HTTPS, FTP and FTPS on redirect (7.65.2).
-\fICURLPROTO_ALL\fP enables all protocols on redirect, including those
-otherwise disabled for security.
-
-These are the available protocol defines:
-.nf
-CURLPROTO_DICT
-CURLPROTO_FILE
-CURLPROTO_FTP
-CURLPROTO_FTPS
-CURLPROTO_GOPHER
-CURLPROTO_HTTP
-CURLPROTO_HTTPS
-CURLPROTO_IMAP
-CURLPROTO_IMAPS
-CURLPROTO_LDAP
-CURLPROTO_LDAPS
-CURLPROTO_POP3
-CURLPROTO_POP3S
-CURLPROTO_RTMP
-CURLPROTO_RTMPE
-CURLPROTO_RTMPS
-CURLPROTO_RTMPT
-CURLPROTO_RTMPTE
-CURLPROTO_RTMPTS
-CURLPROTO_RTSP
-CURLPROTO_SCP
-CURLPROTO_SFTP
-CURLPROTO_SMB
-CURLPROTO_SMBS
-CURLPROTO_SMTP
-CURLPROTO_SMTPS
-CURLPROTO_TELNET
-CURLPROTO_TFTP
-.fi
-.SH DEFAULT
-HTTP, HTTPS, FTP and FTPS (Added in 7.65.2).
-
-Older versions defaulted to all protocols except FILE, SCP and since 7.40.0
-SMB and SMBS.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- /* pass in the URL from an external source */
- curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
-
- /* only allow redirects to HTTP and HTTPS URLs */
- curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS,
- CURLPROTO_HTTP | CURLPROTO_HTTPS);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.4, before then it would follow all protocols. Deprecated
-since 7.85.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_SCHEME (3),
-.BR CURLOPT_DEFAULT_PROTOCOL (3),
-.BR CURLOPT_PROTOCOLS (3),
-.BR CURLOPT_REDIR_PROTOCOLS_STR (3)
diff --git a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.md b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.md
new file mode 100644
index 000000000..4d06d4658
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS.md
@@ -0,0 +1,115 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_REDIR_PROTOCOLS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SCHEME (3)
+ - CURLOPT_DEFAULT_PROTOCOL (3)
+ - CURLOPT_PROTOCOLS (3)
+ - CURLOPT_REDIR_PROTOCOLS_STR (3)
+---
+
+# NAME
+
+CURLOPT_REDIR_PROTOCOLS - protocols allowed to redirect to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS, long bitmask);
+~~~
+
+# DESCRIPTION
+
+This option is deprecated. We strongly recommend using
+CURLOPT_REDIR_PROTOCOLS_STR(3) instead because this option cannot
+control all available protocols!
+
+Pass a long that holds a bitmask of CURLPROTO_* defines. If used, this bitmask
+limits what protocols libcurl may use in a transfer that it follows to in a
+redirect when CURLOPT_FOLLOWLOCATION(3) is enabled. This allows you to
+limit specific transfers to only be allowed to use a subset of protocols in
+redirections.
+
+Protocols denied by CURLOPT_PROTOCOLS(3) are not overridden by this
+option.
+
+By default libcurl allows HTTP, HTTPS, FTP and FTPS on redirect (7.65.2).
+*CURLPROTO_ALL* enables all protocols on redirect, including those
+otherwise disabled for security.
+
+These are the available protocol defines:
+~~~c
+CURLPROTO_DICT
+CURLPROTO_FILE
+CURLPROTO_FTP
+CURLPROTO_FTPS
+CURLPROTO_GOPHER
+CURLPROTO_HTTP
+CURLPROTO_HTTPS
+CURLPROTO_IMAP
+CURLPROTO_IMAPS
+CURLPROTO_LDAP
+CURLPROTO_LDAPS
+CURLPROTO_POP3
+CURLPROTO_POP3S
+CURLPROTO_RTMP
+CURLPROTO_RTMPE
+CURLPROTO_RTMPS
+CURLPROTO_RTMPT
+CURLPROTO_RTMPTE
+CURLPROTO_RTMPTS
+CURLPROTO_RTSP
+CURLPROTO_SCP
+CURLPROTO_SFTP
+CURLPROTO_SMB
+CURLPROTO_SMBS
+CURLPROTO_SMTP
+CURLPROTO_SMTPS
+CURLPROTO_TELNET
+CURLPROTO_TFTP
+~~~
+
+# DEFAULT
+
+HTTP, HTTPS, FTP and FTPS (Added in 7.65.2).
+
+Older versions defaulted to all protocols except FILE, SCP and since 7.40.0
+SMB and SMBS.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(int argc, char **argv)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* pass in the URL from an external source */
+ curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
+
+ /* only allow redirects to HTTP and HTTPS URLs */
+ curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS,
+ CURLPROTO_HTTP | CURLPROTO_HTTPS);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.4, before then it would follow all protocols. Deprecated
+since 7.85.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.3 b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.3
deleted file mode 100644
index 0ddb6ff02..000000000
--- a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.3
+++ /dev/null
@@ -1,93 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_REDIR_PROTOCOLS_STR 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_REDIR_PROTOCOLS_STR \- protocols allowed to redirect to
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS_STR,
- char *spec);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a string that holds a comma-separated list of case
-insensitive protocol names (URL schemes). That list limits what protocols
-libcurl may use in a transfer that it follows to in a redirect when
-\fICURLOPT_FOLLOWLOCATION(3)\fP is enabled. This option allows applications to
-limit specific transfers to only be allowed to use a subset of protocols in
-redirections.
-
-Protocols denied by \fICURLOPT_PROTOCOLS_STR(3)\fP are not overridden by this
-option.
-
-By default libcurl allows HTTP, HTTPS, FTP and FTPS on redirects (since
-7.65.2).
-
-These are the available protocols:
-
-DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
-MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
-SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
-
-You can set "ALL" as a short-cut to enable all protocols. Note that by setting
-all, you may enable protocols that were not supported the day you write this
-but are introduced in a future libcurl version.
-
-If trying to set a non-existing protocol or if no matching protocol at all is
-set, it returns error.
-.SH DEFAULT
-HTTP, HTTPS, FTP and FTPS (Added in 7.65.2).
-
-Older versions defaulted to all protocols except FILE, SCP and since 7.40.0
-SMB and SMBS.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- /* pass in the URL from an external source */
- curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
-
- /* only allow redirects to HTTP and HTTPS URLs */
- curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https");
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.85.0.
-.SH RETURN VALUE
-Returns CURLE_UNKNOWN_OPTION if the option is not implemented,
-CURLE_UNSUPPORTED_PROTOCOL if a listed protocol is not supported or disabled,
-CURLE_BAD_FUNCTION_ARGUMENT if no protocol is listed else CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_PROTOCOLS_STR (3),
-.BR CURLINFO_SCHEME (3),
-.BR CURLOPT_DEFAULT_PROTOCOL (3),
-.BR CURLOPT_PROTOCOLS (3),
-.BR CURLOPT_REDIR_PROTOCOLS (3)
diff --git a/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.md b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.md
new file mode 100644
index 000000000..9201a4b41
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_REDIR_PROTOCOLS_STR.md
@@ -0,0 +1,94 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_REDIR_PROTOCOLS_STR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SCHEME (3)
+ - CURLOPT_DEFAULT_PROTOCOL (3)
+ - CURLOPT_PROTOCOLS (3)
+ - CURLOPT_PROTOCOLS_STR (3)
+ - CURLOPT_REDIR_PROTOCOLS (3)
+---
+
+# NAME
+
+CURLOPT_REDIR_PROTOCOLS_STR - protocols allowed to redirect to
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REDIR_PROTOCOLS_STR,
+ char *spec);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a string that holds a comma-separated list of case
+insensitive protocol names (URL schemes). That list limits what protocols
+libcurl may use in a transfer that it follows to in a redirect when
+CURLOPT_FOLLOWLOCATION(3) is enabled. This option allows applications to
+limit specific transfers to only be allowed to use a subset of protocols in
+redirections.
+
+Protocols denied by CURLOPT_PROTOCOLS_STR(3) are not overridden by this
+option.
+
+By default libcurl allows HTTP, HTTPS, FTP and FTPS on redirects (since
+7.65.2).
+
+These are the available protocols:
+
+DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
+MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
+SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
+
+You can set "ALL" as a short-cut to enable all protocols. Note that by setting
+all, you may enable protocols that were not supported the day you write this
+but are introduced in a future libcurl version.
+
+If trying to set a non-existing protocol or if no matching protocol at all is
+set, it returns error.
+
+# DEFAULT
+
+HTTP, HTTPS, FTP and FTPS (Added in 7.65.2).
+
+Older versions defaulted to all protocols except FILE, SCP and since 7.40.0
+SMB and SMBS.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(int argc, char **argv)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* pass in the URL from an external source */
+ curl_easy_setopt(curl, CURLOPT_URL, argv[1]);
+
+ /* only allow redirects to HTTP and HTTPS URLs */
+ curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.85.0.
+
+# RETURN VALUE
+
+Returns CURLE_UNKNOWN_OPTION if the option is not implemented,
+CURLE_UNSUPPORTED_PROTOCOL if a listed protocol is not supported or disabled,
+CURLE_BAD_FUNCTION_ARGUMENT if no protocol is listed else CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_REFERER.3 b/docs/libcurl/opts/CURLOPT_REFERER.3
deleted file mode 100644
index f294bdaf7..000000000
--- a/docs/libcurl/opts/CURLOPT_REFERER.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_REFERER 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_REFERER \- the HTTP referer header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REFERER, char *where);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter. It is used to set the
-Referer: header field in the HTTP request sent to the remote server. You can
-set any custom header with \fICURLOPT_HTTPHEADER(3)\fP.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* tell it where we found the link to this place */
- curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.com/aboutme.html");
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-If built with HTTP support
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP support is enabled, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLINFO_REDIRECT_URL (3),
-.BR CURLINFO_REFERER (3),
-.BR CURLOPT_HTTPHEADER (3),
-.BR CURLOPT_USERAGENT (3)
diff --git a/docs/libcurl/opts/CURLOPT_REFERER.md b/docs/libcurl/opts/CURLOPT_REFERER.md
new file mode 100644
index 000000000..6af19cb01
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_REFERER.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_REFERER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_URL (3)
+ - CURLINFO_REFERER (3)
+ - CURLOPT_HTTPHEADER (3)
+ - CURLOPT_USERAGENT (3)
+---
+
+# NAME
+
+CURLOPT_REFERER - the HTTP referer header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REFERER, char *where);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. It is used to set the
+Referer: header field in the HTTP request sent to the remote server. You can
+set any custom header with CURLOPT_HTTPHEADER(3).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* tell it where we found the link to this place */
+ curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.org/me.html");
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built with HTTP support
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP support is enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3 b/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3
deleted file mode 100644
index bd26a95b6..000000000
--- a/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_REQUEST_TARGET 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_REQUEST_TARGET \- alternative target for this request
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
-.fi
-.SH DESCRIPTION
-Pass a char * to string which libcurl uses in the upcoming request instead of
-the path as extracted from the URL.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/*");
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
-
- /* issue an OPTIONS * request (no leading slash) */
- curl_easy_setopt(curl, CURLOPT_REQUEST_TARGET, "*");
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CUSTOMREQUEST (3),
-.BR CURLOPT_HTTPGET (3),
-.BR CURLOPT_PATH_AS_IS (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.md b/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.md
new file mode 100644
index 000000000..cfc15d7b4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_REQUEST_TARGET.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_REQUEST_TARGET
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CUSTOMREQUEST (3)
+ - CURLOPT_HTTPGET (3)
+ - CURLOPT_PATH_AS_IS (3)
+ - CURLOPT_URL (3)
+---
+
+# NAME
+
+CURLOPT_REQUEST_TARGET - alternative target for this request
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to string which libcurl uses in the upcoming request
+instead of the path as extracted from the URL.
+
+libcurl passes on the verbatim string in its request without any filter or
+other safe guards. That includes white space and control characters.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/*");
+ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+
+ /* issue an OPTIONS * request (no leading slash) */
+ curl_easy_setopt(curl, CURLOPT_REQUEST_TARGET, "*");
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVE.3 b/docs/libcurl/opts/CURLOPT_RESOLVE.3
deleted file mode 100644
index 670089e8b..000000000
--- a/docs/libcurl/opts/CURLOPT_RESOLVE.3
+++ /dev/null
@@ -1,113 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RESOLVE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RESOLVE \- provide custom host name to IP address resolves
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVE,
- struct curl_slist *hosts);
-.SH DESCRIPTION
-Pass a pointer to a linked list of strings with host name resolve information
-to use for requests with this handle. The linked list should be a fully valid
-list of \fBstruct curl_slist\fP structs properly filled in. Use
-\fIcurl_slist_append(3)\fP to create the list and \fIcurl_slist_free_all(3)\fP
-to clean up an entire list.
-
-Each resolve rule to add should be written using the format
-
-.nf
- [+]HOST:PORT:ADDRESS[,ADDRESS]
-.fi
-
-HOST is the name libcurl wants to resolve, PORT is the port number of the
-service where libcurl wants to connect to the HOST and ADDRESS is one or more
-numerical IP addresses. If you specify multiple IP addresses they need to be
-separated by comma. If libcurl is built to support IPv6, each of the ADDRESS
-entries can of course be either IPv4 or IPv6 style addressing.
-
-This option effectively populates the DNS cache with entries for the host+port
-pair so redirects and everything that operations against the HOST+PORT instead
-use your provided ADDRESS.
-
-The optional leading "+" specifies that the new entry should time-out. Entries
-added without the leading plus character never times out whereas entries added
-with "+HOST:..." times out just like ordinary DNS cache entries.
-
-If the DNS cache already has an entry for the given host+port pair, the new
-entry overrides the former one.
-
-An ADDRESS provided by this option is only used if not restricted by the
-setting of \fICURLOPT_IPRESOLVE(3)\fP to a different IP version.
-
-To remove names from the DNS cache again, to stop providing these fake
-resolves, include a string in the linked list that uses the format
-
-.nf
- -HOST:PORT
-.fi
-
-The entry to remove must be prefixed with a dash, and the host name and port
-number must exactly match what was added previously.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl;
-struct curl_slist *host = NULL;
-host = curl_slist_append(NULL, "example.com:443:127.0.0.1");
-
-curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_perform(curl);
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-
-curl_slist_free_all(host);
-.fi
-.SH AVAILABILITY
-Added in 7.21.3. Removal support added in 7.42.0.
-
-Support for providing the ADDRESS within [brackets] was added in 7.57.0.
-
-Support for providing multiple IP addresses per entry was added in 7.59.0.
-
-Support for adding non-permanent entries by using the "+" prefix was added in
-7.75.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECT_TO (3),
-.BR CURLOPT_DNS_CACHE_TIMEOUT (3),
-.BR CURLOPT_IPRESOLVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVE.md b/docs/libcurl/opts/CURLOPT_RESOLVE.md
new file mode 100644
index 000000000..ce446bdbf
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RESOLVE.md
@@ -0,0 +1,115 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RESOLVE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECT_TO (3)
+ - CURLOPT_DNS_CACHE_TIMEOUT (3)
+ - CURLOPT_IPRESOLVE (3)
+---
+
+# NAME
+
+CURLOPT_RESOLVE - provide custom hostname to IP address resolves
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVE,
+ struct curl_slist *hosts);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a linked list of strings with hostname resolve information
+to use for requests with this handle. The linked list should be a fully valid
+list of **struct curl_slist** structs properly filled in. Use
+curl_slist_append(3) to create the list and curl_slist_free_all(3) to clean up
+an entire list.
+
+Each resolve rule to add should be written using the format
+
+~~~c
+ [+]HOST:PORT:ADDRESS[,ADDRESS]
+~~~
+
+HOST is the name libcurl wants to resolve, PORT is the port number of the
+service where libcurl wants to connect to the HOST and ADDRESS is one or more
+numerical IP addresses. If you specify multiple IP addresses they need to be
+separated by comma. If libcurl is built to support IPv6, each of the ADDRESS
+entries can of course be either IPv4 or IPv6 style addressing.
+
+This option effectively populates the DNS cache with entries for the host+port
+pair so redirects and everything that operations against the HOST+PORT instead
+use your provided ADDRESS.
+
+The optional leading "+" specifies that the new entry should time-out. Entries
+added without the leading plus character never times out whereas entries added
+with "+HOST:..." times out just like ordinary DNS cache entries.
+
+If the DNS cache already has an entry for the given host+port pair, the new
+entry overrides the former one.
+
+An ADDRESS provided by this option is only used if not restricted by the
+setting of CURLOPT_IPRESOLVE(3) to a different IP version.
+
+To remove names from the DNS cache again, to stop providing these fake
+resolves, include a string in the linked list that uses the format
+
+~~~c
+ -HOST:PORT
+~~~
+
+The entry to remove must be prefixed with a dash, and the hostname and port
+number must exactly match what was added previously.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl;
+ struct curl_slist *host = NULL;
+ host = curl_slist_append(NULL, "example.com:443:127.0.0.1");
+
+ curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+
+ curl_slist_free_all(host);
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.3. Removal support added in 7.42.0.
+
+Support for providing the ADDRESS within [brackets] was added in 7.57.0.
+
+Support for providing multiple IP addresses per entry was added in 7.59.0.
+
+Support for adding non-permanent entries by using the "+" prefix was added in
+7.75.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3 b/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3
deleted file mode 100644
index 2344de908..000000000
--- a/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RESOLVER_START_DATA 3 "14 Feb 2018" libcurl libcurl
-.SH NAME
-CURLOPT_RESOLVER_START_DATA \- pointer passed to the resolver start callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVER_START_DATA,
- void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP is be untouched by libcurl and passed as the third
-argument in the resolver start callback set with
-\fICURLOPT_RESOLVER_START_FUNCTION(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static int resolver_start_cb(void *resolver_state, void *reserved,
- void *userdata)
-{
- (void)reserved;
- printf("Received resolver_state=%p userdata=%p\\n",
- resolver_state, userdata);
- return 0;
-}
-
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_RESOLVER_START_FUNCTION, resolver_start_cb);
- curl_easy_setopt(curl, CURLOPT_RESOLVER_START_DATA, curl);
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.59.0
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_PREREQFUNCTION (3),
-.BR CURLOPT_RESOLVER_START_FUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.md b/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.md
new file mode 100644
index 000000000..f34cf8bd6
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RESOLVER_START_DATA.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RESOLVER_START_DATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PREREQFUNCTION (3)
+ - CURLOPT_RESOLVER_START_FUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_RESOLVER_START_DATA - pointer passed to the resolver start callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESOLVER_START_DATA,
+ void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* is be untouched by libcurl and passed as the third
+argument in the resolver start callback set with
+CURLOPT_RESOLVER_START_FUNCTION(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+static int resolver_start_cb(void *resolver_state, void *reserved,
+ void *userdata)
+{
+ (void)reserved;
+ printf("Received resolver_state=%p userdata=%p\n",
+ resolver_state, userdata);
+ return 0;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_RESOLVER_START_FUNCTION, resolver_start_cb);
+ curl_easy_setopt(curl, CURLOPT_RESOLVER_START_DATA, curl);
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.59.0
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3
deleted file mode 100644
index 96e726ae0..000000000
--- a/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RESOLVER_START_FUNCTION 3 "14 Feb 2018" libcurl libcurl
-.SH NAME
-CURLOPT_RESOLVER_START_FUNCTION \- callback called before a new name resolve is started
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int resolver_start_cb(void *resolver_state, void *reserved, void *userdata);
-
-CURLcode curl_easy_setopt(CURL *handle,
- CURLOPT_RESOLVER_START_FUNCTION,
- resolver_start_cb);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl every time before a new resolve
-request is started.
-
-\fIresolver_state\fP points to a backend-specific resolver state. Currently
-only the ares resolver backend has a resolver state. It can be used to set up
-any desired option on the ares channel before it's used, for example setting up
-socket callback options.
-
-\fIreserved\fP is reserved.
-
-\fIuserdata\fP is the user pointer set with the
-\fICURLOPT_RESOLVER_START_DATA(3)\fP option.
-
-The callback must return 0 on success. Returning a non-zero value causes the
-resolve to fail.
-.SH DEFAULT
-NULL (No callback)
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static int resolver_start_cb(void *resolver_state, void *reserved,
- void *userdata)
-{
- (void)reserved;
- printf("Received resolver_state=%p userdata=%p\\n",
- resolver_state, userdata);
- return 0;
-}
-
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_RESOLVER_START_FUNCTION, resolver_start_cb);
- curl_easy_setopt(curl, CURLOPT_RESOLVER_START_DATA, curl);
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.59.0
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_PREREQFUNCTION (3),
-.BR CURLOPT_RESOLVER_START_DATA (3)
diff --git a/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.md b/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.md
new file mode 100644
index 000000000..a9b490726
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RESOLVER_START_FUNCTION.md
@@ -0,0 +1,88 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RESOLVER_START_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PREREQFUNCTION (3)
+ - CURLOPT_RESOLVER_START_DATA (3)
+---
+
+# NAME
+
+CURLOPT_RESOLVER_START_FUNCTION - callback called before a new name resolve is started
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int resolver_start_cb(void *resolver_state, void *reserved, void *userdata);
+
+CURLcode curl_easy_setopt(CURL *handle,
+ CURLOPT_RESOLVER_START_FUNCTION,
+ resolver_start_cb);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl every time before a new resolve
+request is started.
+
+*resolver_state* points to a backend-specific resolver state. Currently only
+the ares resolver backend has a resolver state. It can be used to set up any
+desired option on the ares channel before it is used, for example setting up
+socket callback options.
+
+*reserved* is reserved.
+
+*userdata* is the user pointer set with the
+CURLOPT_RESOLVER_START_DATA(3) option.
+
+The callback must return 0 on success. Returning a non-zero value causes the
+resolve to fail.
+
+# DEFAULT
+
+NULL (No callback)
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+static int start_cb(void *resolver_state, void *reserved,
+ void *userdata)
+{
+ (void)reserved;
+ printf("Received resolver_state=%p userdata=%p\n",
+ resolver_state, userdata);
+ return 0;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_RESOLVER_START_FUNCTION, start_cb);
+ curl_easy_setopt(curl, CURLOPT_RESOLVER_START_DATA, curl);
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.59.0
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_RESUME_FROM.3 b/docs/libcurl/opts/CURLOPT_RESUME_FROM.3
deleted file mode 100644
index 3254f7c12..000000000
--- a/docs/libcurl/opts/CURLOPT_RESUME_FROM.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RESUME_FROM 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RESUME_FROM \- offset to resume transfer from
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESUME_FROM, long from);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter. It contains the offset in number of bytes that you
-want the transfer to start from. Set this option to 0 to make the transfer
-start from the beginning (effectively disabling resume). For FTP, set this
-option to -1 to make the transfer start from the end of the target file
-(useful to continue an interrupted upload).
-
-When doing uploads with FTP, the resume position is where in the local/source
-file libcurl should try to resume the upload from and it then appends the
-source file to the remote target file.
-
-If you need to resume a transfer beyond the 2GB limit, use
-\fICURLOPT_RESUME_FROM_LARGE(3)\fP instead.
-.SH DEFAULT
-0, not used
-.SH PROTOCOLS
-HTTP, FTP, SFTP, FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com");
-
- /* resume upload at byte index 200 */
- curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 200L);
-
- /* ask for upload */
- curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
-
- /* set total data amount to expect */
- curl_easy_setopt(curl, CURLOPT_INFILESIZE, size_of_file);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_RESUME_FROM_LARGE (3),
-.BR CURLOPT_RANGE (3),
-.BR CURLOPT_INFILESIZE (3)
diff --git a/docs/libcurl/opts/CURLOPT_RESUME_FROM.md b/docs/libcurl/opts/CURLOPT_RESUME_FROM.md
new file mode 100644
index 000000000..c8de1ee6b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RESUME_FROM.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RESUME_FROM
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_INFILESIZE (3)
+ - CURLOPT_RANGE (3)
+ - CURLOPT_RESUME_FROM_LARGE (3)
+---
+
+# NAME
+
+CURLOPT_RESUME_FROM - offset to resume transfer from
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESUME_FROM, long from);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter. It contains the offset in number of bytes that you
+want the transfer to start from. Set this option to 0 to make the transfer
+start from the beginning (effectively disabling resume). For FTP, set this
+option to -1 to make the transfer start from the end of the target file
+(useful to continue an interrupted upload).
+
+When doing uploads with FTP, the resume position is where in the local/source
+file libcurl should try to resume the upload from and it then appends the
+source file to the remote target file.
+
+If you need to resume a transfer beyond the 2GB limit, use
+CURLOPT_RESUME_FROM_LARGE(3) instead.
+
+# DEFAULT
+
+0, not used
+
+# PROTOCOLS
+
+HTTP, FTP, SFTP, FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ long size_of_file;
+
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com");
+
+ /* resume upload at byte index 200 */
+ curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 200L);
+
+ /* ask for upload */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+
+ /* set total data amount to expect */
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE, size_of_file);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3 b/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3
deleted file mode 100644
index d4fae3d44..000000000
--- a/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RESUME_FROM_LARGE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RESUME_FROM_LARGE \- offset to resume transfer from
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESUME_FROM_LARGE,
- curl_off_t from);
-.SH DESCRIPTION
-Pass a curl_off_t as parameter. It contains the offset in number of bytes that
-you want the transfer to start from. Set this option to 0 to make the transfer
-start from the beginning (effectively disabling resume). For FTP, set this
-option to -1 to make the transfer start from the end of the target file
-(useful to continue an interrupted upload).
-
-When doing uploads with FTP, the resume position is where in the local/source
-file libcurl should try to resume the upload from and it appends the source
-file to the remote target file.
-.SH DEFAULT
-0, not used
-.SH PROTOCOLS
-HTTP, FTP, SFTP, FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_off_t resume_position = GET_IT_SOMEHOW;
- curl_off_t file_size = GET_IT_SOMEHOW_AS_WELL;
-
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com");
-
- /* resuming upload at this position, possibly beyond 2GB */
- curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, resume_position);
-
- /* ask for upload */
- curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
-
- /* set total data amount to expect */
- curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.11.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_INFILESIZE_LARGE (3),
-.BR CURLOPT_RANGE (3),
-.BR CURLOPT_RESUME_FROM (3)
diff --git a/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.md b/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.md
new file mode 100644
index 000000000..950a4f496
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RESUME_FROM_LARGE.md
@@ -0,0 +1,79 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RESUME_FROM_LARGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_INFILESIZE_LARGE (3)
+ - CURLOPT_RANGE (3)
+ - CURLOPT_RESUME_FROM (3)
+---
+
+# NAME
+
+CURLOPT_RESUME_FROM_LARGE - offset to resume transfer from
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RESUME_FROM_LARGE,
+ curl_off_t from);
+~~~
+
+# DESCRIPTION
+
+Pass a curl_off_t as parameter. It contains the offset in number of bytes that
+you want the transfer to start from. Set this option to 0 to make the transfer
+start from the beginning (effectively disabling resume). For FTP, set this
+option to -1 to make the transfer start from the end of the target file
+(useful to continue an interrupted upload).
+
+When doing uploads with FTP, the resume position is where in the local/source
+file libcurl should try to resume the upload from and it appends the source
+file to the remote target file.
+
+# DEFAULT
+
+0, not used
+
+# PROTOCOLS
+
+HTTP, FTP, SFTP, FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_off_t resume_position; /* get it somehow */
+ curl_off_t file_size; /* get it somehow as well */
+
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com");
+
+ /* resuming upload at this position, possibly beyond 2GB */
+ curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, resume_position);
+
+ /* ask for upload */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+
+ /* set total data amount to expect */
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.11.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3 b/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3
deleted file mode 100644
index 625641170..000000000
--- a/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RTSP_CLIENT_CSEQ 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RTSP_CLIENT_CSEQ \- RTSP client CSEQ number
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_CLIENT_CSEQ, long cseq);
-.fi
-.SH DESCRIPTION
-Pass a long to set the CSEQ number to issue for the next RTSP request. Useful
-if the application is resuming a previously broken connection. The CSEQ
-increments from this new number henceforth.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
- curl_easy_setopt(curl, CURLOPT_RTSP_CLIENT_CSEQ, 1234L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_RTSP_CLIENT_CSEQ (3),
-.BR CURLINFO_RTSP_SERVER_CSEQ (3),
-.BR CURLOPT_RTSP_REQUEST (3),
-.BR CURLOPT_RTSP_SERVER_CSEQ (3)
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md b/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md
new file mode 100644
index 000000000..6c83663dc
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RTSP_CLIENT_CSEQ
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RTSP_CLIENT_CSEQ (3)
+ - CURLINFO_RTSP_SERVER_CSEQ (3)
+ - CURLOPT_RTSP_REQUEST (3)
+ - CURLOPT_RTSP_SERVER_CSEQ (3)
+---
+
+# NAME
+
+CURLOPT_RTSP_CLIENT_CSEQ - RTSP client CSEQ number
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_CLIENT_CSEQ, long cseq);
+~~~
+
+# DESCRIPTION
+
+Pass a long to set the CSEQ number to issue for the next RTSP request. Useful
+if the application is resuming a previously broken connection. The CSEQ
+increments from this new number henceforth.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_RTSP_CLIENT_CSEQ, 1234L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3 b/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3
deleted file mode 100644
index 3a8ddb200..000000000
--- a/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.3
+++ /dev/null
@@ -1,118 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RTSP_REQUEST 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RTSP_REQUEST \- RTSP request
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_REQUEST, long request);
-.fi
-.SH DESCRIPTION
-Tell libcurl what kind of RTSP request to make. Pass one of the following RTSP
-enum values as a long in the \fIrequest\fP argument. Unless noted otherwise,
-commands require the Session ID to be initialized.
-.IP CURL_RTSPREQ_OPTIONS
-Used to retrieve the available methods of the server. The application is
-responsible for parsing and obeying the response. The session ID is not needed
-for this method.
-.IP CURL_RTSPREQ_DESCRIBE
-Used to get the low level description of a stream. The application should note
-what formats it understands in the \fI'Accept:'\fP header. Unless set
-manually, libcurl automatically adds in \fI'Accept: application/sdp'\fP.
-Time-condition headers are added to Describe requests if the
-\fICURLOPT_TIMECONDITION(3)\fP option is used. \fB(The session ID is not
-needed for this method)\fP
-.IP CURL_RTSPREQ_ANNOUNCE
-When sent by a client, this method changes the description of the session. For
-example, if a client is using the server to record a meeting, the client can
-use Announce to inform the server of all the meta-information about the
-session. ANNOUNCE acts like an HTTP PUT or POST just like
-\fICURL_RTSPREQ_SET_PARAMETER\fP
-.IP CURL_RTSPREQ_SETUP
-Setup is used to initialize the transport layer for the session. The
-application must set the desired Transport options for a session by using the
-\fICURLOPT_RTSP_TRANSPORT(3)\fP option prior to calling setup. If no session
-ID is currently set with \fICURLOPT_RTSP_SESSION_ID(3)\fP, libcurl extracts
-and uses the session ID in the response to this request. The session ID is not
-needed for this method.
-.IP CURL_RTSPREQ_PLAY
-Send a Play command to the server. Use the \fICURLOPT_RANGE(3)\fP option to
-modify the playback time (e.g. \fInpt=10-15\fP).
-.IP CURL_RTSPREQ_PAUSE
-Send a Pause command to the server. Use the \fICURLOPT_RANGE(3)\fP option with
-a single value to indicate when the stream should be
-halted. (e.g. \fInpt=25\fP)
-.IP CURL_RTSPREQ_TEARDOWN
-This command terminates an RTSP session. Simply closing a connection does not
-terminate the RTSP session since it is valid to control an RTSP session over
-different connections.
-.IP CURL_RTSPREQ_GET_PARAMETER
-Retrieve a parameter from the server. By default, libcurl adds a
-\fIContent-Type: text/parameters\fP header on all non-empty requests unless a
-custom one is set. GET_PARAMETER acts just like an HTTP PUT or POST (see
-\fICURL_RTSPREQ_SET_PARAMETER\fP). Applications wishing to send a heartbeat
-message (e.g. in the presence of a server-specified timeout) should send use
-an empty GET_PARAMETER request.
-.IP CURL_RTSPREQ_SET_PARAMETER
-Set a parameter on the server. By default, libcurl uses a
-\fIContent-Type: text/parameters\fP header unless a custom one is set.
-The interaction with SET_PARAMETER is much like an HTTP PUT or POST. An
-application may either use \fICURLOPT_UPLOAD(3)\fP with
-\fICURLOPT_READDATA(3)\fP like a HTTP PUT, or it may use
-\fICURLOPT_POSTFIELDS(3)\fP like an HTTP POST. No chunked transfers are
-allowed, so the application must set the \fICURLOPT_INFILESIZE(3)\fP in the
-former and \fICURLOPT_POSTFIELDSIZE(3)\fP in the latter. Also, there is no use
-of multi-part POSTs within RTSP.
-.IP CURL_RTSPREQ_RECORD
-Used to tell the server to record a session. Use the \fICURLOPT_RANGE(3)\fP
-option to modify the record time.
-.IP CURL_RTSPREQ_RECEIVE
-This is a special request because it does not send any data to the server. The
-application may call this function in order to receive interleaved RTP
-data. It returns after processing one read buffer of data in order to give the
-application a chance to run.
-.SH DEFAULT
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
- /* ask for options! */
- curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_OPTIONS);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_RTSP_SESSION_ID (3),
-.BR CURLOPT_RTSP_STREAM_URI (3)
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md b/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md
new file mode 100644
index 000000000..d56b34dc9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md
@@ -0,0 +1,139 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RTSP_REQUEST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_RTSP_SESSION_ID (3)
+ - CURLOPT_RTSP_STREAM_URI (3)
+---
+
+# NAME
+
+CURLOPT_RTSP_REQUEST - RTSP request
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_REQUEST, long request);
+~~~
+
+# DESCRIPTION
+
+Tell libcurl what kind of RTSP request to make. Pass one of the following RTSP
+enum values as a long in the *request* argument. Unless noted otherwise,
+commands require the Session ID to be initialized.
+
+## CURL_RTSPREQ_OPTIONS
+
+Used to retrieve the available methods of the server. The application is
+responsible for parsing and obeying the response. The session ID is not needed
+for this method.
+
+## CURL_RTSPREQ_DESCRIBE
+
+Used to get the low level description of a stream. The application should note
+what formats it understands in the *'Accept:'* header. Unless set manually,
+libcurl automatically adds in *'Accept: application/sdp'*. Time-condition
+headers are added to Describe requests if the CURLOPT_TIMECONDITION(3)
+option is used. (The session ID is not needed for this method)
+
+## CURL_RTSPREQ_ANNOUNCE
+
+When sent by a client, this method changes the description of the session. For
+example, if a client is using the server to record a meeting, the client can
+use Announce to inform the server of all the meta-information about the
+session. ANNOUNCE acts like an HTTP PUT or POST just like
+*CURL_RTSPREQ_SET_PARAMETER*
+
+## CURL_RTSPREQ_SETUP
+
+Setup is used to initialize the transport layer for the session. The
+application must set the desired Transport options for a session by using the
+CURLOPT_RTSP_TRANSPORT(3) option prior to calling setup. If no session
+ID is currently set with CURLOPT_RTSP_SESSION_ID(3), libcurl extracts
+and uses the session ID in the response to this request. The session ID is not
+needed for this method.
+
+## CURL_RTSPREQ_PLAY
+
+Send a Play command to the server. Use the CURLOPT_RANGE(3) option to
+modify the playback time (e.g. *npt=10-15*).
+
+## CURL_RTSPREQ_PAUSE
+
+Send a Pause command to the server. Use the CURLOPT_RANGE(3) option with
+a single value to indicate when the stream should be
+halted. (e.g. *npt=25*)
+
+## CURL_RTSPREQ_TEARDOWN
+
+This command terminates an RTSP session. Simply closing a connection does not
+terminate the RTSP session since it is valid to control an RTSP session over
+different connections.
+
+## CURL_RTSPREQ_GET_PARAMETER
+
+Retrieve a parameter from the server. By default, libcurl adds a
+*Content-Type: text/parameters* header on all non-empty requests unless a
+custom one is set. GET_PARAMETER acts just like an HTTP PUT or POST (see
+*CURL_RTSPREQ_SET_PARAMETER*). Applications wishing to send a heartbeat
+message (e.g. in the presence of a server-specified timeout) should send use
+an empty GET_PARAMETER request.
+
+## CURL_RTSPREQ_SET_PARAMETER
+
+Set a parameter on the server. By default, libcurl uses a *Content-Type:
+text/parameters* header unless a custom one is set. The interaction with
+SET_PARAMETER is much like an HTTP PUT or POST. An application may either use
+CURLOPT_UPLOAD(3) with CURLOPT_READDATA(3) like an HTTP PUT, or it may use
+CURLOPT_POSTFIELDS(3) like an HTTP POST. No chunked transfers are allowed, so
+the application must set the CURLOPT_INFILESIZE(3) in the former and
+CURLOPT_POSTFIELDSIZE(3) in the latter. Also, there is no use of multi-part
+POSTs within RTSP.
+
+## CURL_RTSPREQ_RECORD
+
+Used to tell the server to record a session. Use the CURLOPT_RANGE(3)
+option to modify the record time.
+
+## CURL_RTSPREQ_RECEIVE
+
+This is a special request because it does not send any data to the server. The
+application may call this function in order to receive interleaved RTP
+data. It returns after processing one read buffer of data in order to give the
+application a chance to run.
+
+# DEFAULT
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
+ /* ask for options! */
+ curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_OPTIONS);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3 b/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3
deleted file mode 100644
index cadf21cc2..000000000
--- a/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RTSP_SERVER_CSEQ 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RTSP_SERVER_CSEQ \- RTSP server CSEQ number
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SERVER_CSEQ, long cseq);
-.fi
-.SH DESCRIPTION
-Pass a long to set the CSEQ number to expect for the next RTSP Server->Client
-request. \fBNOTE\fP: this feature (listening for Server requests) is
-unimplemented.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
- curl_easy_setopt(curl, CURLOPT_RTSP_SERVER_CSEQ, 1234L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLINFO_RTSP_SERVER_CSEQ (3),
-.BR CURLOPT_RTSP_CLIENT_CSEQ (3),
-.BR CURLOPT_RTSP_STREAM_URI (3)
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md b/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md
new file mode 100644
index 000000000..521084388
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RTSP_SERVER_CSEQ
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_RTSP_SERVER_CSEQ (3)
+ - CURLOPT_RTSP_CLIENT_CSEQ (3)
+ - CURLOPT_RTSP_STREAM_URI (3)
+---
+
+# NAME
+
+CURLOPT_RTSP_SERVER_CSEQ - RTSP server CSEQ number
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SERVER_CSEQ, long cseq);
+~~~
+
+# DESCRIPTION
+
+Pass a long to set the CSEQ number to expect for the next RTSP Server->Client
+request. **NOTE**: this feature (listening for Server requests) is
+unimplemented.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_RTSP_SERVER_CSEQ, 1234L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3 b/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3
deleted file mode 100644
index 3eaae0324..000000000
--- a/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RTSP_SESSION_ID 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RTSP_SESSION_ID \- RTSP session ID
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SESSION_ID, char *id);
-.fi
-.SH DESCRIPTION
-Pass a char * as a parameter to set the value of the current RTSP Session ID
-for the handle. Useful for resuming an in-progress session. Once this value is
-set to any non-NULL value, libcurl returns \fICURLE_RTSP_SESSION_ERROR\fP if
-ID received from the server does not match. If unset (or set to NULL), libcurl
-automatically sets the ID the first time the server sets it in a response.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- char *prev_id; /* saved from before somehow */
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
- curl_easy_setopt(curl, CURLOPT_RTSP_SESSION_ID, prev_id);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.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_RTSP_REQUEST (3),
-.BR CURLOPT_RTSP_STREAM_URI (3)
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md b/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md
new file mode 100644
index 000000000..8af7f7c59
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RTSP_SESSION_ID
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_RTSP_REQUEST (3)
+ - CURLOPT_RTSP_STREAM_URI (3)
+---
+
+# NAME
+
+CURLOPT_RTSP_SESSION_ID - RTSP session ID
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_SESSION_ID, char *id);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as a parameter to set the value of the current RTSP
+Session ID for the handle. Useful for resuming an in-progress session. Once
+this value is set to any non-NULL value, libcurl returns
+*CURLE_RTSP_SESSION_ERROR* if ID received from the server does not match. If
+unset (or set to NULL), libcurl automatically sets the ID the first time the
+server sets it in a response.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ char *prev_id; /* saved from before somehow */
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_RTSP_SESSION_ID, prev_id);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3 b/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3
deleted file mode 100644
index f6eea3047..000000000
--- a/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RTSP_STREAM_URI 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RTSP_STREAM_URI \- RTSP stream URI
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_STREAM_URI, char *URI);
-.fi
-.SH DESCRIPTION
-Set the stream \fIURI\fP to operate on by passing a char * . For example, a
-single session may be controlling \fIrtsp://foo/twister/audio\fP and
-\fIrtsp://foo/twister/video\fP and the application can switch to the
-appropriate stream using this option. If unset, libcurl defaults to operating
-on generic server options by passing '*' in the place of the RTSP Stream
-URI. This option is distinct from \fICURLOPT_URL(3)\fP. When working with
-RTSP, the \fICURLOPT_RTSP_STREAM_URI(3)\fP indicates what URL to send to the
-server in the request header while the \fICURLOPT_URL(3)\fP indicates where to
-make the connection to. (e.g. the \fICURLOPT_URL(3)\fP for the above examples
-might be set to \fIrtsp://foo/twister\fP
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-\&'*'
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- char *prev_id; /* saved from before somehow */
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
- curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI,
- "rtsp://foo.example.com/twister/video");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.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_RTSP_REQUEST (3),
-.BR CURLOPT_RTSP_TRANSPORT (3)
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md b/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md
new file mode 100644
index 000000000..e138a3cd9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RTSP_STREAM_URI
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_RTSP_REQUEST (3)
+ - CURLOPT_RTSP_TRANSPORT (3)
+---
+
+# NAME
+
+CURLOPT_RTSP_STREAM_URI - RTSP stream URI
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_STREAM_URI, char *URI);
+~~~
+
+# DESCRIPTION
+
+Set the stream *URI* to operate on by passing a char * . For example, a single
+session may be controlling *rtsp://foo/twister/audio* and
+*rtsp://foo/twister/video* and the application can switch to the appropriate
+stream using this option. If unset, libcurl defaults to operating on generic
+server options by passing '*' in the place of the RTSP Stream URI. This option
+is distinct from CURLOPT_URL(3). When working with RTSP, the
+CURLOPT_RTSP_STREAM_URI(3) indicates what URL to send to the server in the
+request header while the CURLOPT_URL(3) indicates where to make the connection
+to. (e.g. the CURLOPT_URL(3) for the above examples might be set to
+*rtsp://foo/twister*
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+"*"
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_RTSP_STREAM_URI,
+ "rtsp://foo.example.com/twister/video");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3 b/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3
deleted file mode 100644
index f276cc2b6..000000000
--- a/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_RTSP_TRANSPORT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_RTSP_TRANSPORT \- RTSP Transport: header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_TRANSPORT,
- char *transport);
-.SH DESCRIPTION
-Pass a char * to tell libcurl what to pass for the Transport: header for this
-RTSP session. This is mainly a convenience method to avoid needing to set a
-custom Transport: header for every SETUP request. The application must set a
-Transport: header before issuing a SETUP request.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-RTSP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
- curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_SETUP);
- curl_easy_setopt(curl, CURLOPT_RTSP_TRANSPORT,
- "RTP/AVP;unicast;client_port=4588-4589");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.20.0
-.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_RTSP_REQUEST (3),
-.BR CURLOPT_RTSP_SESSION_ID (3)
diff --git a/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md b/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md
new file mode 100644
index 000000000..b8083967d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_RTSP_TRANSPORT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_RTSP_REQUEST (3)
+ - CURLOPT_RTSP_SESSION_ID (3)
+---
+
+# NAME
+
+CURLOPT_RTSP_TRANSPORT - RTSP Transport: header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RTSP_TRANSPORT,
+ char *transport);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer to tell libcurl what to pass for the Transport: header for
+this RTSP session. This is mainly a convenience method to avoid needing to set
+a custom Transport: header for every SETUP request. The application must set a
+Transport: header before issuing a SETUP request.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+RTSP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_SETUP);
+ curl_easy_setopt(curl, CURLOPT_RTSP_TRANSPORT,
+ "RTP/AVP;unicast;client_port=4588-4589");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.20.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3 b/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3
deleted file mode 100644
index d0b73f923..000000000
--- a/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SASL_AUTHZID 3 "11 Sep 2019" libcurl libcurl
-.SH NAME
-CURLOPT_SASL_AUTHZID \- authorization identity (identity to act as)
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_AUTHZID, char *authzid);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter, which should be pointing to the null-terminated
-authorization identity (\fIauthzid\fP) for the transfer. Only applicable to
-the PLAIN SASL authentication mechanism where it is optional.
-
-When not specified only the authentication identity (\fIauthcid\fP) as
-specified by the username is sent to the server, along with the password. The
-server derives a \fIauthzid\fP from the \fIauthcid\fP when not provided, which
-it then uses internally.
-
-When the \fIauthzid\fP is specified, the use of which is server dependent, it
-can be used to access another user's inbox, that the user has been granted
-access to, or a shared mailbox for example.
-.SH DEFAULT
-blank
-.SH PROTOCOLS
-IMAP, LDAP, POP3 and SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "imap://example.com/");
- curl_easy_setopt(curl, CURLOPT_USERNAME, "Kurt");
- curl_easy_setopt(curl, CURLOPT_PASSWORD, "xipj3plmq");
- curl_easy_setopt(curl, CURLOPT_SASL_AUTHZID, "Ursel");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.66.0. Support for OpenLDAP added in 7.82.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_PASSWORD (3),
-.BR CURLOPT_USERNAME (3),
-.BR CURLOPT_USERPWD (3)
diff --git a/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md b/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md
new file mode 100644
index 000000000..5ff67c6ab
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SASL_AUTHZID
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_USERNAME (3)
+ - CURLOPT_USERPWD (3)
+---
+
+# NAME
+
+CURLOPT_SASL_AUTHZID - authorization identity (identity to act as)
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_AUTHZID, char *authzid);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be pointing to the
+null-terminated authorization identity (*authzid*) for the transfer. Only
+applicable to the PLAIN SASL authentication mechanism where it is optional.
+
+When not specified only the authentication identity (*authcid*) as
+specified by the username is sent to the server, along with the password. The
+server derives a *authzid* from the *authcid* when not provided, which
+it then uses internally.
+
+When the *authzid* is specified, the use of which is server dependent, it
+can be used to access another user's inbox, that the user has been granted
+access to, or a shared mailbox for example.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+IMAP, LDAP, POP3 and SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "imap://example.com/");
+ curl_easy_setopt(curl, CURLOPT_USERNAME, "Kurt");
+ curl_easy_setopt(curl, CURLOPT_PASSWORD, "xipj3plmq");
+ curl_easy_setopt(curl, CURLOPT_SASL_AUTHZID, "Ursel");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.66.0. Support for OpenLDAP added in 7.82.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SASL_IR.3 b/docs/libcurl/opts/CURLOPT_SASL_IR.3
deleted file mode 100644
index 7c3a7a4ba..000000000
--- a/docs/libcurl/opts/CURLOPT_SASL_IR.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SASL_IR 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SASL_IR \- send initial response in first packet
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_IR, long enable);
-.fi
-.SH DESCRIPTION
-Pass a long. If the value is 1, curl sends the initial response to the server
-in the first authentication packet in order to reduce the number of ping pong
-requests. Only applicable to the following supporting SASL authentication
-mechanisms:
-
-* Login
-* Plain
-* GSSAPI
-* NTLM
-* OAuth 2.0
-
-Note: Whilst IMAP supports this option there is no need to explicitly set it,
-as libcurl can determine the feature itself when the server supports the
-SASL-IR CAPABILITY.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-IMAP, POP3 and SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
- curl_easy_setopt(curl, CURLOPT_SASL_IR, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.31.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_MAIL_AUTH (3),
-.BR CURLOPT_MAIL_FROM (3),
-.BR CURLOPT_SASL_AUTHZID (3)
diff --git a/docs/libcurl/opts/CURLOPT_SASL_IR.md b/docs/libcurl/opts/CURLOPT_SASL_IR.md
new file mode 100644
index 000000000..204734d01
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SASL_IR.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SASL_IR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAIL_AUTH (3)
+ - CURLOPT_MAIL_FROM (3)
+ - CURLOPT_SASL_AUTHZID (3)
+---
+
+# NAME
+
+CURLOPT_SASL_IR - send initial response in first packet
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_IR, long enable);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If the value is 1, curl sends the initial response to the server
+in the first authentication packet in order to reduce the number of ping pong
+requests. Only applicable to the following supporting SASL authentication
+mechanisms:
+
+* Login
+* Plain
+* GSSAPI
+* NTLM
+* OAuth 2.0
+
+Note: Whilst IMAP supports this option there is no need to explicitly set it,
+as libcurl can determine the feature itself when the server supports the
+SASL-IR CAPABILITY.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+IMAP, POP3 and SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SASL_IR, 1L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.31.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SEEKDATA.3 b/docs/libcurl/opts/CURLOPT_SEEKDATA.3
deleted file mode 100644
index 8810115a3..000000000
--- a/docs/libcurl/opts/CURLOPT_SEEKDATA.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SEEKDATA 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SEEKDATA \- pointer passed to the seek callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SEEKDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Data \fIpointer\fP to pass to the seek callback function. If you use the
-\fICURLOPT_SEEKFUNCTION(3)\fP option, this is the pointer you get as input.
-.SH DEFAULT
-If you do not set this, NULL is passed to the callback.
-.SH PROTOCOLS
-HTTP, FTP, SFTP
-.SH EXAMPLE
-.nf
-static int seek_cb(void *clientp, curl_off_t offset, int origin)
-{
- struct data *d = (struct data *)clientp;
- lseek(d->our_fd, offset, origin);
- return CURL_SEEKFUNC_OK;
-}
-
-{
- struct data seek_data;
- curl_easy_setopt(CURL *handle, CURLOPT_SEEKFUNCTION, seek_cb);
- curl_easy_setopt(CURL *handle, CURLOPT_SEEKDATA, &seek_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.18.0
-.SH RETURN VALUE
-.SH "SEE ALSO"
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_IOCTLFUNCTION (3),
-.BR CURLOPT_SEEKFUNCTION (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_SEEKDATA.md b/docs/libcurl/opts/CURLOPT_SEEKDATA.md
new file mode 100644
index 000000000..9392c2366
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SEEKDATA.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SEEKDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_IOCTLFUNCTION (3)
+ - CURLOPT_SEEKFUNCTION (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_SEEKDATA - pointer passed to the seek callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SEEKDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Data *pointer* to pass to the seek callback function. If you use the
+CURLOPT_SEEKFUNCTION(3) option, this is the pointer you get as input.
+
+# DEFAULT
+
+If you do not set this, NULL is passed to the callback.
+
+# PROTOCOLS
+
+HTTP, FTP, SFTP
+
+# EXAMPLE
+
+~~~c
+#include <unistd.h> /* for lseek() */
+
+struct data {
+ int our_fd;
+};
+
+static int seek_cb(void *clientp, curl_off_t offset, int origin)
+{
+ struct data *d = (struct data *)clientp;
+ lseek(d->our_fd, offset, origin);
+ return CURL_SEEKFUNC_OK;
+}
+
+int main(void)
+{
+ struct data seek_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_cb);
+ curl_easy_setopt(curl, CURLOPT_SEEKDATA, &seek_data);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.18.0
+
+# RETURN VALUE
+
diff --git a/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3
deleted file mode 100644
index 1e000bd8a..000000000
--- a/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SEEKFUNCTION 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SEEKFUNCTION \- user callback for seeking in input stream
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-/* These are the return codes for the seek callbacks */
-#define CURL_SEEKFUNC_OK 0
-#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
-#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking cannot be done, so
- libcurl might try other means instead */
-
-int seek_callback(void *clientp, curl_off_t offset, int origin);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SEEKFUNCTION, seek_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This function gets called by libcurl to seek to a certain position in the
-input stream and can be used to fast forward a file in a resumed upload
-(instead of reading all uploaded bytes with the normal read
-function/callback). It is also called to rewind a stream when data has already
-been sent to the server and needs to be sent again. This may happen when doing
-an HTTP PUT or POST with a multi-pass authentication method, or when an
-existing HTTP connection is reused too late and the server closes the
-connection. The function shall work like fseek(3) or lseek(3) and it gets
-SEEK_SET, SEEK_CUR or SEEK_END as argument for \fIorigin\fP, although libcurl
-currently only passes SEEK_SET.
-
-\fIclientp\fP is the pointer you set with \fICURLOPT_SEEKDATA(3)\fP.
-
-The callback function must return \fICURL_SEEKFUNC_OK\fP on success,
-\fICURL_SEEKFUNC_FAIL\fP to cause the upload operation to fail or
-\fICURL_SEEKFUNC_CANTSEEK\fP to indicate that while the seek failed, libcurl
-is free to work around the problem if possible. The latter can sometimes be
-done by instead reading from the input or similar.
-
-If you forward the input arguments directly to fseek(3) or lseek(3), note that
-the data type for \fIoffset\fP is not the same as defined for curl_off_t on
-many systems!
-.SH DEFAULT
-By default, this is NULL and unused.
-.SH PROTOCOLS
-HTTP, FTP, SFTP
-.SH EXAMPLE
-.nf
-static int seek_cb(void *clientp, curl_off_t offset, int origin)
-{
- struct data *d = (struct data *)clientp;
- lseek(our_fd, offset, origin);
- return CURL_SEEKFUNC_OK;
-}
-
-{
- struct data seek_data;
- curl_easy_setopt(CURL *handle, CURLOPT_SEEKFUNCTION, seek_cb);
- curl_easy_setopt(CURL *handle, CURLOPT_SEEKDATA, &seek_data);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.18.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_IOCTLFUNCTION (3),
-.BR CURLOPT_SEEKDATA (3),
-.BR CURLOPT_STDERR (3)
diff --git a/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.md b/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.md
new file mode 100644
index 000000000..102bdcfc7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SEEKFUNCTION.md
@@ -0,0 +1,102 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SEEKFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_IOCTLFUNCTION (3)
+ - CURLOPT_SEEKDATA (3)
+ - CURLOPT_STDERR (3)
+---
+
+# NAME
+
+CURLOPT_SEEKFUNCTION - user callback for seeking in input stream
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+/* These are the return codes for the seek callbacks */
+#define CURL_SEEKFUNC_OK 0
+#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
+#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking cannot be done, so
+ libcurl might try other means instead */
+
+int seek_callback(void *clientp, curl_off_t offset, int origin);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SEEKFUNCTION, seek_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This function gets called by libcurl to seek to a certain position in the
+input stream and can be used to fast forward a file in a resumed upload
+(instead of reading all uploaded bytes with the normal read
+function/callback). It is also called to rewind a stream when data has already
+been sent to the server and needs to be sent again. This may happen when doing
+an HTTP PUT or POST with a multi-pass authentication method, or when an
+existing HTTP connection is reused too late and the server closes the
+connection. The function shall work like fseek(3) or lseek(3) and it gets
+SEEK_SET, SEEK_CUR or SEEK_END as argument for *origin*, although libcurl
+currently only passes SEEK_SET.
+
+*clientp* is the pointer you set with CURLOPT_SEEKDATA(3).
+
+The callback function must return *CURL_SEEKFUNC_OK* on success,
+*CURL_SEEKFUNC_FAIL* to cause the upload operation to fail or
+*CURL_SEEKFUNC_CANTSEEK* to indicate that while the seek failed, libcurl
+is free to work around the problem if possible. The latter can sometimes be
+done by instead reading from the input or similar.
+
+If you forward the input arguments directly to fseek(3) or lseek(3), note that
+the data type for *offset* is not the same as defined for curl_off_t on
+many systems!
+
+# DEFAULT
+
+By default, this is NULL and unused.
+
+# PROTOCOLS
+
+HTTP, FTP, SFTP
+
+# EXAMPLE
+
+~~~c
+#include <unistd.h> /* for lseek */
+
+struct data {
+ int our_fd;
+};
+static int seek_cb(void *clientp, curl_off_t offset, int origin)
+{
+ struct data *d = (struct data *)clientp;
+ lseek(d->our_fd, offset, origin);
+ return CURL_SEEKFUNC_OK;
+}
+
+int main(void)
+{
+ struct data seek_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_cb);
+ curl_easy_setopt(curl, CURLOPT_SEEKDATA, &seek_data);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.18.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.3
deleted file mode 100644
index 0628b374c..000000000
--- a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SERVER_RESPONSE_TIMEOUT 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SERVER_RESPONSE_TIMEOUT \- time allowed to wait for server response
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVER_RESPONSE_TIMEOUT,
- long timeout);
-.fi
-.SH DESCRIPTION
-Pass a long. Causes libcurl to set a \fItimeout\fP period (in seconds) on the
-amount of time that the server is allowed to take in order to send a response
-message for a command before the session is considered dead. While libcurl is
-waiting for a response, this value overrides \fICURLOPT_TIMEOUT(3)\fP. It is
-recommended that if used in conjunction with \fICURLOPT_TIMEOUT(3)\fP, you set
-\fICURLOPT_SERVER_RESPONSE_TIMEOUT(3)\fP to a value smaller than
-\fICURLOPT_TIMEOUT(3)\fP.
-
-This option was formerly known as CURLOPT_FTP_RESPONSE_TIMEOUT.
-.SH DEFAULT
-None
-.SH PROTOCOLS
-FTP, IMAP, POP3, SMTP, and SSH
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/slow.txt");
- /* wait no more than 23 seconds */
- curl_easy_setopt(curl, CURLOPT_SERVER_RESPONSE_TIMEOUT, 23L);
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.10.8. Used under this name since 7.20.0
-
-Support for SSH is predicated on a new enough (1.11.0) version of libssh2
-being available when compiling libcurl.
-.SH RETURN VALUE
-Returns CURLE_OK if supported, and CURLE_UNKNOWN_OPTION if not. Returns
-CURLE_BAD_FUNCTION_ARGUMENT if set to a negative value or a value that when
-converted to milliseconds is too large.
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECTTIMEOUT (3),
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md
new file mode 100644
index 000000000..5385d521e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SERVER_RESPONSE_TIMEOUT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT (3)
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_SERVER_RESPONSE_TIMEOUT - time allowed to wait for server response
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVER_RESPONSE_TIMEOUT,
+ long timeout);
+~~~
+
+# DESCRIPTION
+
+Pass a long. Causes libcurl to set a *timeout* period (in seconds) on the
+amount of time that the server is allowed to take in order to send a response
+message for a command before the session is considered dead. While libcurl is
+waiting for a response, this value overrides CURLOPT_TIMEOUT(3). It is
+recommended that if used in conjunction with CURLOPT_TIMEOUT(3), you set
+CURLOPT_SERVER_RESPONSE_TIMEOUT(3) to a value smaller than
+CURLOPT_TIMEOUT(3).
+
+This option was formerly known as CURLOPT_FTP_RESPONSE_TIMEOUT.
+
+# DEFAULT
+
+None
+
+# PROTOCOLS
+
+FTP, IMAP, POP3, SMTP, and SSH
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/slow.txt");
+ /* wait no more than 23 seconds */
+ curl_easy_setopt(curl, CURLOPT_SERVER_RESPONSE_TIMEOUT, 23L);
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10.8. Used under this name since 7.20.0
+
+Support for SSH is predicated on a new enough (1.11.0) version of libssh2
+being available when compiling libcurl.
+
+# RETURN VALUE
+
+Returns CURLE_OK if supported, and CURLE_UNKNOWN_OPTION if not. Returns
+CURLE_BAD_FUNCTION_ARGUMENT if set to a negative value or a value that when
+converted to milliseconds is too large.
diff --git a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md
new file mode 100644
index 000000000..a7d9c9137
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md
@@ -0,0 +1,74 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SERVER_RESPONSE_TIMEOUT_MS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT (3)
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_SERVER_RESPONSE_TIMEOUT_MS - time allowed to wait for server response
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVER_RESPONSE_TIMEOUT_MS,
+ long timeout);
+~~~
+
+# DESCRIPTION
+
+Pass a long. Causes libcurl to set a *timeout* period (in milliseconds) on the
+amount of time that the server is allowed to take in order to send a response
+message for a command before the session is considered dead. While libcurl is
+waiting for a response, this value overrides CURLOPT_TIMEOUT(3). It is
+recommended that if used in conjunction with CURLOPT_TIMEOUT(3), you set
+CURLOPT_SERVER_RESPONSE_TIMEOUT_MS(3) to a value smaller than
+CURLOPT_TIMEOUT(3).
+
+The maximum accepted value is 2147483648.
+
+This is the millisecond version of CURLOPT_SERVER_RESPONSE_TIMEOUT(3).
+
+# DEFAULT
+
+None
+
+# PROTOCOLS
+
+FTP, IMAP, POP3, SMTP, and SSH
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/slow.txt");
+ /* wait no more than 237 milliseconds */
+ curl_easy_setopt(curl, CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, 237L);
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 8.6.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if supported, and CURLE_UNKNOWN_OPTION if not. Returns
+CURLE_BAD_FUNCTION_ARGUMENT if set to a negative value or a value that when
+converted to milliseconds is too large.
diff --git a/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3 b/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3
deleted file mode 100644
index 2c3f70f2d..000000000
--- a/docs/libcurl/opts/CURLOPT_SERVICE_NAME.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SERVICE_NAME 3 "17 Jun 2015" libcurl libcurl
-.SH NAME
-CURLOPT_SERVICE_NAME \- authentication service name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVICE_NAME, char *name);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter to a string holding the \fIname\fP of the service
-for DIGEST-MD5, SPNEGO and Kerberos 5 authentication mechanisms. The default
-service names are "ftp", "HTTP", "imap", "ldap", "pop" and "smtp". This option
-allows you to change them.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-See above
-.SH PROTOCOLS
-HTTP, FTP, IMAP, LDAP, POP3 and SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- CURLcode ret;
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SERVICE_NAME, "custom");
- ret = curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.43.0 for HTTP, 7.49.0 for FTP, IMAP, POP3 and SMTP,
-7.82.0 for OpenLDAP.
-.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 (3),
-.BR CURLOPT_PROXY_SERVICE_NAME (3),
-.BR CURLOPT_PROXYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SERVICE_NAME.md b/docs/libcurl/opts/CURLOPT_SERVICE_NAME.md
new file mode 100644
index 000000000..0e13ca712
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SERVICE_NAME.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SERVICE_NAME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYTYPE (3)
+ - CURLOPT_PROXY_SERVICE_NAME (3)
+---
+
+# NAME
+
+CURLOPT_SERVICE_NAME - authentication service name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SERVICE_NAME, char *name);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter to a string holding the *name* of the service
+for DIGEST-MD5, SPNEGO and Kerberos 5 authentication mechanisms. The default
+service names are "ftp", "HTTP", "imap", "ldap", "pop" and "smtp". This option
+allows you to change them.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+See above
+
+# PROTOCOLS
+
+HTTP, FTP, IMAP, LDAP, POP3 and SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SERVICE_NAME, "custom");
+ ret = curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.43.0 for HTTP, 7.49.0 for FTP, IMAP, POP3 and SMTP,
+7.82.0 for OpenLDAP.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SHARE.3 b/docs/libcurl/opts/CURLOPT_SHARE.3
deleted file mode 100644
index ec481e561..000000000
--- a/docs/libcurl/opts/CURLOPT_SHARE.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SHARE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SHARE \- share handle to use
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SHARE, CURLSH *share);
-.fi
-.SH DESCRIPTION
-Pass a \fIshare\fP handle as a parameter. The share handle must have been
-created by a previous call to \fIcurl_share_init(3)\fP. Setting this option,
-makes this curl handle use the data from the shared handle instead of keeping
-the data to itself. This enables several curl handles to share data. If the
-curl handles are used simultaneously in multiple threads, you \fBMUST\fP use
-the locking methods in the share handle. See \fIcurl_share_setopt(3)\fP for
-details.
-
-If you add a share that is set to share cookies, your easy handle uses that
-cookie cache and get the cookie engine enabled. If you stop sharing an object
-that was using cookies (or change to another object that does not share
-cookies), the easy handle gets its cookie engine disabled.
-
-Data that the share object is not set to share is dealt with the usual way, as
-if no share was used.
-
-Set this option to NULL again to stop using that share object.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-CURL *curl2 = curl_easy_init(); /* a second handle */
-if(curl) {
- CURLSH *shobject = curl_share_init();
- curl_share_setopt(shobject, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
- curl_easy_setopt(curl, CURLOPT_SHARE, shobject);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-
- /* the second handle shares cookies from the first */
- curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/second");
- curl_easy_setopt(curl2, CURLOPT_COOKIEFILE, "");
- curl_easy_setopt(curl2, CURLOPT_SHARE, shobject);
- ret = curl_easy_perform(curl2);
- curl_easy_cleanup(curl2);
-
- curl_share_cleanup(shobject);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_COOKIE (3),
-.BR CURLSHOPT_SHARE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SHARE.md b/docs/libcurl/opts/CURLOPT_SHARE.md
new file mode 100644
index 000000000..3c0e7d259
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SHARE.md
@@ -0,0 +1,88 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SHARE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_COOKIE (3)
+ - CURLSHOPT_SHARE (3)
+---
+
+# NAME
+
+CURLOPT_SHARE - share handle to use
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SHARE, CURLSH *share);
+~~~
+
+# DESCRIPTION
+
+Pass a *share* handle as a parameter. The share handle must have been
+created by a previous call to curl_share_init(3). Setting this option,
+makes this curl handle use the data from the shared handle instead of keeping
+the data to itself. This enables several curl handles to share data. If the
+curl handles are used simultaneously in multiple threads, you **MUST** use
+the locking methods in the share handle. See curl_share_setopt(3) for
+details.
+
+If you add a share that is set to share cookies, your easy handle uses that
+cookie cache and get the cookie engine enabled. If you stop sharing an object
+that was using cookies (or change to another object that does not share
+cookies), the easy handle gets its cookie engine disabled.
+
+Data that the share object is not set to share is dealt with the usual way, as
+if no share was used.
+
+Set this option to NULL again to stop using that share object.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ CURL *curl2 = curl_easy_init(); /* a second handle */
+ if(curl) {
+ CURLcode res;
+ CURLSH *shobject = curl_share_init();
+ curl_share_setopt(shobject, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
+ curl_easy_setopt(curl, CURLOPT_SHARE, shobject);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+
+ /* the second handle shares cookies from the first */
+ curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/second");
+ curl_easy_setopt(curl2, CURLOPT_COOKIEFILE, "");
+ curl_easy_setopt(curl2, CURLOPT_SHARE, shobject);
+ res = curl_easy_perform(curl2);
+ curl_easy_cleanup(curl2);
+
+ curl_share_cleanup(shobject);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3 b/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3
deleted file mode 100644
index c63504a99..000000000
--- a/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SOCKOPTDATA 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SOCKOPTDATA \- pointer to pass to sockopt callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKOPTDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP that is untouched by libcurl and passed as the first
-argument in the sockopt callback set with \fICURLOPT_SOCKOPTFUNCTION(3)\fP.
-.SH DEFAULT
-The default value of this parameter is NULL.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-static int sockopt_callback(void *clientp, curl_socket_t curlfd,
- curlsocktype purpose)
-{
- int val = *(int *)clientp;
- setsockopt(curldfd, SOL_SOCKET, SO_RCVBUF, (const char *)&val, sizeof(val));
- return CURL_SOCKOPT_OK;
-}
-
-curl = curl_easy_init();
-if(curl) {
- int recvbuffersize = 256 * 1024;
-
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
-
- /* call this function to set options for the socket */
- curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
- curl_easy_setopt(curl, CURLOPT_SOCKOPTDATA, &recvbuffersize);
-
- res = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.0
-.SH RETURN VALUE
-Returns \fICURLE_OK\fP if the option is supported, and \fICURLE_UNKNOWN_OPTION\fP if not.
-.SH "SEE ALSO"
-.BR CURLOPT_OPENSOCKETFUNCTION (3),
-.BR CURLOPT_SOCKOPTFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md b/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md
new file mode 100644
index 000000000..f44bf532d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SOCKOPTDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_OPENSOCKETFUNCTION (3)
+ - CURLOPT_SOCKOPTFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_SOCKOPTDATA - pointer to pass to sockopt callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKOPTDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* that is untouched by libcurl and passed as the first
+argument in the sockopt callback set with CURLOPT_SOCKOPTFUNCTION(3).
+
+# DEFAULT
+
+The default value of this parameter is NULL.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+static int sockopt_callback(void *clientp, curl_socket_t curlfd,
+ curlsocktype purpose)
+{
+ int val = *(int *)clientp;
+ setsockopt((int)curlfd, SOL_SOCKET, SO_RCVBUF,
+ (const char *)&val, sizeof(val));
+ return CURL_SOCKOPT_OK;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ int recvbuffersize = 256 * 1024;
+
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+
+ /* call this function to set options for the socket */
+ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
+ curl_easy_setopt(curl, CURLOPT_SOCKOPTDATA, &recvbuffersize);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.0
+
+# RETURN VALUE
+
+Returns *CURLE_OK* if the option is supported, and *CURLE_UNKNOWN_OPTION* if not.
diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3
deleted file mode 100644
index 107d68a6a..000000000
--- a/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.3
+++ /dev/null
@@ -1,127 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SOCKOPTFUNCTION 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SOCKOPTFUNCTION \- callback for setting socket options
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-typedef enum {
- CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
- CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
- CURLSOCKTYPE_LAST /* never use */
-} curlsocktype;
-
-#define CURL_SOCKOPT_OK 0
-#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
- CURLE_ABORTED_BY_CALLBACK */
-#define CURL_SOCKOPT_ALREADY_CONNECTED 2
-
-int sockopt_callback(void *clientp,
- curl_socket_t curlfd,
- curlsocktype purpose);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-When set, this callback function gets called by libcurl when the socket has
-been created, but before the connect call to allow applications to change
-specific socket options. The callback's \fIpurpose\fP argument identifies the
-exact purpose for this particular socket:
-
-\fICURLSOCKTYPE_IPCXN\fP for actively created connections or since 7.28.0
-\fICURLSOCKTYPE_ACCEPT\fP for FTP when the connection was setup with PORT/EPSV
-(in earlier versions these sockets were not passed to this callback).
-
-Future versions of libcurl may support more purposes. libcurl passes the newly
-created socket descriptor to the callback in the \fIcurlfd\fP parameter so
-additional setsockopt() calls can be done at the user's discretion.
-
-The \fIclientp\fP pointer contains whatever user-defined value set using the
-\fICURLOPT_SOCKOPTDATA(3)\fP function.
-
-Return \fICURL_SOCKOPT_OK\fP from the callback on success. Return
-\fICURL_SOCKOPT_ERROR\fP from the callback function to signal an unrecoverable
-error to the library and it closes the socket and returns
-\fICURLE_COULDNT_CONNECT\fP. Alternatively, the callback function can return
-\fICURL_SOCKOPT_ALREADY_CONNECTED\fP, to tell libcurl that the socket is
-already connected and then libcurl does no attempt to connect. This allows an
-application to pass in an already connected socket with
-\fICURLOPT_OPENSOCKETFUNCTION(3)\fP and then have this function make libcurl
-not attempt to connect (again).
-.SH DEFAULT
-By default, this callback is NULL and unused.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-/* make libcurl use the already established socket 'sockfd' */
-
-static curl_socket_t opensocket(void *clientp,
- curlsocktype purpose,
- struct curl_sockaddr *address)
-{
- curl_socket_t sockfd;
- sockfd = *(curl_socket_t *)clientp;
- /* the actual externally set socket is passed in via the OPENSOCKETDATA
- option */
- return sockfd;
-}
-
-static int sockopt_callback(void *clientp, curl_socket_t curlfd,
- curlsocktype purpose)
-{
- /* This return code was added in libcurl 7.21.5 */
- return CURL_SOCKOPT_ALREADY_CONNECTED;
-}
-
-curl = curl_easy_init();
-if(curl) {
- /* libcurl thinks that you connect to the host
- * and port that you specify in the URL option. */
- curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
- /* call this function to get a socket */
- curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
- curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
-
- /* call this function to set options for the socket */
- curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
-
- res = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-.fi
-.SH AVAILABILITY
-Added in 7.16.0. The \fICURL_SOCKOPT_ALREADY_CONNECTED\fP return code was
-added in 7.21.5.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_OPENSOCKETFUNCTION (3),
-.BR CURLOPT_SEEKFUNCTION (3),
-.BR CURLOPT_SOCKOPTDATA (3)
diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md b/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md
new file mode 100644
index 000000000..f5de31685
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md
@@ -0,0 +1,132 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SOCKOPTFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_OPENSOCKETFUNCTION (3)
+ - CURLOPT_SEEKFUNCTION (3)
+ - CURLOPT_SOCKOPTDATA (3)
+---
+
+# NAME
+
+CURLOPT_SOCKOPTFUNCTION - callback for setting socket options
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+typedef enum {
+ CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */
+ CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
+ CURLSOCKTYPE_LAST /* never use */
+} curlsocktype;
+
+#define CURL_SOCKOPT_OK 0
+#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
+ CURLE_ABORTED_BY_CALLBACK */
+#define CURL_SOCKOPT_ALREADY_CONNECTED 2
+
+int sockopt_callback(void *clientp,
+ curl_socket_t curlfd,
+ curlsocktype purpose);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+When set, this callback function gets called by libcurl when the socket has
+been created, but before the connect call to allow applications to change
+specific socket options. The callback's *purpose* argument identifies the
+exact purpose for this particular socket:
+
+*CURLSOCKTYPE_IPCXN* for actively created connections or since 7.28.0
+*CURLSOCKTYPE_ACCEPT* for FTP when the connection was setup with PORT/EPSV
+(in earlier versions these sockets were not passed to this callback).
+
+Future versions of libcurl may support more purposes. libcurl passes the newly
+created socket descriptor to the callback in the *curlfd* parameter so
+additional setsockopt() calls can be done at the user's discretion.
+
+The *clientp* pointer contains whatever user-defined value set using the
+CURLOPT_SOCKOPTDATA(3) function.
+
+Return *CURL_SOCKOPT_OK* from the callback on success. Return
+*CURL_SOCKOPT_ERROR* from the callback function to signal an unrecoverable
+error to the library and it closes the socket and returns
+*CURLE_COULDNT_CONNECT*. Alternatively, the callback function can return
+*CURL_SOCKOPT_ALREADY_CONNECTED*, to tell libcurl that the socket is
+already connected and then libcurl does no attempt to connect. This allows an
+application to pass in an already connected socket with
+CURLOPT_OPENSOCKETFUNCTION(3) and then have this function make libcurl
+not attempt to connect (again).
+
+# DEFAULT
+
+By default, this callback is NULL and unused.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+/* make libcurl use the already established socket 'sockfd' */
+
+static curl_socket_t opensocket(void *clientp,
+ curlsocktype purpose,
+ struct curl_sockaddr *address)
+{
+ curl_socket_t sockfd;
+ sockfd = *(curl_socket_t *)clientp;
+ /* the actual externally set socket is passed in via the OPENSOCKETDATA
+ option */
+ return sockfd;
+}
+
+static int sockopt_callback(void *clientp, curl_socket_t curlfd,
+ curlsocktype purpose)
+{
+ /* This return code was added in libcurl 7.21.5 */
+ return CURL_SOCKOPT_ALREADY_CONNECTED;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ int sockfd; /* our custom file descriptor */
+ /* libcurl thinks that you connect to the host
+ * and port that you specify in the URL option. */
+ curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
+ /* call this function to get a socket */
+ curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
+ curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
+
+ /* call this function to set options for the socket */
+ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.0. The *CURL_SOCKOPT_ALREADY_CONNECTED* return code was
+added in 7.21.5.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3 b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3
deleted file mode 100644
index 6ee8c30c1..000000000
--- a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SOCKS5_AUTH 3 "27 April 2017" libcurl libcurl
-.SH NAME
-CURLOPT_SOCKS5_AUTH \- methods for SOCKS5 proxy authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_AUTH, long bitmask);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter, which is set to a bitmask, to tell libcurl which
-authentication method(s) are allowed for SOCKS5 proxy authentication. The only
-supported flags are \fICURLAUTH_BASIC\fP, which allows username/password
-authentication, \fICURLAUTH_GSSAPI\fP, which allows GSS-API authentication, and
-\fICURLAUTH_NONE\fP, which allows no authentication. Set the actual user name
-and password with the \fICURLOPT_PROXYUSERPWD(3)\fP option.
-.SH DEFAULT
-CURLAUTH_BASIC|CURLAUTH_GSSAPI
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* request to use a SOCKS5 proxy */
- curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://user:pass@myproxy.com");
-
- /* enable username/password authentication only */
- curl_easy_setopt(curl, CURLOPT_SOCKS5_AUTH, (long)CURLAUTH_BASIC);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_NOT_BUILT_IN if the bitmask contains unsupported flags.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_PROXYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md
new file mode 100644
index 000000000..457ef9940
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SOCKS5_AUTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_SOCKS5_AUTH - methods for SOCKS5 proxy authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_AUTH, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter, which is set to a bitmask, to tell libcurl which
+authentication method(s) are allowed for SOCKS5 proxy authentication. The only
+supported flags are *CURLAUTH_BASIC*, which allows username/password
+authentication, *CURLAUTH_GSSAPI*, which allows GSS-API authentication, and
+*CURLAUTH_NONE*, which allows no authentication. Set the actual user name and
+password with the CURLOPT_PROXYUSERPWD(3) option.
+
+# DEFAULT
+
+CURLAUTH_BASIC|CURLAUTH_GSSAPI
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* request to use a SOCKS5 proxy */
+ curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://user:pass@myproxy.com");
+
+ /* enable username/password authentication only */
+ curl_easy_setopt(curl, CURLOPT_SOCKS5_AUTH, (long)CURLAUTH_BASIC);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.55.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_NOT_BUILT_IN if the bitmask contains unsupported flags.
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3 b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3
deleted file mode 100644
index a8829a7ff..000000000
--- a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SOCKS5_GSSAPI_NEC 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SOCKS5_GSSAPI_NEC \- SOCKS proxy GSSAPI negotiation protection
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_NEC, long nec);
-.fi
-.SH DESCRIPTION
-Pass a long set to 1 to enable or 0 to disable. As part of the GSSAPI
-negotiation a protection mode is negotiated. The RFC 1961 says in section
-4.3/4.4 it should be protected, but the NEC reference implementation does not.
-If enabled, this option allows the unprotected exchange of the protection mode
-negotiation.
-.SH DEFAULT
-?
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://proxy");
- curl_easy_setopt(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SOCKS5_GSSAPI_SERVICE (3),
-.BR CURLOPT_PROXY (3)
-
-
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md
new file mode 100644
index 000000000..08a1ced6a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SOCKS5_GSSAPI_NEC
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_SOCKS5_GSSAPI_SERVICE (3)
+---
+
+# NAME
+
+CURLOPT_SOCKS5_GSSAPI_NEC - SOCKS proxy GSSAPI negotiation protection
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_NEC, long nec);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 1 to enable or 0 to disable. As part of the GSSAPI
+negotiation a protection mode is negotiated. The RFC 1961 says in section
+4.3/4.4 it should be protected, but the NEC reference implementation does not.
+If enabled, this option allows the unprotected exchange of the protection mode
+negotiation.
+
+# DEFAULT
+
+?
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://proxy");
+ curl_easy_setopt(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3 b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3
deleted file mode 100644
index f22aa12fc..000000000
--- a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SOCKS5_GSSAPI_SERVICE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SOCKS5_GSSAPI_SERVICE \- SOCKS5 proxy authentication service name
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_SERVICE,
- char *name);
-.fi
-.SH DESCRIPTION
-Deprecated since 7.49.0. Use \fICURLOPT_PROXY_SERVICE_NAME(3)\fP instead.
-
-Pass a \fBchar *\fP as parameter to a string holding the \fIname\fP of the
-service. The default service name for a SOCKS5 server is \fI"rcmd"\fP. This
-option allows you to change it.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-See above
-.SH PROTOCOLS
-All network protocols
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://proxy");
- curl_easy_setopt(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE, "rcmd-special");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.4, deprecated in 7.49.0
-.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 (3),
-.BR CURLOPT_PROXYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md
new file mode 100644
index 000000000..47f6e28db
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SOCKS5_GSSAPI_SERVICE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY (3)
+ - CURLOPT_PROXYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_SOCKS5_GSSAPI_SERVICE - SOCKS5 proxy authentication service name
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_GSSAPI_SERVICE,
+ char *name);
+~~~
+
+# DESCRIPTION
+
+Deprecated since 7.49.0. Use CURLOPT_PROXY_SERVICE_NAME(3) instead.
+
+Pass a char pointer as parameter to a string holding the *name* of the
+service. The default service name for a SOCKS5 server is *rcmd*. This option
+allows you to change it.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+See above
+
+# PROTOCOLS
+
+All network protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "socks5://proxy");
+ curl_easy_setopt(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE, "rcmd-special");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.4, deprecated in 7.49.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3 b/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3
deleted file mode 100644
index e125429b5..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_AUTH_TYPES 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_AUTH_TYPES \- auth types for SFTP and SCP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_AUTH_TYPES, long bitmask);
-.fi
-.SH DESCRIPTION
-Pass a long set to a bitmask consisting of one or more of
-CURLSSH_AUTH_PUBLICKEY, CURLSSH_AUTH_PASSWORD, CURLSSH_AUTH_HOST,
-CURLSSH_AUTH_KEYBOARD and CURLSSH_AUTH_AGENT.
-
-Set \fICURLSSH_AUTH_ANY\fP to let libcurl pick a suitable one. Currently
-CURLSSH_AUTH_HOST has no effect. If CURLSSH_AUTH_AGENT is used, libcurl
-attempts to connect to ssh-agent or pageant and let the agent attempt the
-authentication.
-.SH DEFAULT
-CURLSSH_AUTH_ANY (all available)
-.SH PROTOCOLS
-SFTP and SCP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
- curl_easy_setopt(curl, CURLOPT_SSH_AUTH_TYPES,
- CURLSSH_AUTH_PUBLICKEY | CURLSSH_AUTH_KEYBOARD);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-CURLSSH_AUTH_HOST was added in 7.16.1, CURLSSH_AUTH_AGENT was added in 7.28.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 (3),
-.BR CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 (3),
-.BR CURLOPT_SSH_PUBLIC_KEYFILE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md b/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md
new file mode 100644
index 000000000..205e94d19
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_AUTH_TYPES
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 (3)
+ - CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 (3)
+ - CURLOPT_SSH_PUBLIC_KEYFILE (3)
+---
+
+# NAME
+
+CURLOPT_SSH_AUTH_TYPES - auth types for SFTP and SCP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_AUTH_TYPES, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to a bitmask consisting of one or more of
+CURLSSH_AUTH_PUBLICKEY, CURLSSH_AUTH_PASSWORD, CURLSSH_AUTH_HOST,
+CURLSSH_AUTH_KEYBOARD and CURLSSH_AUTH_AGENT.
+
+Set *CURLSSH_AUTH_ANY* to let libcurl pick a suitable one. Currently
+CURLSSH_AUTH_HOST has no effect. If CURLSSH_AUTH_AGENT is used, libcurl
+attempts to connect to ssh-agent or pageant and let the agent attempt the
+authentication.
+
+# DEFAULT
+
+CURLSSH_AUTH_ANY (all available)
+
+# PROTOCOLS
+
+SFTP and SCP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
+ curl_easy_setopt(curl, CURLOPT_SSH_AUTH_TYPES,
+ CURLSSH_AUTH_PUBLICKEY | CURLSSH_AUTH_KEYBOARD);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+CURLSSH_AUTH_HOST was added in 7.16.1, CURLSSH_AUTH_AGENT was added in 7.28.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3 b/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3
deleted file mode 100644
index b440f7fb0..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_COMPRESSION 3 "05 Aug 2017" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_COMPRESSION \- enable SSH compression
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_COMPRESSION, long enable);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter set to 1L to enable or 0L to disable.
-
-Enables built-in SSH compression. This is a request, not an order; the server
-may or may not do it.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-All SSH based protocols: SCP, SFTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com");
-
- /* enable built-in compression */
- curl_easy_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.56.0
-.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_ACCEPT_ENCODING (3),
-.BR CURLOPT_TRANSFER_ENCODING (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.md b/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.md
new file mode 100644
index 000000000..5e2b2785d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_COMPRESSION.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_COMPRESSION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ACCEPT_ENCODING (3)
+ - CURLOPT_TRANSFER_ENCODING (3)
+---
+
+# NAME
+
+CURLOPT_SSH_COMPRESSION - enable SSH compression
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_COMPRESSION, long enable);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter set to 1L to enable or 0L to disable.
+
+Enables built-in SSH compression. This is a request, not an order; the server
+may or may not do it.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+All SSH based protocols: SCP, SFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com");
+
+ /* enable built-in compression */
+ curl_easy_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.56.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.3 b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.3
deleted file mode 100644
index ac13dc6a2..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_KEYDATA 3 "4 Nov 2021" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_HOSTKEYDATA \- pointer to pass to the SSH host key callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOSTKEYDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a void * as parameter. This \fIpointer\fP is passed along untouched to
-the callback set with \fICURLOPT_SSH_HOSTKEYFUNCTION(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SCP and SFTP
-.SH EXAMPLE
-.nf
-int hostkeycb(void *clientp, /* passed with CURLOPT_SSH_HOSTKEYDATA */
- int keytype, /* CURLKHTYPE */
- const char * key, /* host key to check */
- size_t keylen); /* length of the key */
-{
- /* 'clientp' points to the callback_data struct */
- /* investigate the situation and return the correct value */
- return CURLKHMATCH_OK;
-}
-{
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
- curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYFUNCTION, hostkeycb);
- curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYDATA, &callback_data);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.84.0, works only with libssh2 backend.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSH_HOSTKEYFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.md b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.md
new file mode 100644
index 000000000..39cbd0ddd
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYDATA.md
@@ -0,0 +1,73 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_KEYDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_HOSTKEYFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_SSH_HOSTKEYDATA - pointer to pass to the SSH host key callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOSTKEYDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a void * as parameter. This *pointer* is passed along untouched to
+the callback set with CURLOPT_SSH_HOSTKEYFUNCTION(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SCP and SFTP
+
+# EXAMPLE
+
+~~~c
+struct mine {
+ void *custom;
+};
+
+static int hostkeycb(void *clientp, /* CURLOPT_SSH_HOSTKEYDATA */
+ int keytype, /* CURLKHTYPE */
+ const char *key, /* host key to check */
+ size_t keylen) /* length of the key */
+{
+ /* 'clientp' points to the callback_data struct */
+ /* investigate the situation and return the correct value */
+ return CURLKHMATCH_OK;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct mine callback_data;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
+ curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYFUNCTION, hostkeycb);
+ curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYDATA, &callback_data);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.84.0, works only with libssh2 backend.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.3
deleted file mode 100644
index 43fa94bf2..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_HOSTKEYFUNCTION 3 "4 Nov 2021" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_HOSTKEYFUNCTION \- callback to check host key
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int keycallback(void *clientp,
- int keytype,
- const char *key,
- size_t keylen);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOSTKEYFUNCTION,
- keycallback);
-.fi
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above. It overrides \fICURLOPT_SSH_KNOWNHOSTS(3)\fP.
-
-This callback gets called when the verification of the SSH host key is needed.
-
-\fBkey\fP is \fBkeylen\fP bytes long and is the key to check. \fBkeytype\fP
-says what type it is, from the \fBCURLKHTYPE_*\fP series in the
-\fBcurl_khtype\fP enum.
-
-\fBclientp\fP is a custom pointer set with \fICURLOPT_SSH_HOSTKEYDATA(3)\fP.
-
-The callback MUST return one of the following return codes to tell libcurl how
-to act:
-.IP CURLKHMATCH_OK
-The host key is accepted, the connection should continue.
-.IP CURLKHMATCH_MISMATCH
-the host key is rejected, the connection is canceled.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SCP and SFTP
-.SH EXAMPLE
-.nf
-int hostkeycb(void *clientp, /* passed with CURLOPT_SSH_HOSTKEYDATA */
- int keytype, /* CURLKHTYPE */
- const char * key, /* host key to check */
- size_t keylen); /* length of the key */
-{
- /* 'clientp' points to the callback_data struct */
- /* investigate the situation and return the correct value */
- return CURLKHMATCH_OK;
-}
-{
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
- curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYFUNCTION, hostkeycb);
- curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYDATA, &callback_data);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.84.0 , work only with libssh2 backend.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSH_HOSTKEYDATA (3),
-.BR CURLOPT_SSH_KNOWNHOSTS (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.md b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.md
new file mode 100644
index 000000000..ed5797520
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOSTKEYFUNCTION.md
@@ -0,0 +1,98 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_HOSTKEYFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_HOSTKEYDATA (3)
+ - CURLOPT_SSH_KNOWNHOSTS (3)
+---
+
+# NAME
+
+CURLOPT_SSH_HOSTKEYFUNCTION - callback to check host key
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int keycallback(void *clientp,
+ int keytype,
+ const char *key,
+ size_t keylen);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOSTKEYFUNCTION,
+ keycallback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above. It overrides CURLOPT_SSH_KNOWNHOSTS(3).
+
+This callback gets called when the verification of the SSH host key is needed.
+
+**key** is **keylen** bytes long and is the key to check. **keytype**
+says what type it is, from the **CURLKHTYPE_*** series in the
+**curl_khtype** enum.
+
+**clientp** is a custom pointer set with CURLOPT_SSH_HOSTKEYDATA(3).
+
+The callback MUST return one of the following return codes to tell libcurl how
+to act:
+
+## CURLKHMATCH_OK
+
+The host key is accepted, the connection should continue.
+
+## CURLKHMATCH_MISMATCH
+
+the host key is rejected, the connection is canceled.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SCP and SFTP
+
+# EXAMPLE
+
+~~~c
+struct mine {
+ void *custom;
+};
+
+int hostkeycb(void *clientp, /* passed with CURLOPT_SSH_HOSTKEYDATA */
+ int keytype, /* CURLKHTYPE */
+ const char *key, /* host key to check */
+ size_t keylen) /* length of the key */
+{
+ /* 'clientp' points to the callback_data struct */
+ /* investigate the situation and return the correct value */
+ return CURLKHMATCH_OK;
+}
+int main(void)
+{
+ struct mine callback_data;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
+ curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYFUNCTION, hostkeycb);
+ curl_easy_setopt(curl, CURLOPT_SSH_HOSTKEYDATA, &callback_data);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.84.0 , work only with libssh2 backend.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3 b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3
deleted file mode 100644
index 30ed2ec16..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 \- MD5 checksum of SSH server public key
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
- char *md5);
-.SH DESCRIPTION
-Pass a char * pointing to a string containing 32 hexadecimal digits. The
-string should be the 128 bit MD5 checksum of the remote host's public key, and
-libcurl aborts the connection to the host unless the MD5 checksum match.
-
-MD5 is a weak algorithm. We strongly recommend using
-\fICURLOPT_SSH_HOST_PUBLIC_KEY_SHA256(3)\fP instead.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SCP and SFTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
- curl_easy_setopt(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
- "afe17cd62a0f3b61f1ab9cb22ba269a7");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.17.1
-.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_SSH_AUTH_TYPES (3),
-.BR CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 (3),
-.BR CURLOPT_SSH_PUBLIC_KEYFILE (3),
-.BR CURLOPT_SSH_KNOWNHOSTS (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md
new file mode 100644
index 000000000..4b7876501
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_AUTH_TYPES (3)
+ - CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 (3)
+ - CURLOPT_SSH_KNOWNHOSTS (3)
+ - CURLOPT_SSH_PUBLIC_KEYFILE (3)
+---
+
+# NAME
+
+CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 - MD5 checksum of SSH server public key
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
+ char *md5);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer pointing to a string containing 32 hexadecimal digits. The
+string should be the 128 bit MD5 checksum of the remote host's public key, and
+libcurl aborts the connection to the host unless the MD5 checksum match.
+
+MD5 is a weak algorithm. We strongly recommend using
+CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256(3) instead.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SCP and SFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
+ curl_easy_setopt(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
+ "afe17cd62a0f3b61f1ab9cb22ba269a7");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.17.1
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.3 b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.3
deleted file mode 100644
index 2798d14bd..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 3 "27 Aug 2021" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 \- SHA256 hash of SSH server public key
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
- char *sha256);
-.SH DESCRIPTION
-Pass a char * pointing to a string containing a Base64-encoded SHA256 hash of
-the remote host's public key. The transfer fails if the given hash does not
-match the hash the remote host provides.
-
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SCP and SFTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
- curl_easy_setopt(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
- "NDVkMTQxMGQ1ODdmMjQ3MjczYjAyOTY5MmRkMjVmNDQ=");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.80.0
-Requires the libssh2 backend.
-.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_SSH_AUTH_TYPES (3),
-.BR CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 (3),
-.BR CURLOPT_SSH_PUBLIC_KEYFILE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md
new file mode 100644
index 000000000..41562db63
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_AUTH_TYPES (3)
+ - CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 (3)
+ - CURLOPT_SSH_PUBLIC_KEYFILE (3)
+---
+
+# NAME
+
+CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 - SHA256 hash of SSH server public key
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
+ char *sha256);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer pointing to a string containing a Base64-encoded SHA256
+hash of the remote host's public key. The transfer fails if the given hash
+does not match the hash the remote host provides.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SCP and SFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
+ curl_easy_setopt(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
+ "NDVkMTQxMGQ1ODdmMjQ3MjczYjAyOTY5MmRkMjVmNDQ=");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.80.0
+Requires the libssh2 backend.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3 b/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3
deleted file mode 100644
index bfa7b7738..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_KEYDATA 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_KEYDATA \- pointer passed to the SSH key callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a void * as parameter. This \fIpointer\fP is passed along verbatim to the
-callback set with \fICURLOPT_SSH_KEYFUNCTION(3)\fP.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SFTP and SCP
-.SH EXAMPLE
-.nf
-static int keycb(CURL *easy,
- const struct curl_khkey *knownkey,
- const struct curl_khkey *foundkey,
- enum curl_khmatch match,
- void *clientp)
-{
- /* 'clientp' points to the callback_data struct */
- /* investigate the situation and return the correct value */
- return CURLKHSTAT_FINE_ADD_TO_FILE;
-}
-{
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
- curl_easy_setopt(curl, CURLOPT_SSH_KEYFUNCTION, keycb);
- curl_easy_setopt(curl, CURLOPT_SSH_KEYDATA, &callback_data);
- curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, "/home/user/known_hosts");
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.6
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSH_KEYDATA (3),
-.BR CURLOPT_SSH_KNOWNHOSTS (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.md b/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.md
new file mode 100644
index 000000000..e90cace34
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_KEYDATA.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_KEYDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_KEYDATA (3)
+ - CURLOPT_SSH_KNOWNHOSTS (3)
+---
+
+# NAME
+
+CURLOPT_SSH_KEYDATA - pointer passed to the SSH key callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a void * as parameter. This *pointer* is passed along verbatim to the
+callback set with CURLOPT_SSH_KEYFUNCTION(3).
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SFTP and SCP
+
+# EXAMPLE
+
+~~~c
+struct mine {
+ void *custom;
+};
+static int keycb(CURL *easy,
+ const struct curl_khkey *knownkey,
+ const struct curl_khkey *foundkey,
+ enum curl_khmatch match,
+ void *clientp)
+{
+ /* 'clientp' points to the callback_data struct */
+ /* investigate the situation and return the correct value */
+ return CURLKHSTAT_FINE_ADD_TO_FILE;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct mine callback_data;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
+ curl_easy_setopt(curl, CURLOPT_SSH_KEYFUNCTION, keycb);
+ curl_easy_setopt(curl, CURLOPT_SSH_KEYDATA, &callback_data);
+ curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, "/home/user/known_hosts");
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.6
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3 b/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3
deleted file mode 100644
index 7c2585195..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.3
+++ /dev/null
@@ -1,133 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_KEYFUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_KEYFUNCTION \- callback for known host matching logic
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-enum curl_khstat {
- CURLKHSTAT_FINE_ADD_TO_FILE,
- CURLKHSTAT_FINE,
- CURLKHSTAT_REJECT, /* reject the connection, return an error */
- CURLKHSTAT_DEFER, /* do not accept it, but we cannot answer right
- now. Causes a CURLE_PEER_FAILED_VERIFICATION error but
- the connection is left intact */
- CURLKHSTAT_FINE_REPLACE
-};
-
-enum curl_khmatch {
- CURLKHMATCH_OK, /* match */
- CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
- CURLKHMATCH_MISSING, /* no matching host/key found */
-};
-
-struct curl_khkey {
- 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;
-};
-
-int ssh_keycallback(CURL *easy,
- const struct curl_khkey *knownkey,
- const struct curl_khkey *foundkey,
- enum curl_khmatch match,
- void *clientp);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYFUNCTION,
- ssh_keycallback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-It gets called when the known_host matching has been done, to allow the
-application to act and decide for libcurl how to proceed. The callback is only
-called if \fICURLOPT_SSH_KNOWNHOSTS(3)\fP is also set.
-
-This callback function gets passed the CURL handle, the key from the
-known_hosts file \fIknownkey\fP, the key from the remote site \fIfoundkey\fP,
-info from libcurl on the matching status and a custom pointer (set with
-\fICURLOPT_SSH_KEYDATA(3)\fP). It MUST return one of the following return
-codes to tell libcurl how to act:
-.IP CURLKHSTAT_FINE_REPLACE
-The new host+key is accepted and libcurl replaces the old host+key into the
-known_hosts file before continuing with the connection. This also adds the new
-host+key combo to the known_host pool kept in memory if it was not already
-present there. The adding of data to the file is done by completely replacing
-the file with a new copy, so the permissions of the file must allow
-this. (Added in 7.73.0)
-.IP CURLKHSTAT_FINE_ADD_TO_FILE
-The host+key is accepted and libcurl appends it to the known_hosts file before
-continuing with the connection. This also adds the host+key combo to the
-known_host pool kept in memory if it was not already present there. The adding
-of data to the file is done by completely replacing the file with a new copy,
-so the permissions of the file must allow this.
-.IP CURLKHSTAT_FINE
-The host+key is accepted libcurl continues with the connection. This also adds
-the host+key combo to the known_host pool kept in memory if it was not already
-present there.
-.IP CURLKHSTAT_REJECT
-The host+key is rejected. libcurl denies the connection to continue and it is
-closed.
-.IP CURLKHSTAT_DEFER
-The host+key is rejected, but the SSH connection is asked to be kept alive.
-This feature could be used when the app wants to somehow return back and act
-on the host+key situation and then retry without needing the overhead of
-setting it up from scratch again.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SFTP and SCP
-.SH EXAMPLE
-.nf
-static int keycb(CURL *easy,
- const struct curl_khkey *knownkey,
- const struct curl_khkey *foundkey,
- enum curl_khmatch match,
- void *clientp)
-{
- /* 'clientp' points to the callback_data struct */
- /* investigate the situation and return the correct value */
- return CURLKHSTAT_FINE_ADD_TO_FILE;
-}
-{
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
- curl_easy_setopt(curl, CURLOPT_SSH_KEYFUNCTION, keycb);
- curl_easy_setopt(curl, CURLOPT_SSH_KEYDATA, &callback_data);
- curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, "/home/user/known_hosts");
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.6
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSH_KEYDATA (3),
-.BR CURLOPT_SSH_KNOWNHOSTS (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md b/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md
new file mode 100644
index 000000000..5fc40060e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md
@@ -0,0 +1,152 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_KEYFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_KEYDATA (3)
+ - CURLOPT_SSH_KNOWNHOSTS (3)
+---
+
+# NAME
+
+CURLOPT_SSH_KEYFUNCTION - callback for known host matching logic
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+enum curl_khstat {
+ CURLKHSTAT_FINE_ADD_TO_FILE,
+ CURLKHSTAT_FINE,
+ CURLKHSTAT_REJECT, /* reject the connection, return an error */
+ CURLKHSTAT_DEFER, /* do not accept it, but we cannot answer right
+ now. Causes a CURLE_PEER_FAILED_VERIFICATION error but
+ the connection is left intact */
+ CURLKHSTAT_FINE_REPLACE
+};
+
+enum curl_khmatch {
+ CURLKHMATCH_OK, /* match */
+ CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
+ CURLKHMATCH_MISSING, /* no matching host/key found */
+};
+
+struct curl_khkey {
+ 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;
+};
+
+int ssh_keycallback(CURL *easy,
+ const struct curl_khkey *knownkey,
+ const struct curl_khkey *foundkey,
+ enum curl_khmatch match,
+ void *clientp);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KEYFUNCTION,
+ ssh_keycallback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+It gets called when the known_host matching has been done, to allow the
+application to act and decide for libcurl how to proceed. The callback is only
+called if CURLOPT_SSH_KNOWNHOSTS(3) is also set.
+
+This callback function gets passed the CURL handle, the key from the
+known_hosts file *knownkey*, the key from the remote site *foundkey*,
+info from libcurl on the matching status and a custom pointer (set with
+CURLOPT_SSH_KEYDATA(3)). It MUST return one of the following return
+codes to tell libcurl how to act:
+
+## CURLKHSTAT_FINE_REPLACE
+
+The new host+key is accepted and libcurl replaces the old host+key into the
+known_hosts file before continuing with the connection. This also adds the new
+host+key combo to the known_host pool kept in memory if it was not already
+present there. The adding of data to the file is done by completely replacing
+the file with a new copy, so the permissions of the file must allow
+this. (Added in 7.73.0)
+
+## CURLKHSTAT_FINE_ADD_TO_FILE
+
+The host+key is accepted and libcurl appends it to the known_hosts file before
+continuing with the connection. This also adds the host+key combo to the
+known_host pool kept in memory if it was not already present there. The adding
+of data to the file is done by completely replacing the file with a new copy,
+so the permissions of the file must allow this.
+
+## CURLKHSTAT_FINE
+
+The host+key is accepted libcurl continues with the connection. This also adds
+the host+key combo to the known_host pool kept in memory if it was not already
+present there.
+
+## CURLKHSTAT_REJECT
+
+The host+key is rejected. libcurl denies the connection to continue and it is
+closed.
+
+## CURLKHSTAT_DEFER
+
+The host+key is rejected, but the SSH connection is asked to be kept alive.
+This feature could be used when the app wants to return and act on the
+host+key situation and then retry without needing the overhead of setting it
+up from scratch again.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SFTP and SCP
+
+# EXAMPLE
+
+~~~c
+struct mine {
+ void *custom;
+};
+
+static int keycb(CURL *easy,
+ const struct curl_khkey *knownkey,
+ const struct curl_khkey *foundkey,
+ enum curl_khmatch match,
+ void *clientp)
+{
+ /* 'clientp' points to the callback_data struct */
+ /* investigate the situation and return the correct value */
+ return CURLKHSTAT_FINE_ADD_TO_FILE;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct mine callback_data;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/thisfile.txt");
+ curl_easy_setopt(curl, CURLOPT_SSH_KEYFUNCTION, keycb);
+ curl_easy_setopt(curl, CURLOPT_SSH_KEYDATA, &callback_data);
+ curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, "/home/user/known_hosts");
+
+ curl_easy_perform(curl);
+}
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.6
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3 b/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3
deleted file mode 100644
index 419e63ec8..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_KNOWNHOSTS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_KNOWNHOSTS \- file name holding the SSH known hosts
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KNOWNHOSTS, char *fname);
-.fi
-.SH DESCRIPTION
-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 only
-accepts connections with hosts that are known and present in that file, with a
-matching public key. Use \fICURLOPT_SSH_KEYFUNCTION(3)\fP to alter the default
-behavior on host and key matches and mismatches.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SFTP and SCP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
- curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS,
- "/home/clarkkent/.ssh/known_hosts");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.6
-.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_SSH_AUTH_TYPES (3),
-.BR CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md b/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md
new file mode 100644
index 000000000..5a5fcbf33
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_KNOWNHOSTS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_AUTH_TYPES (3)
+ - CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 (3)
+---
+
+# NAME
+
+CURLOPT_SSH_KNOWNHOSTS - filename holding the SSH known hosts
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KNOWNHOSTS, char *fname);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string holding the filename 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 only
+accepts connections with hosts that are known and present in that file, with a
+matching public key. Use CURLOPT_SSH_KEYFUNCTION(3) to alter the default
+behavior on host and key matches and mismatches.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SFTP and SCP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
+ curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS,
+ "/home/clarkkent/.ssh/known_hosts");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.6
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3 b/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3
deleted file mode 100644
index 384aae9b5..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_PRIVATE_KEYFILE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_PRIVATE_KEYFILE \- private key file for SSH auth
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_PRIVATE_KEYFILE,
- char *filename);
-.SH DESCRIPTION
-Pass a char * pointing to a \fIfilename\fP for your private key. If not used,
-libcurl defaults to \fB$HOME/.ssh/id_rsa\fP or \fB$HOME/.ssh/id_dsa\fP if the
-HOME environment variable is set, and just \fB"id_rsa"\fP or \fB"id_dsa"\fP in
-the current directory if HOME is not set.
-
-If the file is password-protected, set the password with
-\fICURLOPT_KEYPASSWD(3)\fP.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-As explained above
-.SH PROTOCOLS
-SFTP and SCP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
- curl_easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE,
- "/home/clarkkent/.ssh/id_rsa");
- curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "password");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.1
-.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_SSH_PUBLIC_KEYFILE (3),
-.BR CURLOPT_SSH_AUTH_TYPES (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md b/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md
new file mode 100644
index 000000000..e8a40079b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md
@@ -0,0 +1,76 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_PRIVATE_KEYFILE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_AUTH_TYPES (3)
+ - CURLOPT_SSH_PUBLIC_KEYFILE (3)
+---
+
+# NAME
+
+CURLOPT_SSH_PRIVATE_KEYFILE - private key file for SSH auth
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_PRIVATE_KEYFILE,
+ char *filename);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer pointing to a *filename* for your private key. If not
+used, libcurl defaults to **$HOME/.ssh/id_rsa** or **$HOME/.ssh/id_dsa** if
+the HOME environment variable is set, and in the current directory if HOME is
+not set.
+
+If the file is password-protected, set the password with
+CURLOPT_KEYPASSWD(3).
+
+The SSH library derives the public key from this private key when possible. If
+the SSH library cannot derive the public key from the private one and no
+public one is provided with CURLOPT_SSH_PUBLIC_KEYFILE(3), the transfer
+fails.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+As explained above
+
+# PROTOCOLS
+
+SFTP and SCP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
+ curl_easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE,
+ "/home/clarkkent/.ssh/id_rsa");
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "password");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.1
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3 b/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3
deleted file mode 100644
index a97aa4c1f..000000000
--- a/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSH_PUBLIC_KEYFILE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSH_PUBLIC_KEYFILE \- public key file for SSH auth
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_PUBLIC_KEYFILE,
- char *filename);
-.SH DESCRIPTION
-Pass a char * pointing to a \fIfilename\fP for your public key. If not used,
-libcurl defaults to \fB$HOME/.ssh/id_dsa.pub\fP if the HOME environment
-variable is set, and just "id_dsa.pub" in the current directory if HOME is not
-set.
-
-If NULL (or an empty string) is passed, libcurl passes no public key to
-libssh2, which then computes it from the private key. This is known to work
-with libssh2 1.4.0+ linked against OpenSSL.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-SFTP and SCP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
- curl_easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE,
- "/home/clarkkent/.ssh/id_rsa.pub");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-The "" trick was added in 7.26.0
-.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_SSH_PRIVATE_KEYFILE (3),
-.BR CURLOPT_SSH_AUTH_TYPES (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md b/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md
new file mode 100644
index 000000000..35d65ad93
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSH_PUBLIC_KEYFILE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSH_AUTH_TYPES (3)
+ - CURLOPT_SSH_PRIVATE_KEYFILE (3)
+---
+
+# NAME
+
+CURLOPT_SSH_PUBLIC_KEYFILE - public key file for SSH auth
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_PUBLIC_KEYFILE,
+ char *filename);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer pointing to a *filename* for your public key. If not used,
+libcurl defaults to **$HOME/.ssh/id_dsa.pub** if the HOME environment variable
+is set, and just "id_dsa.pub" in the current directory if HOME is not set.
+
+If NULL (or an empty string) is passed to this option, libcurl passes no
+public key to the SSH library, which then rather derives it from the private
+key. If the SSH library cannot derive the public key from the private one and
+no public one is provided, the transfer fails.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+SFTP and SCP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/file");
+ curl_easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE,
+ "/home/clarkkent/.ssh/id_rsa.pub");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+The "" trick was added in 7.26.0
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT.3 b/docs/libcurl/opts/CURLOPT_SSLCERT.3
deleted file mode 100644
index 2727498f4..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLCERT.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLCERT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSLCERT \- SSL client certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT, char *cert);
-.fi
-.SH DESCRIPTION
-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.
-
-With Secure Transport, this can also be the nickname of the certificate 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 can be specified by a path expression to a
-certificate store. (You can import \fIPFX\fP to a store first). You can use
-"<store location>\\<store name>\\<thumbprint>" to refer to a certificate in
-the system certificates store, for example,
-\fB"CurrentUser\\MY\\934a7ac6f8a5d579285a74fa"\fP. The thumbprint is usually a
-SHA-1 hex string which you can see in certificate details. Following store
-locations are supported: \fBCurrentUser\fP, \fBLocalMachine\fP,
-\fBCurrentService\fP, \fBServices\fP, \fBCurrentUserGroupPolicy\fP,
-\fBLocalMachineGroupPolicy\fP, \fBLocalMachineEnterprise\fP. 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.
-
-The application does not have to keep the string around after setting this
-option.
-.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) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If built TLS enabled.
-.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),
-.BR CURLOPT_SSLKEY (3),
-.BR CURLOPT_KEYPASSWD (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT.md b/docs/libcurl/opts/CURLOPT_SSLCERT.md
new file mode 100644
index 000000000..21f052ff7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLCERT.md
@@ -0,0 +1,87 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLCERT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_KEYPASSWD (3)
+ - CURLOPT_SSLCERTTYPE (3)
+ - CURLOPT_SSLKEY (3)
+---
+
+# NAME
+
+CURLOPT_SSLCERT - SSL client certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT, char *cert);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. The string should be
+the filename of your client certificate. The default format is "P12" on Secure
+Transport and "PEM" on other engines, and can be changed with
+CURLOPT_SSLCERTTYPE(3).
+
+With Secure Transport, this can also be the nickname of the certificate 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 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,
+**"CurrentUserMY934a7ac6f8a5d579285a74fa"**. The 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 CURLOPT_SSLCERTTYPE(3).
+
+When using a client certificate, you most likely also need to provide a
+private key with CURLOPT_SSLKEY(3).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3 b/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3
deleted file mode 100644
index 6c2abd003..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLCERTTYPE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSLCERTTYPE \- type of client SSL certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERTTYPE, char *type);
-.fi
-.SH DESCRIPTION
-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 or
-Schannel. OpenSSL (versions 0.9.3 and later), Secure Transport (on iOS 5 or
-later, or OS X 10.7 or later) and Schannel support "P12" for PKCS#12-encoded
-files.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-"PEM"
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
- curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If built TLS enabled. Added in 7.9.3
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_SSLCERT (3),
-.BR CURLOPT_SSLKEY (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md b/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md
new file mode 100644
index 000000000..420ca4f86
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLCERTTYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSLCERT (3)
+ - CURLOPT_SSLKEY (3)
+---
+
+# NAME
+
+CURLOPT_SSLCERTTYPE - type of client SSL certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERTTYPE, char *type);
+~~~
+
+# DESCRIPTION
+
+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 or
+Schannel. OpenSSL (versions 0.9.3 and later), Secure Transport (on iOS 5 or
+later, or OS X 10.7 or later) and Schannel support "P12" for PKCS#12-encoded
+files.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+"PEM"
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built TLS enabled. Added in 7.9.3
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3
deleted file mode 100644
index 45510422e..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLCERT_BLOB 3 "24 Jun 2020" libcurl libcurl
-.SH NAME
-CURLOPT_SSLCERT_BLOB \- SSL client certificate from memory blob
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT_BLOB,
- struct curl_blob *stblob);
-.fi
-.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 format must be
-"DER" or "PEM" on mbedTLS. The format 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 7.71.0. This option is supported by the OpenSSL, Secure Transport,
-Schannel and mbedTLS (since 7.78.0) 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),
-.BR CURLOPT_SSLKEY (3),
-.BR CURLOPT_KEYPASSWD (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md
new file mode 100644
index 000000000..1f3ed56ed
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md
@@ -0,0 +1,83 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLCERT_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_KEYPASSWD (3)
+ - CURLOPT_SSLCERTTYPE (3)
+ - CURLOPT_SSLKEY (3)
+---
+
+# NAME
+
+CURLOPT_SSLCERT_BLOB - SSL client certificate from memory blob
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT_BLOB,
+ struct curl_blob *stblob);
+~~~
+
+# 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 format must be
+"DER" or "PEM" on mbedTLS. The format must be specified with
+CURLOPT_SSLCERTTYPE(3).
+
+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 CURLOPT_SSLCERT(3) which instead
+expects a filename as input.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+
+extern char *certificateData; /* point to data */
+extern size_t filesize; /* size of data */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.71.0. This option is supported by the OpenSSL, Secure Transport,
+Schannel and mbedTLS (since 7.78.0) backends.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE.3 b/docs/libcurl/opts/CURLOPT_SSLENGINE.3
deleted file mode 100644
index 839f59598..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLENGINE.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLENGINE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSLENGINE \- SSL engine identifier
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE, char *id);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter. It is 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
-option.
-.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) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSLENGINE, "dynamic");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Only if the SSL backend is OpenSSL built with engine support.
-.SH RETURN VALUE
-CURLE_OK - Engine found.
-
-CURLE_SSL_ENGINE_NOTFOUND - Engine not found, or OpenSSL was not built with
-engine support.
-
-CURLE_SSL_ENGINE_INITFAILED - Engine found but initialization failed.
-
-CURLE_NOT_BUILT_IN - Option not built in, OpenSSL is not the SSL backend.
-
-CURLE_UNKNOWN_OPTION - Option not recognized.
-
-CURLE_OUT_OF_MEMORY - Insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLINFO_SSL_ENGINES (3),
-.BR CURLOPT_SSLENGINE_DEFAULT (3),
-.BR CURLOPT_SSLKEY (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE.md b/docs/libcurl/opts/CURLOPT_SSLENGINE.md
new file mode 100644
index 000000000..45ccc42c5
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLENGINE.md
@@ -0,0 +1,74 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLENGINE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_SSL_ENGINES (3)
+ - CURLOPT_SSLENGINE_DEFAULT (3)
+ - CURLOPT_SSLKEY (3)
+---
+
+# NAME
+
+CURLOPT_SSLENGINE - SSL engine identifier
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE, char *id);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. It is 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
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSLENGINE, "dynamic");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Only if the SSL backend is OpenSSL built with engine support.
+
+# RETURN VALUE
+
+CURLE_OK - Engine found.
+
+CURLE_SSL_ENGINE_NOTFOUND - Engine not found, or OpenSSL was not built with
+engine support.
+
+CURLE_SSL_ENGINE_INITFAILED - Engine found but initialization failed.
+
+CURLE_NOT_BUILT_IN - Option not built in, OpenSSL is not the SSL backend.
+
+CURLE_UNKNOWN_OPTION - Option not recognized.
+
+CURLE_OUT_OF_MEMORY - Insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3 b/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3
deleted file mode 100644
index 00a69d26b..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLENGINE_DEFAULT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSLENGINE_DEFAULT \- make SSL engine default
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE_DEFAULT, long val);
-.fi
-.SH DESCRIPTION
-Pass a long set to 1 to make the already specified crypto engine the default
-for (asymmetric) crypto operations.
-
-This option has no effect unless set after \fICURLOPT_SSLENGINE(3)\fP.
-.SH DEFAULT
-None
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSLENGINE, "dynamic");
- curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Only if the SSL backend is OpenSSL built with engine support.
-.SH RETURN VALUE
-CURLE_OK - Engine set as default.
-
-CURLE_SSL_ENGINE_SETFAILED - Engine could not be set as default.
-
-CURLE_NOT_BUILT_IN - Option not built in, OpenSSL is not the SSL backend.
-
-CURLE_UNKNOWN_OPTION - Option not recognized.
-
-CURLE_OUT_OF_MEMORY - Insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_SSLENGINE (3),
-.BR CURLOPT_SSLCERT (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md b/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md
new file mode 100644
index 000000000..d082f7b54
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLENGINE_DEFAULT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSLCERT (3)
+ - CURLOPT_SSLENGINE (3)
+---
+
+# NAME
+
+CURLOPT_SSLENGINE_DEFAULT - make SSL engine default
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE_DEFAULT, long val);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 1 to make the already specified crypto engine the default
+for (asymmetric) crypto operations.
+
+This option has no effect unless set after CURLOPT_SSLENGINE(3).
+
+# DEFAULT
+
+None
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSLENGINE, "dynamic");
+ curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Only if the SSL backend is OpenSSL built with engine support.
+
+# RETURN VALUE
+
+CURLE_OK - Engine set as default.
+
+CURLE_SSL_ENGINE_SETFAILED - Engine could not be set as default.
+
+CURLE_NOT_BUILT_IN - Option not built in, OpenSSL is not the SSL backend.
+
+CURLE_UNKNOWN_OPTION - Option not recognized.
+
+CURLE_OUT_OF_MEMORY - Insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY.3 b/docs/libcurl/opts/CURLOPT_SSLKEY.3
deleted file mode 100644
index ee85aaff2..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLKEY.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLKEY 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSLKEY \- private key file for TLS and SSL client cert
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEY, char *keyfile);
-.fi
-.SH DESCRIPTION
-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.
-
-(Windows, iOS and Mac OS X) This option is ignored by Secure Transport and
-Schannel SSL backends because they expect the private key to be already present
-in the key-chain or PKCS#12 file containing the certificate.
-
-The application does not have to keep the string around after setting this
-option.
-.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) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_SSLCERT (3),
-.BR CURLOPT_SSLKEY_BLOB (3),
-.BR CURLOPT_SSLKEYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY.md b/docs/libcurl/opts/CURLOPT_SSLKEY.md
new file mode 100644
index 000000000..292258fd7
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLKEY.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLKEY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSLCERT (3)
+ - CURLOPT_SSLKEYTYPE (3)
+ - CURLOPT_SSLKEY_BLOB (3)
+---
+
+# NAME
+
+CURLOPT_SSLKEY - private key file for TLS and SSL client cert
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEY, char *keyfile);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. The string should be
+the filename of your private key. The default format is "PEM" and can be
+changed with CURLOPT_SSLKEYTYPE(3).
+
+(Windows, iOS and Mac OS X) This option is ignored by Secure Transport and
+Schannel SSL backends because they expect the private key to be already present
+in the key-chain or PKCS#12 file containing the certificate.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3 b/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3
deleted file mode 100644
index 6cb46d104..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLKEYTYPE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSLKEYTYPE \- type of the private key file
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEYTYPE, char *type);
-.fi
-.SH DESCRIPTION
-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
-this case \fICURLOPT_SSLKEY(3)\fP is used as an identifier passed to the
-engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE(3)\fP.
-\&"DER" format key file currently does not work because of a bug in OpenSSL.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-"PEM"
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
- curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
- curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
- curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_SSLCERT (3),
-.BR CURLOPT_SSLKEY (3),
-.BR CURLOPT_PROXY_SSLKEYTYPE (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md b/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md
new file mode 100644
index 000000000..b3f114109
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLKEYTYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLKEYTYPE (3)
+ - CURLOPT_SSLCERT (3)
+ - CURLOPT_SSLKEY (3)
+---
+
+# NAME
+
+CURLOPT_SSLKEYTYPE - type of the private key file
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEYTYPE, char *type);
+~~~
+
+# DESCRIPTION
+
+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
+this case CURLOPT_SSLKEY(3) is used as an identifier passed to the engine. You
+have to set the crypto engine with CURLOPT_SSLENGINE(3). "DER" format key file
+currently does not work because of a bug in OpenSSL.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+"PEM"
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
+ curl_easy_setopt(curl, CURLOPT_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3 b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3
deleted file mode 100644
index e43461d3f..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLKEY_BLOB 3 "24 Jun 2020" libcurl libcurl
-.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 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),
-.BR CURLOPT_SSLKEY (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md
new file mode 100644
index 000000000..74425692b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md
@@ -0,0 +1,87 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLKEY_BLOB
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSLKEY (3)
+ - CURLOPT_SSLKEYTYPE (3)
+---
+
+# NAME
+
+CURLOPT_SSLKEY_BLOB - private key for client cert from memory blob
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEY_BLOB,
+ struct curl_blob *blob);
+~~~
+
+# 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 CURLOPT_SSLKEYTYPE(3).
+
+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 CURLOPT_SSLKEY(3) which instead expects a
+filename as input.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+
+extern char *certificateData; /* point to cert */
+extern size_t filesize; /* size of cert */
+
+extern char *privateKeyData; /* point to key */
+extern size_t privateKeySize; /* size of key */
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ 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");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.71.0. This option is supported by the OpenSSL backends.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSLVERSION.3 b/docs/libcurl/opts/CURLOPT_SSLVERSION.3
deleted file mode 100644
index e504c0e18..000000000
--- a/docs/libcurl/opts/CURLOPT_SSLVERSION.3
+++ /dev/null
@@ -1,121 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSLVERSION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSLVERSION \- preferred TLS/SSL version
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLVERSION, long version);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter to control which version range of SSL/TLS versions to
-use.
-
-The SSL and TLS versions have typically developed from the most insecure
-version to be more and more secure in this order through history: SSL v2,
-SSLv3, TLS v1.0, TLS v1.1, TLS v1.2 and the most recent TLS v1.3.
-
-Use one of the available defines for this purpose. The available options are:
-.RS
-.IP CURL_SSLVERSION_DEFAULT
-The default acceptable version range. The minimum acceptable version is by
-default TLS v1.0 since 7.39.0 (unless the TLS library has a stricter rule).
-.IP CURL_SSLVERSION_TLSv1
-TLS v1.0 or later
-.IP CURL_SSLVERSION_SSLv2
-SSL v2 - refused
-.IP CURL_SSLVERSION_SSLv3
-SSL v3 - refused
-.IP CURL_SSLVERSION_TLSv1_0
-TLS v1.0 or later (Added in 7.34.0)
-.IP CURL_SSLVERSION_TLSv1_1
-TLS v1.1 or later (Added in 7.34.0)
-.IP CURL_SSLVERSION_TLSv1_2
-TLS v1.2 or later (Added in 7.34.0)
-.IP CURL_SSLVERSION_TLSv1_3
-TLS v1.3 or later (Added in 7.52.0)
-.RE
-
-The maximum TLS version can be set by using \fIone\fP of the
-CURL_SSLVERSION_MAX_ macros below. It is also possible to OR \fIone\fP of the
-CURL_SSLVERSION_ macros with \fIone\fP of the CURL_SSLVERSION_MAX_ macros.
-The MAX macros are not supported for WolfSSL.
-.RS
-.IP CURL_SSLVERSION_MAX_DEFAULT
-The flag defines the maximum supported TLS version by libcurl, or the default
-value from the SSL library is used. libcurl uses a sensible default maximum,
-which was TLS v1.2 up to before 7.61.0 and is TLS v1.3 since then - assuming
-the TLS library support it. (Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_0
-The flag defines maximum supported TLS version as TLS v1.0.
-(Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_1
-The flag defines maximum supported TLS version as TLS v1.1.
-(Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_2
-The flag defines maximum supported TLS version as TLS v1.2.
-(Added in 7.54.0)
-.IP CURL_SSLVERSION_MAX_TLSv1_3
-The flag defines maximum supported TLS version as TLS v1.3.
-(Added in 7.54.0)
-.RE
-
-In versions of curl prior to 7.54 the CURL_SSLVERSION_TLS options were
-documented to allow \fIonly\fP the specified TLS version, but behavior was
-inconsistent depending on the TLS library.
-
-.SH DEFAULT
-CURL_SSLVERSION_DEFAULT
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* ask libcurl to use TLS version 1.0 or later */
- curl_easy_setopt(curl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-SSLv2 and SSLv3 are refused completely since curl 7.77.0
-
-SSLv2 is disabled by default since 7.18.1. Other SSL versions availability may
-vary depending on which backend libcurl has been built to use.
-
-SSLv3 is disabled by default since 7.39.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTP_VERSION (3),
-.BR CURLOPT_IPRESOLVE (3),
-.BR CURLOPT_PROXY_SSLVERSION (3),
-.BR CURLOPT_USE_SSL (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSLVERSION.md b/docs/libcurl/opts/CURLOPT_SSLVERSION.md
new file mode 100644
index 000000000..f64a13b5f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLVERSION.md
@@ -0,0 +1,143 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSLVERSION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTP_VERSION (3)
+ - CURLOPT_IPRESOLVE (3)
+ - CURLOPT_PROXY_SSLVERSION (3)
+ - CURLOPT_USE_SSL (3)
+---
+
+# NAME
+
+CURLOPT_SSLVERSION - preferred TLS/SSL version
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLVERSION, long version);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter to control which version range of SSL/TLS versions to
+use.
+
+The SSL and TLS versions have typically developed from the most insecure
+version to be more and more secure in this order through history: SSL v2,
+SSLv3, TLS v1.0, TLS v1.1, TLS v1.2 and the most recent TLS v1.3.
+
+Use one of the available defines for this purpose. The available options are:
+
+## CURL_SSLVERSION_DEFAULT
+
+The default acceptable version range. The minimum acceptable version is by
+default TLS v1.0 since 7.39.0 (unless the TLS library has a stricter rule).
+
+## CURL_SSLVERSION_TLSv1
+
+TLS v1.0 or later
+
+## CURL_SSLVERSION_SSLv2
+
+SSL v2 - refused
+
+## CURL_SSLVERSION_SSLv3
+
+SSL v3 - refused
+
+## CURL_SSLVERSION_TLSv1_0
+
+TLS v1.0 or later (Added in 7.34.0)
+
+## CURL_SSLVERSION_TLSv1_1
+
+TLS v1.1 or later (Added in 7.34.0)
+
+## CURL_SSLVERSION_TLSv1_2
+
+TLS v1.2 or later (Added in 7.34.0)
+
+## CURL_SSLVERSION_TLSv1_3
+
+TLS v1.3 or later (Added in 7.52.0)
+
+The maximum TLS version can be set by using *one* of the
+CURL_SSLVERSION_MAX_ macros below. It is also possible to OR *one* of the
+CURL_SSLVERSION_ macros with *one* of the CURL_SSLVERSION_MAX_ macros.
+The MAX macros are not supported for WolfSSL.
+
+## CURL_SSLVERSION_MAX_DEFAULT
+
+The flag defines the maximum supported TLS version by libcurl, or the default
+value from the SSL library is used. libcurl uses a sensible default maximum,
+which was TLS v1.2 up to before 7.61.0 and is TLS v1.3 since then - assuming
+the TLS library support it. (Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_0
+
+The flag defines maximum supported TLS version as TLS v1.0.
+(Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_1
+
+The flag defines maximum supported TLS version as TLS v1.1.
+(Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_2
+
+The flag defines maximum supported TLS version as TLS v1.2.
+(Added in 7.54.0)
+
+## CURL_SSLVERSION_MAX_TLSv1_3
+
+The flag defines maximum supported TLS version as TLS v1.3.
+(Added in 7.54.0)
+
+In versions of curl prior to 7.54 the CURL_SSLVERSION_TLS options were
+documented to allow *only* the specified TLS version, but behavior was
+inconsistent depending on the TLS library.
+
+# DEFAULT
+
+CURL_SSLVERSION_DEFAULT
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* ask libcurl to use TLS version 1.0 or later */
+ curl_easy_setopt(curl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+SSLv2 and SSLv3 are refused completely since curl 7.77.0
+
+SSLv2 is disabled by default since 7.18.1. Other SSL versions availability may
+vary depending on which backend libcurl has been built to use.
+
+SSLv3 is disabled by default since 7.39.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3
deleted file mode 100644
index 87626feba..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.3
+++ /dev/null
@@ -1,90 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_CIPHER_LIST 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_CIPHER_LIST \- ciphers to use for TLS
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CIPHER_LIST, char *list);
-.fi
-.SH DESCRIPTION
-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, \&!, \&-
-and \&+ can be used as operators.
-
-For OpenSSL and GnuTLS valid examples of cipher lists include \fBRC4-SHA\fP,
-\fBSHA1+DES\fP, \fBTLSv1\fP and \fBDEFAULT\fP. The default list is normally
-set when you compile OpenSSL.
-
-For WolfSSL, valid examples of cipher lists include \fBECDHE-RSA-RC4-SHA\fP,
-\fBAES256-SHA:AES256-SHA256\fP, etc.
-
-For BearSSL, valid examples of cipher lists include
-\fBECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256\fP, or when using IANA names
-\fBTLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\fP,
-etc.
-With BearSSL you do not add/remove ciphers. If one uses this option then all
-known ciphers are disabled and only those passed in are enabled.
-
-For Schannel, you can use this option to set algorithms but not specific cipher
-suites. Refer to the ciphers lists document for algorithms.
-
-Find more details about cipher lists on this URL:
-
- https://curl.se/docs/ssl-ciphers.html
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL, use internal default
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, "TLSv1");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.9, in 7.83.0 for BearSSL
-
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_TLS13_CIPHERS (3),
-.BR CURLOPT_SSLVERSION (3),
-.BR CURLOPT_PROXY_SSL_CIPHER_LIST (3),
-.BR CURLOPT_PROXY_TLS13_CIPHERS (3),
-.BR CURLOPT_USE_SSL (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md b/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md
new file mode 100644
index 000000000..c96c93f3e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md
@@ -0,0 +1,92 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_CIPHER_LIST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSL_CIPHER_LIST (3)
+ - CURLOPT_PROXY_TLS13_CIPHERS (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_TLS13_CIPHERS (3)
+ - CURLOPT_USE_SSL (3)
+---
+
+# NAME
+
+CURLOPT_SSL_CIPHER_LIST - ciphers to use for TLS
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CIPHER_LIST, char *list);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer, 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, !, - and
++ can be used as operators.
+
+For OpenSSL and GnuTLS valid examples of cipher lists include **RC4-SHA**,
+**SHA1+DES**, **TLSv1** and **DEFAULT**. The default list is normally set when
+you compile OpenSSL.
+
+For WolfSSL, valid examples of cipher lists include **ECDHE-RSA-RC4-SHA**,
+**AES256-SHA:AES256-SHA256**, etc.
+
+For BearSSL, valid examples of cipher lists include
+**ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256**, or when using
+IANA names
+**TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256**,
+etc. With BearSSL you do not add/remove ciphers. If one uses this option then
+all known ciphers are disabled and only those passed in are enabled.
+
+For Schannel, you can use this option to set algorithms but not specific
+cipher suites. Refer to the ciphers lists document for algorithms.
+
+Find more details about cipher lists on this URL:
+
+ https://curl.se/docs/ssl-ciphers.html
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL, use internal default
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, "TLSv1");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.9, in 7.83.0 for BearSSL
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3 b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3
deleted file mode 100644
index 5dcf059e7..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.3
+++ /dev/null
@@ -1,126 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_CTX_DATA 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_CTX_DATA \- pointer passed to SSL context callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_DATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Data \fIpointer\fP to pass to the ssl context callback set by the option
-\fICURLOPT_SSL_CTX_FUNCTION(3)\fP, this is the pointer you get as third
-parameter.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-/* OpenSSL specific */
-
-#include <openssl/ssl.h>
-#include <curl/curl.h>
-#include <stdio.h>
-
-static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
-{
- X509_STORE *store;
- X509 *cert = NULL;
- BIO *bio;
- char *mypem = parm;
- /* get a BIO */
- bio = BIO_new_mem_buf(mypem, -1);
- /* use it to read the PEM formatted certificate from memory into an
- * X509 structure that SSL can use
- */
- PEM_read_bio_X509(bio, &cert, 0, NULL);
- if(cert == NULL)
- printf("PEM_read_bio_X509 failed...\\n");
-
- /* get a pointer to the X509 certificate store (which may be empty) */
- store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
-
- /* add our certificate to this store */
- if(X509_STORE_add_cert(store, cert) == 0)
- printf("error adding certificate\\n");
-
- /* decrease reference counts */
- X509_free(cert);
- BIO_free(bio);
-
- /* all set to go */
- return CURLE_OK;
-}
-
-int main(void)
-{
- CURL * ch;
- CURLcode rv;
- char *mypem = /* example CA cert PEM - shortened */
- "-----BEGIN CERTIFICATE-----\\n"
- "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\\n"
- "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\\n"
- "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\\n"
- "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\\n"
- "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\\n"
- "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\\n"
- "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\\n"
- "-----END CERTIFICATE-----\\n";
-
- curl_global_init(CURL_GLOBAL_ALL);
- ch = curl_easy_init();
-
- curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
- curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
- curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
-
- curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
- curl_easy_setopt(ch, CURLOPT_SSL_CTX_DATA, mypem);
- rv = curl_easy_perform(ch);
- if(!rv)
- printf("*** transfer succeeded ***\\n");
- else
- printf("*** transfer failed ***\\n");
-
- curl_easy_cleanup(ch);
- curl_global_cleanup();
- return rv;
-}
-.fi
-.SH AVAILABILITY
-Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL, in 7.54.0 for mbedTLS,
-in 7.83.0 in BearSSL. Other SSL backends are not supported.
-.SH RETURN VALUE
-CURLE_OK if supported; or an error such as:
-
-CURLE_NOT_BUILT_IN - Not supported by the SSL backend
-
-CURLE_UNKNOWN_OPTION
-.SH "SEE ALSO"
-.BR CURLOPT_SSL_CTX_FUNCTION (3),
-.BR CURLOPT_SSLVERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md
new file mode 100644
index 000000000..6e328a5bd
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md
@@ -0,0 +1,124 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_CTX_DATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_SSL_CTX_FUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_SSL_CTX_DATA - pointer passed to SSL context callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_DATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Data *pointer* to pass to the ssl context callback set by the option
+CURLOPT_SSL_CTX_FUNCTION(3), this is the pointer you get as third
+parameter.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+/* OpenSSL specific */
+
+#include <openssl/ssl.h>
+#include <curl/curl.h>
+#include <stdio.h>
+
+static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
+{
+ X509_STORE *store;
+ X509 *cert = NULL;
+ BIO *bio;
+ char *mypem = parm;
+ /* get a BIO */
+ bio = BIO_new_mem_buf(mypem, -1);
+ /* use it to read the PEM formatted certificate from memory into an
+ * X509 structure that SSL can use
+ */
+ PEM_read_bio_X509(bio, &cert, 0, NULL);
+ if(!cert)
+ printf("PEM_read_bio_X509 failed...\n");
+
+ /* get a pointer to the X509 certificate store (which may be empty) */
+ store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
+
+ /* add our certificate to this store */
+ if(X509_STORE_add_cert(store, cert) == 0)
+ printf("error adding certificate\n");
+
+ /* decrease reference counts */
+ X509_free(cert);
+ BIO_free(bio);
+
+ /* all set to go */
+ return CURLE_OK;
+}
+
+int main(void)
+{
+ CURL *ch;
+ CURLcode rv;
+ char *mypem = /* example CA cert PEM - shortened */
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n"
+ "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n"
+ "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\n"
+ "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\n"
+ "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\n"
+ "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\n"
+ "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"
+ "-----END CERTIFICATE-----\n";
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ ch = curl_easy_init();
+
+ curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
+ curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
+ curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
+
+ curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
+ curl_easy_setopt(ch, CURLOPT_SSL_CTX_DATA, mypem);
+ rv = curl_easy_perform(ch);
+ if(!rv)
+ printf("*** transfer succeeded ***\n");
+ else
+ printf("*** transfer failed ***\n");
+
+ curl_easy_cleanup(ch);
+ curl_global_cleanup();
+ return rv;
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL, in 7.54.0 for mbedTLS,
+in 7.83.0 in BearSSL. Other SSL backends are not supported.
+
+# RETURN VALUE
+
+CURLE_OK if supported; or an error such as:
+
+CURLE_NOT_BUILT_IN - Not supported by the SSL backend
+
+CURLE_UNKNOWN_OPTION
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3 b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3
deleted file mode 100644
index 220f1b992..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.3
+++ /dev/null
@@ -1,168 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_CTX_FUNCTION 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_CTX_FUNCTION \- SSL context callback for OpenSSL, wolfSSL or mbedTLS
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *clientp);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_FUNCTION,
- ssl_ctx_callback);
-.SH DESCRIPTION
-This option only works for libcurl powered by OpenSSL, wolfSSL, mbedTLS or
-BearSSL. If libcurl was built against another SSL library this functionality
-is absent.
-
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl just before the initialization
-of an SSL connection after having processed all other SSL related options to
-give a last chance to an application to modify the behavior of the SSL
-initialization. The \fIssl_ctx\fP parameter is actually a pointer to the SSL
-library's \fISSL_CTX\fP for OpenSSL or wolfSSL, a pointer to
-\fImbedtls_ssl_config\fP for mbedTLS or a pointer to
-\fIbr_ssl_client_context\fP for BearSSL. If an error is returned from the
-callback no attempt to establish a connection is made and the perform
-operation returns the callback's error code. Set the \fIclientp\fP argument
-with the \fICURLOPT_SSL_CTX_DATA(3)\fP option.
-
-This function gets called on all new connections made to a server, during the
-SSL negotiation. The \fIssl_ctx\fP points to a newly initialized object each
-time, but note the pointer may be the same as from a prior call.
-
-To use this properly, a non-trivial amount of knowledge of your SSL library is
-necessary. For example, you can use this function to call library-specific
-callbacks to add additional validation code for certificates, and even to
-change the actual URI of an HTTPS request.
-
-For OpenSSL, asynchronous certificate verification via
-\fISSL_set_retry_verify\fP is supported. (Added in 8.3.0)
-
-WARNING: The \fICURLOPT_SSL_CTX_FUNCTION(3)\fP callback allows the application
-to reach in and modify SSL details in the connection without libcurl itself
-knowing anything about it, which then subsequently can lead to libcurl
-unknowingly reusing SSL connections with different properties. To remedy this
-you may set \fICURLOPT_FORBID_REUSE(3)\fP from the callback function.
-
-WARNING: If you are using DNS-over-HTTPS (DoH) via \fICURLOPT_DOH_URL(3)\fP
-then this callback is also called for those transfers and the curl handle is
-set to an internal handle. \fBThis behavior is subject to change.\fP We
-recommend before performing your transfer set \fICURLOPT_PRIVATE(3)\fP on your
-curl handle so you can identify it in the context callback. If you have a
-reason to modify DoH SSL context please let us know on the curl-library
-mailing list because we are considering removing this capability.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-/* OpenSSL specific */
-
-#include <openssl/ssl.h>
-#include <curl/curl.h>
-#include <stdio.h>
-
-static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
-{
- X509_STORE *store;
- X509 *cert = NULL;
- BIO *bio;
- char *mypem = parm;
- /* get a BIO */
- bio = BIO_new_mem_buf(mypem, -1);
- /* use it to read the PEM formatted certificate from memory into an
- * X509 structure that SSL can use
- */
- PEM_read_bio_X509(bio, &cert, 0, NULL);
- if(cert == NULL)
- printf("PEM_read_bio_X509 failed...\\n");
-
- /* get a pointer to the X509 certificate store (which may be empty) */
- store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
-
- /* add our certificate to this store */
- if(X509_STORE_add_cert(store, cert) == 0)
- printf("error adding certificate\\n");
-
- /* decrease reference counts */
- X509_free(cert);
- BIO_free(bio);
-
- /* all set to go */
- return CURLE_OK;
-}
-
-int main(void)
-{
- CURL * ch;
- CURLcode rv;
- char *mypem = /* example CA cert PEM - shortened */
- "-----BEGIN CERTIFICATE-----\\n"
- "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\\n"
- "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\\n"
- "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\\n"
- "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\\n"
- "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\\n"
- "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\\n"
- "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\\n"
- "-----END CERTIFICATE-----\\n";
-
- curl_global_init(CURL_GLOBAL_ALL);
- ch = curl_easy_init();
-
- curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
- curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
- curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
-
- curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
- curl_easy_setopt(ch, CURLOPT_SSL_CTX_DATA, mypem);
- rv = curl_easy_perform(ch);
- if(!rv)
- printf("*** transfer succeeded ***\\n");
- else
- printf("*** transfer failed ***\\n");
-
- curl_easy_cleanup(ch);
- curl_global_cleanup();
- return rv;
-}
-.fi
-.SH AVAILABILITY
-Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL, in 7.54.0 for mbedTLS,
-in 7.83.0 in BearSSL. Other SSL backends are not supported.
-.SH RETURN VALUE
-CURLE_OK if supported; or an error such as:
-
-CURLE_NOT_BUILT_IN - Not supported by the SSL backend
-
-CURLE_UNKNOWN_OPTION
-.SH "SEE ALSO"
-.BR CURLOPT_SSL_CTX_DATA (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md
new file mode 100644
index 000000000..ae8b8bbad
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md
@@ -0,0 +1,167 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_CTX_FUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSL_CTX_DATA (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_SSL_CTX_FUNCTION - SSL context callback for OpenSSL, wolfSSL or mbedTLS
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode ssl_ctx_callback(CURL *curl, void *ssl_ctx, void *clientp);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_FUNCTION,
+ ssl_ctx_callback);
+~~~
+
+# DESCRIPTION
+
+This option only works for libcurl powered by OpenSSL, wolfSSL, mbedTLS or
+BearSSL. If libcurl was built against another SSL library this functionality
+is absent.
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl just before the initialization
+of an SSL connection after having processed all other SSL related options to
+give a last chance to an application to modify the behavior of the SSL
+initialization. The *ssl_ctx* parameter is actually a pointer to the SSL
+library's *SSL_CTX* for OpenSSL or wolfSSL, a pointer to
+*mbedtls_ssl_config* for mbedTLS or a pointer to
+*br_ssl_client_context* for BearSSL. If an error is returned from the
+callback no attempt to establish a connection is made and the perform
+operation returns the callback's error code. Set the *clientp* argument
+with the CURLOPT_SSL_CTX_DATA(3) option.
+
+This function gets called on all new connections made to a server, during the
+SSL negotiation. The *ssl_ctx* points to a newly initialized object each
+time, but note the pointer may be the same as from a prior call.
+
+To use this properly, a non-trivial amount of knowledge of your SSL library is
+necessary. For example, you can use this function to call library-specific
+callbacks to add additional validation code for certificates, and even to
+change the actual URI of an HTTPS request.
+
+For OpenSSL, asynchronous certificate verification via
+*SSL_set_retry_verify* is supported. (Added in 8.3.0)
+
+WARNING: The CURLOPT_SSL_CTX_FUNCTION(3) callback allows the application
+to reach in and modify SSL details in the connection without libcurl itself
+knowing anything about it, which then subsequently can lead to libcurl
+unknowingly reusing SSL connections with different properties. To remedy this
+you may set CURLOPT_FORBID_REUSE(3) from the callback function.
+
+WARNING: If you are using DNS-over-HTTPS (DoH) via CURLOPT_DOH_URL(3)
+then this callback is also called for those transfers and the curl handle is
+set to an internal handle. **This behavior is subject to change.** We
+recommend before performing your transfer set CURLOPT_PRIVATE(3) on your
+curl handle so you can identify it in the context callback. If you have a
+reason to modify DoH SSL context please let us know on the curl-library
+mailing list because we are considering removing this capability.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+/* OpenSSL specific */
+
+#include <openssl/ssl.h>
+#include <curl/curl.h>
+#include <stdio.h>
+
+static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
+{
+ X509_STORE *store;
+ X509 *cert = NULL;
+ BIO *bio;
+ char *mypem = parm;
+ /* get a BIO */
+ bio = BIO_new_mem_buf(mypem, -1);
+ /* use it to read the PEM formatted certificate from memory into an
+ * X509 structure that SSL can use
+ */
+ PEM_read_bio_X509(bio, &cert, 0, NULL);
+ if(!cert)
+ printf("PEM_read_bio_X509 failed...\n");
+
+ /* get a pointer to the X509 certificate store (which may be empty) */
+ store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
+
+ /* add our certificate to this store */
+ if(X509_STORE_add_cert(store, cert) == 0)
+ printf("error adding certificate\n");
+
+ /* decrease reference counts */
+ X509_free(cert);
+ BIO_free(bio);
+
+ /* all set to go */
+ return CURLE_OK;
+}
+
+int main(void)
+{
+ CURL *ch;
+ CURLcode rv;
+ char *mypem = /* example CA cert PEM - shortened */
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290\n"
+ "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB\n"
+ "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA\n"
+ "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO\n"
+ "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk\n"
+ "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW\n"
+ "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"
+ "-----END CERTIFICATE-----\n";
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ ch = curl_easy_init();
+
+ curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
+ curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
+ curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/");
+
+ curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
+ curl_easy_setopt(ch, CURLOPT_SSL_CTX_DATA, mypem);
+ rv = curl_easy_perform(ch);
+ if(!rv)
+ printf("*** transfer succeeded ***\n");
+ else
+ printf("*** transfer failed ***\n");
+
+ curl_easy_cleanup(ch);
+ curl_global_cleanup();
+ return rv;
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL, in 7.54.0 for mbedTLS,
+in 7.83.0 in BearSSL. Other SSL backends are not supported.
+
+# RETURN VALUE
+
+CURLE_OK if supported; or an error such as:
+
+CURLE_NOT_BUILT_IN - Not supported by the SSL backend
+
+CURLE_UNKNOWN_OPTION
diff --git a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3 b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3
deleted file mode 100644
index fab363226..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_EC_CURVES 3 "29 Aug 2020" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_EC_CURVES \- key exchange curves
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_EC_CURVES, char *alg_list);
-.fi
-.SH DESCRIPTION
-Pass a string as parameter with a colon delimited list of (EC) algorithms. This
-option defines the client's key exchange algorithms in the SSL handshake (if
-the SSL backend libcurl is built to use supports it).
-.SH DEFAULT
-"", embedded in SSL backend
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSL_EC_CURVES, "X25519:P-521");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.73.0. Supported by the OpenSSL backend.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSL_OPTIONS (3),
-.BR CURLOPT_SSL_CIPHER_LIST (3),
-.BR CURLOPT_TLS13_CIPHERS (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md
new file mode 100644
index 000000000..adfaae34c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md
@@ -0,0 +1,61 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_EC_CURVES
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSL_CIPHER_LIST (3)
+ - CURLOPT_SSL_OPTIONS (3)
+ - CURLOPT_TLS13_CIPHERS (3)
+---
+
+# NAME
+
+CURLOPT_SSL_EC_CURVES - key exchange curves
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_EC_CURVES, char *alg_list);
+~~~
+
+# DESCRIPTION
+
+Pass a string as parameter with a colon delimited list of (EC) algorithms. This
+option defines the client's key exchange algorithms in the SSL handshake (if
+the SSL backend libcurl is built to use supports it).
+
+# DEFAULT
+
+"", embedded in SSL backend
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSL_EC_CURVES, "X25519:P-521");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.73.0. Supported by the OpenSSL backend.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3 b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3
deleted file mode 100644
index 748cdb746..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.3
+++ /dev/null
@@ -1,58 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_ENABLE_ALPN 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_ENABLE_ALPN \- Application Layer Protocol Negotiation
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_ALPN, long npn);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter, 0 or 1 where 1 is for enable and 0 for disable. This
-option enables/disables ALPN in the SSL handshake (if the SSL backend libcurl
-is built to use supports it), which can be used to negotiate http2.
-.SH DEFAULT
-1, enabled
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.36.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSL_ENABLE_NPN (3),
-.BR CURLOPT_SSL_OPTIONS (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md
new file mode 100644
index 000000000..e1b456a06
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md
@@ -0,0 +1,60 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_ENABLE_ALPN
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSL_ENABLE_NPN (3)
+ - CURLOPT_SSL_OPTIONS (3)
+---
+
+# NAME
+
+CURLOPT_SSL_ENABLE_ALPN - Application Layer Protocol Negotiation
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_ALPN, long npn);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter, 0 or 1 where 1 is for enable and 0 for disable. This
+option enables/disables ALPN in the SSL handshake (if the SSL backend libcurl
+is built to use supports it), which can be used to negotiate http2.
+
+# DEFAULT
+
+1, enabled
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.36.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3 b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3
deleted file mode 100644
index 04286c02c..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.3
+++ /dev/null
@@ -1,60 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_ENABLE_NPN 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_ENABLE_NPN \- use NPN
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_NPN, long npn);
-.fi
-.SH DESCRIPTION
-Deprecated in 7.86.0. Setting this option has no function.
-
-Pass a long as parameter, 0 or 1 where 1 is for enable and 0 for disable. This
-option enables/disables NPN in the SSL handshake (if the SSL backend libcurl
-is built to use supports it), which can be used to negotiate http2.
-.SH DEFAULT
-1, enabled
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.36.0. Deprecated in 7.86.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSL_ENABLE_ALPN (3),
-.BR CURLOPT_SSL_OPTIONS (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md
new file mode 100644
index 000000000..36221cabd
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_ENABLE_NPN
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSL_ENABLE_ALPN (3)
+ - CURLOPT_SSL_OPTIONS (3)
+---
+
+# NAME
+
+CURLOPT_SSL_ENABLE_NPN - use NPN
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_ENABLE_NPN, long npn);
+~~~
+
+# DESCRIPTION
+
+Deprecated in 7.86.0. Setting this option has no function.
+
+Pass a long as parameter, 0 or 1 where 1 is for enable and 0 for disable. This
+option enables/disables NPN in the SSL handshake (if the SSL backend libcurl
+is built to use supports it), which can be used to negotiate http2.
+
+# DEFAULT
+
+1, enabled
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 1L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.36.0. Deprecated in 7.86.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3 b/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3
deleted file mode 100644
index 4d3339e53..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3
+++ /dev/null
@@ -1,61 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_FALSESTART 3 "14 Feb 2015" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_FALSESTART \- TLS false start
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_FALSESTART, long enable);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter set to 1L to enable or 0 to disable.
-
-This option determines whether libcurl should use false start during the TLS
-handshake. False start is a mode where a TLS client starts sending application
-data before verifying the server's Finished message, thus saving a round trip
-when performing a full handshake.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.42.0. This option is currently only supported by the Secure
-Transport (on iOS 7.0 or later, or OS X 10.9 or later) TLS backend.
-.SH RETURN VALUE
-Returns CURLE_OK if false start is supported by the SSL backend, otherwise
-returns CURLE_NOT_BUILT_IN.
-.SH SEE ALSO
-.BR CURLOPT_TCP_FASTOPEN "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.md b/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.md
new file mode 100644
index 000000000..084728c70
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_FALSESTART
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TCP_FASTOPEN (3)
+---
+
+# NAME
+
+CURLOPT_SSL_FALSESTART - TLS false start
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_FALSESTART, long enable);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter set to 1L to enable or 0 to disable.
+
+This option determines whether libcurl should use false start during the TLS
+handshake. False start is a mode where a TLS client starts sending application
+data before verifying the server's Finished message, thus saving a round trip
+when performing a full handshake.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.42.0. This option is currently only supported by the Secure
+Transport (on iOS 7.0 or later, or OS X 10.9 or later) TLS backend.
+
+# RETURN VALUE
+
+Returns CURLE_OK if false start is supported by the SSL backend, otherwise
+returns CURLE_NOT_BUILT_IN.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
deleted file mode 100644
index fc6823875..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
+++ /dev/null
@@ -1,101 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_OPTIONS 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_OPTIONS \- SSL behavior options
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_OPTIONS, long bitmask);
-.fi
-.SH DESCRIPTION
-Pass a long with a bitmask to tell libcurl about specific SSL
-behaviors. Available bits:
-.IP CURLSSLOPT_ALLOW_BEAST
-Tells libcurl to not attempt to use any workarounds for a security flaw in the
-SSL3 and TLS1.0 protocols. If this option is not used or this bit is set to 0,
-the SSL layer libcurl uses may use a work-around for this flaw although it
-might cause interoperability problems with some (older) SSL implementations.
-WARNING: avoiding this work-around lessens the security, and by setting this
-option to 1 you ask for exactly that. This option is only supported for
-Secure Transport and OpenSSL.
-.IP CURLSSLOPT_NO_REVOKE
-Tells libcurl to disable certificate revocation checks for those SSL backends
-where such behavior is present. This option is only supported for Schannel
-(the native Windows SSL library), with an exception in the case of Windows'
-Untrusted Publishers block list which it seems cannot be bypassed. (Added in
-7.44.0)
-.IP CURLSSLOPT_NO_PARTIALCHAIN
-Tells libcurl to not accept "partial" certificate chains, which it otherwise
-does by default. This option is only supported for OpenSSL and fails the
-certificate verification if the chain ends with an intermediate certificate
-and not with a root cert. (Added in 7.68.0)
-.IP CURLSSLOPT_REVOKE_BEST_EFFORT
-Tells libcurl to ignore certificate revocation checks in case of missing or
-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, Linux (Debian, Ubuntu, Gentoo, Fedora,
-RHEL), macOS, Android and iOS when built to use wolfSSL (since 8.3.0) or on
-Windows when built to use OpenSSL. If you set this option and also set a CA
-certificate file or directory then during verification those certificates
-are searched in addition to the native CA store.
-(Added in 7.71.0)
-.IP CURLSSLOPT_AUTO_CLIENT_CERT
-Tell libcurl to automatically locate and use a client certificate for
-authentication, when requested by the server. This option is only supported
-for Schannel (the native Windows SSL library). Prior to 7.77.0 this was the
-default behavior in libcurl with Schannel. Since the server can request any
-certificate that supports client authentication in the OS certificate store it
-could be a privacy violation and unexpected.
-(Added in 7.77.0)
-.SH DEFAULT
-0
-.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/");
- /* weaken TLS only for use with silly servers */
- curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST |
- CURLSSLOPT_NO_REVOKE);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.25.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSL_OPTIONS (3),
-.BR CURLOPT_SSL_CIPHER_LIST (3),
-.BR CURLOPT_SSLVERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md
new file mode 100644
index 000000000..ffc62c33c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md
@@ -0,0 +1,116 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_OPTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSL_OPTIONS (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_SSL_CIPHER_LIST (3)
+---
+
+# NAME
+
+CURLOPT_SSL_OPTIONS - SSL behavior options
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_OPTIONS, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long with a bitmask to tell libcurl about specific SSL
+behaviors. Available bits:
+
+## CURLSSLOPT_ALLOW_BEAST
+
+Tells libcurl to not attempt to use any workarounds for a security flaw in the
+SSL3 and TLS1.0 protocols. If this option is not used or this bit is set to 0,
+the SSL layer libcurl uses may use a work-around for this flaw although it
+might cause interoperability problems with some (older) SSL implementations.
+WARNING: avoiding this work-around lessens the security, and by setting this
+option to 1 you ask for exactly that. This option is only supported for Secure
+Transport and OpenSSL.
+
+## CURLSSLOPT_NO_REVOKE
+
+Tells libcurl to disable certificate revocation checks for those SSL backends
+where such behavior is present. This option is only supported for Schannel
+(the native Windows SSL library), with an exception in the case of Windows'
+Untrusted Publishers block list which it seems cannot be bypassed. (Added in
+7.44.0)
+
+## CURLSSLOPT_NO_PARTIALCHAIN
+
+Tells libcurl to not accept "partial" certificate chains, which it otherwise
+does by default. This option is only supported for OpenSSL and fails the
+certificate verification if the chain ends with an intermediate certificate
+and not with a root cert. (Added in 7.68.0)
+
+## CURLSSLOPT_REVOKE_BEST_EFFORT
+
+Tells libcurl to ignore certificate revocation checks in case of missing or
+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 *CURLSSLOPT_NO_REVOKE*, the latter takes
+precedence. (Added in 7.70.0)
+
+## CURLSSLOPT_NATIVE_CA
+
+Tell libcurl to use the operating system's native CA store for certificate
+verification. If you set this option and also set a CA certificate file or
+directory then during verification those certificates are searched in addition
+to the native CA store.
+
+Works with wolfSSL on Windows, Linux (Debian, Ubuntu, Gentoo, Fedora, RHEL),
+macOS, Android and iOS (added in 8.3.0), with GnuTLS (added in 8.5.0) or on
+Windows when built to use OpenSSL (Added in 7.71.0).
+
+## CURLSSLOPT_AUTO_CLIENT_CERT
+
+Tell libcurl to automatically locate and use a client certificate for
+authentication, when requested by the server. This option is only supported
+for Schannel (the native Windows SSL library). Prior to 7.77.0 this was the
+default behavior in libcurl with Schannel. Since the server can request any
+certificate that supports client authentication in the OS certificate store it
+could be a privacy violation and unexpected.
+(Added in 7.77.0)
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* weaken TLS only for use with silly servers */
+ curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST |
+ CURLSSLOPT_NO_REVOKE);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.25.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3 b/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3
deleted file mode 100644
index 3325f3b40..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_SESSIONID_CACHE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_SESSIONID_CACHE \- use the SSL session-ID cache
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_SESSIONID_CACHE,
- long enabled);
-.SH DESCRIPTION
-Pass a long set to 0 to disable libcurl's use of SSL session-ID caching. Set
-this to 1 to enable it. By default all transfers are done using the cache
-enabled. While nothing ever should get hurt by attempting to reuse SSL
-session-IDs, there seem to be or have been broken SSL implementations in the
-wild that may require you to disable this in order for you to succeed.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-All TLS-based
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* switch off session-id use! */
- curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.16.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_DNS_CACHE_TIMEOUT (3),
-.BR CURLOPT_MAXAGE_CONN (3),
-.BR CURLOPT_MAXLIFETIME_CONN (3),
-.BR CURLOPT_SSLVERSION (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md b/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md
new file mode 100644
index 000000000..a6b3cf195
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_SESSIONID_CACHE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DNS_CACHE_TIMEOUT (3)
+ - CURLOPT_MAXAGE_CONN (3)
+ - CURLOPT_MAXLIFETIME_CONN (3)
+ - CURLOPT_SSLVERSION (3)
+---
+
+# NAME
+
+CURLOPT_SSL_SESSIONID_CACHE - use the SSL session-ID cache
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_SESSIONID_CACHE,
+ long enabled);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 0 to disable libcurl's use of SSL session-ID caching. Set
+this to 1 to enable it. By default all transfers are done using the cache
+enabled. While nothing ever should get hurt by attempting to reuse SSL
+session-IDs, there seem to be or have been broken SSL implementations in the
+wild that may require you to disable this in order for you to succeed.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+All TLS-based
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* switch off session-id use! */
+ curl_easy_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE, 0L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.16.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3 b/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3
deleted file mode 100644
index 1bff9305a..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.3
+++ /dev/null
@@ -1,112 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_VERIFYHOST 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_VERIFYHOST \- verify the certificate's name against host
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYHOST, long verify);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter specifying what to \fIverify\fP.
-
-This option determines whether libcurl verifies that the server cert is for
-the server it is known as.
-
-When negotiating TLS and SSL connections, the server sends a certificate
-indicating its identity.
-
-When \fICURLOPT_SSL_VERIFYHOST(3)\fP is 2, that certificate must indicate that
-the server is the server to which you meant to connect, or the connection
-fails. Simply put, it means it has to have the same name in the certificate as
-is in the URL you operate against.
-
-Curl considers the server the intended one when the Common Name field or a
-Subject Alternate Name field in the certificate matches the host name in the
-URL to which you told Curl to connect.
-
-If \fIverify\fP value is set to 1:
-
-In 7.28.0 and earlier: treated as a debug option of some sorts, not supported
-anymore due to frequently leading to programmer mistakes.
-
-From 7.28.1 to 7.65.3: setting it to 1 made \fIcurl_easy_setopt(3)\fP return
-an error and leaving the flag untouched.
-
-From 7.66.0: treats 1 and 2 the same.
-
-When the \fIverify\fP value is 0, the connection succeeds regardless of the
-names in the certificate. Use that ability with caution!
-
-The default value for this option is 2.
-
-This option controls checking the server's certificate's claimed identity.
-The server could be lying. To control lying, see
-\fICURLOPT_SSL_VERIFYPEER(3)\fP.
-
-WARNING: disabling verification of the certificate allows bad guys to
-man-in-the-middle the communication without you knowing it. Disabling
-verification makes the communication insecure. Just having encryption on a
-transfer is not enough as you cannot be sure that you are communicating with
-the correct end-point.
-
-When libcurl uses secure protocols it trusts responses and allows for example
-HSTS and Alt-Svc information to be stored and used subsequently. Disabling
-certificate verification can make libcurl trust and use such information from
-malicious servers.
-.SH LIMITATIONS
-Secure Transport: If \fIverify\fP value is 0, then SNI is also disabled. SNI is
-a TLS extension that sends the hostname to the server. The server may use that
-information to do such things as sending back a specific certificate for the
-hostname, or forwarding the request to a specific origin server. Some hostnames
-may be inaccessible if SNI is not sent.
-.SH DEFAULT
-2
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Set the default value: strict name check please */
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if TLS is supported, and CURLE_UNKNOWN_OPTION if not.
-
-If 1 is set as argument, \fICURLE_BAD_FUNCTION_ARGUMENT\fP is returned.
-.SH "SEE ALSO"
-.BR CURLOPT_CAINFO (3),
-.BR CURLOPT_PINNEDPUBLICKEY (3),
-.BR CURLOPT_SSL_VERIFYPEER (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.md b/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.md
new file mode 100644
index 000000000..75648a11b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_VERIFYHOST.md
@@ -0,0 +1,114 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_VERIFYHOST
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_PINNEDPUBLICKEY (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_SSL_VERIFYHOST - verify the certificate's name against host
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYHOST, long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter specifying what to *verify*.
+
+This option determines whether libcurl verifies that the server cert is for
+the server it is known as.
+
+When negotiating TLS and SSL connections, the server sends a certificate
+indicating its identity.
+
+When CURLOPT_SSL_VERIFYHOST(3) is 2, that certificate must indicate that
+the server is the server to which you meant to connect, or the connection
+fails. Simply put, it means it has to have the same name in the certificate as
+is in the URL you operate against.
+
+Curl considers the server the intended one when the Common Name field or a
+Subject Alternate Name field in the certificate matches the hostname in the
+URL to which you told Curl to connect.
+
+If *verify* value is set to 1:
+
+In 7.28.0 and earlier: treated as a debug option of some sorts, not supported
+anymore due to frequently leading to programmer mistakes.
+
+From 7.28.1 to 7.65.3: setting it to 1 made curl_easy_setopt(3) return
+an error and leaving the flag untouched.
+
+From 7.66.0: treats 1 and 2 the same.
+
+When the *verify* value is 0, the connection succeeds regardless of the
+names in the certificate. Use that ability with caution!
+
+The default value for this option is 2.
+
+This option controls checking the server's certificate's claimed identity.
+The server could be lying. To control lying, see CURLOPT_SSL_VERIFYPEER(3).
+
+WARNING: disabling verification of the certificate allows bad guys to
+man-in-the-middle the communication without you knowing it. Disabling
+verification makes the communication insecure. Just having encryption on a
+transfer is not enough as you cannot be sure that you are communicating with
+the correct end-point.
+
+When libcurl uses secure protocols it trusts responses and allows for example
+HSTS and Alt-Svc information to be stored and used subsequently. Disabling
+certificate verification can make libcurl trust and use such information from
+malicious servers.
+
+# LIMITATIONS
+
+Secure Transport: If *verify* value is 0, then SNI is also disabled. SNI is
+a TLS extension that sends the hostname to the server. The server may use that
+information to do such things as sending back a specific certificate for the
+hostname, or forwarding the request to a specific origin server. Some hostnames
+may be inaccessible if SNI is not sent.
+
+# DEFAULT
+
+2
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the default value: strict name check please */
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if TLS is supported, and CURLE_UNKNOWN_OPTION if not.
+
+If 1 is set as argument, *CURLE_BAD_FUNCTION_ARGUMENT* is returned.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3 b/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3
deleted file mode 100644
index e26233e84..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.3
+++ /dev/null
@@ -1,97 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_VERIFYPEER 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_VERIFYPEER \- verify the peer's SSL certificate
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYPEER, long verify);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter to enable or disable.
-
-This option determines whether curl verifies the authenticity of the peer's
-certificate. A value of 1 means curl verifies; 0 (zero) means it does not.
-
-When negotiating a TLS or SSL connection, the server sends a certificate
-indicating its identity. Curl verifies whether the certificate is authentic,
-i.e. that you can trust that the server is who the certificate says it is.
-This trust is based on a chain of digital signatures, rooted in certification
-authority (CA) certificates you supply. curl uses a default bundle of CA
-certificates (the path for that is determined at build time) and you can
-specify alternate certificates with the \fICURLOPT_CAINFO(3)\fP option or the
-\fICURLOPT_CAPATH(3)\fP option.
-
-When \fICURLOPT_SSL_VERIFYPEER(3)\fP is enabled, and the verification fails to
-prove that the certificate is signed by a CA, the connection fails.
-
-When this option is disabled (set to zero), the CA certificates are not loaded
-and the peer certificate verification is simply skipped.
-
-Authenticating the certificate is not enough to be sure about the server. You
-typically also want to ensure that the server is the server you mean to be
-talking to. Use \fICURLOPT_SSL_VERIFYHOST(3)\fP for that. The check that the
-host name in the certificate is valid for the host name you are connecting to
-is done independently of the \fICURLOPT_SSL_VERIFYPEER(3)\fP option.
-
-WARNING: disabling verification of the certificate allows bad guys to
-man-in-the-middle the communication without you knowing it. Disabling
-verification makes the communication insecure. Just having encryption on a
-transfer is not enough as you cannot be sure that you are communicating with
-the correct end-point.
-
-When libcurl uses secure protocols it trusts responses and allows for example
-HSTS and Alt-Svc information to be stored and used subsequently. Disabling
-certificate verification can make libcurl trust and use such information from
-malicious servers.
-.SH DEFAULT
-1 - enabled
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Set the default value: strict certificate check please */
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-If built TLS enabled.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_PROXY_SSL_VERIFYPEER (3),
-.BR CURLOPT_PROXY_SSL_VERIFYHOST (3),
-.BR CURLOPT_CAINFO (3),
-.BR CURLINFO_CAINFO (3),
-.BR CURLINFO_CAPATH (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.md b/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.md
new file mode 100644
index 000000000..c9884ceb9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_VERIFYPEER.md
@@ -0,0 +1,98 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_VERIFYPEER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_CAINFO (3)
+ - CURLINFO_CAPATH (3)
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_PROXY_SSL_VERIFYHOST (3)
+ - CURLOPT_PROXY_SSL_VERIFYPEER (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+---
+
+# NAME
+
+CURLOPT_SSL_VERIFYPEER - verify the peer's SSL certificate
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYPEER, long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter to enable or disable.
+
+This option determines whether curl verifies the authenticity of the peer's
+certificate. A value of 1 means curl verifies; 0 (zero) means it does not.
+
+When negotiating a TLS or SSL connection, the server sends a certificate
+indicating its identity. Curl verifies whether the certificate is authentic,
+i.e. that you can trust that the server is who the certificate says it is.
+This trust is based on a chain of digital signatures, rooted in certification
+authority (CA) certificates you supply. curl uses a default bundle of CA
+certificates (the path for that is determined at build time) and you can
+specify alternate certificates with the CURLOPT_CAINFO(3) option or the
+CURLOPT_CAPATH(3) option.
+
+When CURLOPT_SSL_VERIFYPEER(3) is enabled, and the verification fails to
+prove that the certificate is signed by a CA, the connection fails.
+
+When this option is disabled (set to zero), the CA certificates are not loaded
+and the peer certificate verification is simply skipped.
+
+Authenticating the certificate is not enough to be sure about the server. You
+typically also want to ensure that the server is the server you mean to be
+talking to. Use CURLOPT_SSL_VERIFYHOST(3) for that. The check that the host
+name in the certificate is valid for the hostname you are connecting to is
+done independently of the CURLOPT_SSL_VERIFYPEER(3) option.
+
+WARNING: disabling verification of the certificate allows bad guys to
+man-in-the-middle the communication without you knowing it. Disabling
+verification makes the communication insecure. Just having encryption on a
+transfer is not enough as you cannot be sure that you are communicating with
+the correct end-point.
+
+When libcurl uses secure protocols it trusts responses and allows for example
+HSTS and Alt-Svc information to be stored and used subsequently. Disabling
+certificate verification can make libcurl trust and use such information from
+malicious servers.
+
+# DEFAULT
+
+1 - enabled
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the default value: strict certificate check please */
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+If built TLS enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3 b/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3
deleted file mode 100644
index 8ae2f9b38..000000000
--- a/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SSL_VERIFYSTATUS 3 "04 Dec 2014" libcurl libcurl
-.SH NAME
-CURLOPT_SSL_VERIFYSTATUS \- verify the certificate's status
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYSTATUS, long verify);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter set to 1 to enable or 0 to disable.
-
-This option determines whether libcurl verifies the status of the server cert
-using the "Certificate Status Request" TLS extension (aka. OCSP stapling).
-
-Note that if this option is enabled but the server does not support the TLS
-extension, the verification fails.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* ask for OCSP stapling! */
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.41.0. This option is currently only supported by the OpenSSL and
-GnuTLS TLS backends.
-.SH RETURN VALUE
-Returns CURLE_OK if OCSP stapling is supported by the SSL backend, otherwise
-returns CURLE_NOT_BUILT_IN.
-.SH "SEE ALSO"
-.BR CURLOPT_SSL_VERIFYHOST (3),
-.BR CURLOPT_SSL_VERIFYPEER (3),
-.BR CURLOPT_CAINFO (3)
diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md b/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md
new file mode 100644
index 000000000..66dbd7465
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SSL_VERIFYSTATUS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CAINFO (3)
+ - CURLOPT_SSL_VERIFYHOST (3)
+ - CURLOPT_SSL_VERIFYPEER (3)
+---
+
+# NAME
+
+CURLOPT_SSL_VERIFYSTATUS - verify the certificate's status
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYSTATUS, long verify);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter set to 1 to enable or 0 to disable.
+
+This option determines whether libcurl verifies the status of the server cert
+using the "Certificate Status Request" TLS extension (aka. OCSP stapling).
+
+Note that if this option is enabled but the server does not support the TLS
+extension, the verification fails.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* ask for OCSP stapling! */
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.41.0. This option is currently only supported by the OpenSSL and
+GnuTLS TLS backends.
+
+# RETURN VALUE
+
+Returns CURLE_OK if OCSP stapling is supported by the SSL backend, otherwise
+returns CURLE_NOT_BUILT_IN.
diff --git a/docs/libcurl/opts/CURLOPT_STDERR.3 b/docs/libcurl/opts/CURLOPT_STDERR.3
deleted file mode 100644
index a1574be37..000000000
--- a/docs/libcurl/opts/CURLOPT_STDERR.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_STDERR 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_STDERR \- redirect stderr to another stream
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STDERR, FILE *stream);
-.fi
-.SH DESCRIPTION
-Pass a FILE * as parameter. Tell libcurl to use this \fIstream\fP instead of
-stderr when showing the progress meter and displaying \fICURLOPT_VERBOSE(3)\fP
-data.
-
-If you are using libcurl as a Windows DLL, this option causes an exception and
-a crash in the library since it cannot access a FILE * passed on from the
-application. A work-around is to instead use \fICURLOPT_DEBUGFUNCTION(3)\fP.
-.SH DEFAULT
-stderr
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-FILE *filep = fopen("dump", "wb");
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_STDERR, filep);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_VERBOSE (3),
-.BR CURLOPT_NOPROGRESS (3),
-.BR CURLOPT_DEBUGFUNCTION (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_STDERR.md b/docs/libcurl/opts/CURLOPT_STDERR.md
new file mode 100644
index 000000000..a20e50366
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_STDERR.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_STDERR
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_NOPROGRESS (3)
+ - CURLOPT_VERBOSE (3)
+---
+
+# NAME
+
+CURLOPT_STDERR - redirect stderr to another stream
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STDERR, FILE *stream);
+~~~
+
+# DESCRIPTION
+
+Pass a FILE * as parameter. Tell libcurl to use this *stream* instead of
+stderr when showing the progress meter and displaying CURLOPT_VERBOSE(3)
+data.
+
+If you are using libcurl as a Windows DLL, this option causes an exception and
+a crash in the library since it cannot access a FILE * passed on from the
+application. A work-around is to instead use CURLOPT_DEBUGFUNCTION(3).
+
+# DEFAULT
+
+stderr
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ FILE *filep = fopen("dump", "wb");
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_STDERR, filep);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3 b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3
deleted file mode 100644
index 9f8e5308b..000000000
--- a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_STREAM_DEPENDS 3 "13 Sep 2015" libcurl libcurl
-.SH NAME
-CURLOPT_STREAM_DEPENDS \- stream this transfer depends on
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS,
- CURL *dephandle);
-.fi
-.SH DESCRIPTION
-Pass a CURL * pointer in \fIdephandle\fP to identify the stream within the
-same connection that this stream is depending upon. This option clears the
-exclusive bit and is mutually exclusive to the
-\fICURLOPT_STREAM_DEPENDS_E(3)\fP option.
-
-The spec says "Including a dependency expresses a preference to allocate
-resources to the identified stream rather than to the dependent stream."
-
-This option can be set during transfer.
-
-\fIdephandle\fP must not be the same as \fIhandle\fP, that makes this function
-return an error. It must be another easy handle, and it also needs to be a
-handle of a transfer that is about to be sent over the same HTTP/2 connection
-for this option to have an actual effect.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP/2
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-CURL *curl2 = curl_easy_init(); /* a second handle */
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/one");
-
- /* the second depends on the first */
- curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/two");
- curl_easy_setopt(curl2, CURLOPT_STREAM_DEPENDS, curl);
-
- /* then add both to a multi handle and transfer them! */
-}
-.fi
-.SH AVAILABILITY
-Added in 7.46.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLOPT_HTTP_VERSION (3),
-.BR CURLOPT_STREAM_DEPENDS_E (3),
-.BR CURLOPT_STREAM_WEIGHT (3)
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md
new file mode 100644
index 000000000..ba2489a30
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_STREAM_DEPENDS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PIPELINING (3)
+ - CURLOPT_HTTP_VERSION (3)
+ - CURLOPT_STREAM_DEPENDS_E (3)
+ - CURLOPT_STREAM_WEIGHT (3)
+---
+
+# NAME
+
+CURLOPT_STREAM_DEPENDS - stream this transfer depends on
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS,
+ CURL *dephandle);
+~~~
+
+# DESCRIPTION
+
+Pass a CURL pointer in *dephandle* to identify the stream within the same
+connection that this stream is depending upon. This option clears the
+exclusive bit and is mutually exclusive to the CURLOPT_STREAM_DEPENDS_E(3)
+option.
+
+The spec says "Including a dependency expresses a preference to allocate
+resources to the identified stream rather than to the dependent stream."
+
+This option can be set during transfer.
+
+*dephandle* must not be the same as *handle*, that makes this function return
+an error. It must be another easy handle, and it also needs to be a handle of
+a transfer that is about to be sent over the same HTTP/2 connection for this
+option to have an actual effect.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP/2
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ CURL *curl2 = curl_easy_init(); /* a second handle */
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/one");
+
+ /* the second depends on the first */
+ curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/two");
+ curl_easy_setopt(curl2, CURLOPT_STREAM_DEPENDS, curl);
+
+ /* then add both to a multi handle and transfer them! */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.46.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3 b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3
deleted file mode 100644
index c8b4cc13c..000000000
--- a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_STREAM_DEPENDS_E 3 "13 Sep 2015" libcurl libcurl
-.SH NAME
-CURLOPT_STREAM_DEPENDS_E \- stream this transfer depends on exclusively
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS_E,
- CURL *dephandle);
-.fi
-.SH DESCRIPTION
-Pass a CURL * pointer in \fIdephandle\fP to identify the stream within the
-same connection that this stream is depending upon exclusively. That means it
-depends on it and sets the Exclusive bit.
-
-The spec says "Including a dependency expresses a preference to allocate
-resources to the identified stream rather than to the dependent stream."
-
-Setting a dependency with the exclusive flag for a reprioritized stream causes
-all the dependencies of the new parent stream to become dependent on the
-reprioritized stream.
-
-This option can be set during transfer.
-
-\fIdephandle\fP must not be the same as \fIhandle\fP, that makes this function
-return an error. It must be another easy handle, and it also needs to be a
-handle of a transfer that is about to be sent over the same HTTP/2 connection
-for this option to have an actual effect.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP/2
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-CURL *curl2 = curl_easy_init(); /* a second handle */
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/one");
-
- /* the second depends on the first */
- curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/two");
- curl_easy_setopt(curl2, CURLOPT_STREAM_DEPENDS_E, curl);
-
- /* then add both to a multi handle and transfer them! */
-}
-.fi
-.SH AVAILABILITY
-Added in 7.46.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLOPT_HTTP_VERSION (3),
-.BR CURLOPT_STREAM_DEPENDS (3),
-.BR CURLOPT_STREAM_WEIGHT (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md
new file mode 100644
index 000000000..e8dbc113f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_STREAM_DEPENDS_E.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_STREAM_DEPENDS_E
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PIPELINING (3)
+ - CURLOPT_HTTP_VERSION (3)
+ - CURLOPT_STREAM_DEPENDS (3)
+ - CURLOPT_STREAM_WEIGHT (3)
+---
+
+# NAME
+
+CURLOPT_STREAM_DEPENDS_E - stream this transfer depends on exclusively
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_DEPENDS_E,
+ CURL *dephandle);
+~~~
+
+# DESCRIPTION
+
+Pass a CURL pointer in *dephandle* to identify the stream within the same
+connection that this stream is depending upon exclusively. That means it
+depends on it and sets the Exclusive bit.
+
+The spec says "Including a dependency expresses a preference to allocate
+resources to the identified stream rather than to the dependent stream."
+
+Setting a dependency with the exclusive flag for a reprioritized stream causes
+all the dependencies of the new parent stream to become dependent on the
+reprioritized stream.
+
+This option can be set during transfer.
+
+*dephandle* must not be the same as *handle*, that makes this function return
+an error. It must be another easy handle, and it also needs to be a handle of
+a transfer that is about to be sent over the same HTTP/2 connection for this
+option to have an actual effect.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP/2
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ CURL *curl2 = curl_easy_init(); /* a second handle */
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/one");
+
+ /* the second depends on the first */
+ curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/two");
+ curl_easy_setopt(curl2, CURLOPT_STREAM_DEPENDS_E, curl);
+
+ /* then add both to a multi handle and transfer them! */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.46.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3 b/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3
deleted file mode 100644
index 9b3997576..000000000
--- a/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_STREAM_WEIGHT 3 "13 Sep 2015" libcurl libcurl
-.SH NAME
-CURLOPT_STREAM_WEIGHT \- numerical stream weight
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_WEIGHT, long weight);
-.fi
-.SH DESCRIPTION
-Set the long \fIweight\fP to a number between 1 and 256.
-
-When using HTTP/2, this option sets the individual weight for this particular
-stream used by the easy \fIhandle\fP. Setting and using weights only makes
-sense and is only usable when doing multiple streams over the same
-connections, which thus implies that you use \fICURLMOPT_PIPELINING(3)\fP.
-
-This option can be set during transfer and causes the updated weight info get
-sent to the server the next time an HTTP/2 frame is sent to the server.
-
-See section 5.3 of RFC 7540 for protocol details.
-
-Streams with the same parent should be allocated resources proportionally
-based on their weight. So if you have two streams going, stream A with weight
-16 and stream B with weight 32, stream B gets two thirds (32/48) of the
-available bandwidth (assuming the server can send off the data equally for
-both streams).
-.SH DEFAULT
-If nothing is set, the HTTP/2 protocol itself uses its own default which is
-16.
-.SH PROTOCOLS
-HTTP/2
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-CURL *curl2 = curl_easy_init(); /* a second handle */
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/one");
- curl_easy_setopt(curl, CURLOPT_STREAM_WEIGHT, 10L);
-
- /* the second has twice the weight */
- curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/two");
- curl_easy_setopt(curl2, CURLOPT_STREAM_WEIGHT, 20L);
-
- /* then add both to a multi handle and transfer them! */
-}
-.fi
-.SH AVAILABILITY
-Added in 7.46.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLMOPT_PIPELINING (3),
-.BR CURLOPT_PIPEWAIT (3),
-.BR CURLOPT_STREAM_DEPENDS (3),
-.BR CURLOPT_STREAM_DEPENDS_E (3)
diff --git a/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.md b/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.md
new file mode 100644
index 000000000..914a4263d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_STREAM_WEIGHT.md
@@ -0,0 +1,81 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_STREAM_WEIGHT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLMOPT_PIPELINING (3)
+ - CURLOPT_PIPEWAIT (3)
+ - CURLOPT_STREAM_DEPENDS (3)
+ - CURLOPT_STREAM_DEPENDS_E (3)
+---
+
+# NAME
+
+CURLOPT_STREAM_WEIGHT - numerical stream weight
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_STREAM_WEIGHT, long weight);
+~~~
+
+# DESCRIPTION
+
+Set the long *weight* to a number between 1 and 256.
+
+When using HTTP/2, this option sets the individual weight for this particular
+stream used by the easy *handle*. Setting and using weights only makes
+sense and is only usable when doing multiple streams over the same
+connections, which thus implies that you use CURLMOPT_PIPELINING(3).
+
+This option can be set during transfer and causes the updated weight info get
+sent to the server the next time an HTTP/2 frame is sent to the server.
+
+See section 5.3 of RFC 7540 for protocol details.
+
+Streams with the same parent should be allocated resources proportionally
+based on their weight. If you have two streams going, stream A with weight 16
+and stream B with weight 32, stream B gets two thirds (32/48) of the available
+bandwidth (assuming the server can send off the data equally for both
+streams).
+
+# DEFAULT
+
+If nothing is set, the HTTP/2 protocol itself uses its own default which is
+16.
+
+# PROTOCOLS
+
+HTTP/2
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ CURL *curl2 = curl_easy_init(); /* a second handle */
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/one");
+ curl_easy_setopt(curl, CURLOPT_STREAM_WEIGHT, 10L);
+
+ /* the second has twice the weight */
+ curl_easy_setopt(curl2, CURLOPT_URL, "https://example.com/two");
+ curl_easy_setopt(curl2, CURLOPT_STREAM_WEIGHT, 20L);
+
+ /* then add both to a multi handle and transfer them! */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.46.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3 b/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3
deleted file mode 100644
index a47944d11..000000000
--- a/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.3
+++ /dev/null
@@ -1,98 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_SUPPRESS_CONNECT_HEADERS 3 "13 February 2017" libcurl libcurl
-.SH NAME
-CURLOPT_SUPPRESS_CONNECT_HEADERS \- suppress proxy CONNECT response headers from user callbacks
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SUPPRESS_CONNECT_HEADERS, long onoff);
-.fi
-.SH DESCRIPTION
-When \fICURLOPT_HTTPPROXYTUNNEL(3)\fP is used and a CONNECT request is made,
-suppress proxy CONNECT response headers from the user callback functions
-\fICURLOPT_HEADERFUNCTION(3)\fP and \fICURLOPT_WRITEFUNCTION(3)\fP.
-
-Proxy CONNECT response headers can complicate header processing since it's
-essentially a separate set of headers. You can enable this option to suppress
-those headers.
-
-For example let's assume an HTTPS URL is to be retrieved via CONNECT. On
-success there would normally be two sets of headers, and each header line sent
-to the header function and/or the write function. The data given to the
-callbacks would look like this:
-
-.nf
-HTTP/1.1 200 Connection established
-{headers}...
-
-HTTP/1.1 200 OK
-Content-Type: application/json
-{headers}...
-
-{body}...
-.fi
-
-However by enabling this option the CONNECT response headers are suppressed, so
-the data given to the callbacks would look like this:
-
-.nf
-HTTP/1.1 200 OK
-Content-Type: application/json
-{headers}...
-
-{body}...
-.fi
-
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
- curl_easy_setopt(curl, CURLOPT_PROXY, "http://foo:3128");
- curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
- curl_easy_setopt(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS, 1L);
-
- curl_easy_perform(curl);
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.54.0
-.SH RETURN VALUE
-CURLE_OK or an error such as CURLE_UNKNOWN_OPTION.
-.SH "SEE ALSO"
-.BR CURLOPT_HEADER (3),
-.BR CURLOPT_PROXY (3),
-.BR CURLOPT_HTTPPROXYTUNNEL (3)
diff --git a/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md b/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md
new file mode 100644
index 000000000..730192585
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md
@@ -0,0 +1,103 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_SUPPRESS_CONNECT_HEADERS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADER (3)
+ - CURLOPT_HTTPPROXYTUNNEL (3)
+ - CURLOPT_PROXY (3)
+---
+
+# NAME
+
+CURLOPT_SUPPRESS_CONNECT_HEADERS - suppress proxy CONNECT response headers
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SUPPRESS_CONNECT_HEADERS, long onoff);
+~~~
+
+# DESCRIPTION
+
+When CURLOPT_HTTPPROXYTUNNEL(3) is used and a CONNECT request is made,
+suppress proxy CONNECT response headers from the user callback functions
+CURLOPT_HEADERFUNCTION(3) and CURLOPT_WRITEFUNCTION(3).
+
+Proxy CONNECT response headers can complicate header processing since it is
+essentially a separate set of headers. You can enable this option to suppress
+those headers.
+
+For example let's assume an HTTPS URL is to be retrieved via CONNECT. On
+success there would normally be two sets of headers, and each header line sent
+to the header function and/or the write function. The data given to the
+callbacks would look like this:
+
+~~~c
+HTTP/1.1 200 Connection established
+{headers}
+...
+
+HTTP/1.1 200 OK
+Content-Type: application/json
+{headers}
+...
+
+{body}
+...
+~~~
+
+However by enabling this option the CONNECT response headers are suppressed,
+so the data given to the callbacks would look like this:
+
+~~~c
+HTTP/1.1 200 OK
+Content-Type: application/json
+{headers}
+...
+
+{body}
+...
+~~~
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
+ curl_easy_setopt(curl, CURLOPT_PROXY, "http://foo:3128");
+ curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
+ curl_easy_setopt(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS, 1L);
+
+ curl_easy_perform(curl);
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.54.0
+
+# RETURN VALUE
+
+CURLE_OK or an error such as CURLE_UNKNOWN_OPTION.
diff --git a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3 b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
deleted file mode 100644
index 06da3bf4c..000000000
--- a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TCP_FASTOPEN 3 "16 Feb 2016" libcurl libcurl
-.SH NAME
-CURLOPT_TCP_FASTOPEN \- TCP Fast Open
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_FASTOPEN, long enable);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter set to 1L to enable or 0 to disable.
-
-TCP Fast Open (RFC 7413) is a mechanism that allows data to be carried in the
-SYN and SYN-ACK packets and consumed by the receiving end during the initial
-connection handshake, saving up to one full round-trip time (RTT).
-
-Beware: the TLS session cache does not work when TCP Fast Open is enabled. TCP
-Fast Open is also known to be problematic on or across certain networks.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L);
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.49.0. This option is currently only supported on Linux and macOS
-10.11 or later.
-.SH RETURN VALUE
-Returns CURLE_OK if fast open is supported by the operating system, otherwise
-returns CURLE_NOT_BUILT_IN.
-.SH SEE ALSO
-.BR CURLOPT_SSL_FALSESTART "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md
new file mode 100644
index 000000000..4db103b4b
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TCP_FASTOPEN
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_SSL_FALSESTART (3)
+---
+
+# NAME
+
+CURLOPT_TCP_FASTOPEN - TCP Fast Open
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_FASTOPEN, long enable);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter set to 1L to enable or 0 to disable.
+
+TCP Fast Open (RFC 7413) is a mechanism that allows data to be carried in the
+SYN and SYN-ACK packets and consumed by the receiving end during the initial
+connection handshake, saving up to one full round-trip time (RTT).
+
+Beware: the TLS session cache does not work when TCP Fast Open is enabled. TCP
+Fast Open is also known to be problematic on or across certain networks.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.49.0. This option is currently only supported on Linux and macOS
+10.11 or later.
+
+# RETURN VALUE
+
+Returns CURLE_OK if fast open is supported by the operating system, otherwise
+returns CURLE_NOT_BUILT_IN.
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3 b/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3
deleted file mode 100644
index de7a4ce7d..000000000
--- a/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TCP_KEEPALIVE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TCP_KEEPALIVE \- TCP keep-alive probing
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPALIVE, long probe);
-.fi
-.SH DESCRIPTION
-Pass a long. If set to 1, TCP keepalive probes are used. The delay and
-frequency of these probes can be controlled by the
-\fICURLOPT_TCP_KEEPIDLE(3)\fP and \fICURLOPT_TCP_KEEPINTVL(3)\fP options,
-provided the operating system supports them. Set to 0 (default behavior) to
-disable keepalive probes
-.SH DEFAULT
-0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* enable TCP keep-alive for this transfer */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
-
- /* keep-alive idle time to 120 seconds */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
-
- /* interval time between keep-alive probes: 60 seconds */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.25.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_TCP_KEEPIDLE (3),
-.BR CURLOPT_TCP_KEEPINTVL (3),
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_MAX_RECV_SPEED_LARGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md b/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md
new file mode 100644
index 000000000..090431993
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TCP_KEEPALIVE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_MAX_RECV_SPEED_LARGE (3)
+ - CURLOPT_TCP_KEEPIDLE (3)
+ - CURLOPT_TCP_KEEPINTVL (3)
+---
+
+# NAME
+
+CURLOPT_TCP_KEEPALIVE - TCP keep-alive probing
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPALIVE, long probe);
+~~~
+
+# DESCRIPTION
+
+Pass a long. If set to 1, TCP keepalive probes are used. The delay and
+frequency of these probes can be controlled by the
+CURLOPT_TCP_KEEPIDLE(3) and CURLOPT_TCP_KEEPINTVL(3) options,
+provided the operating system supports them. Set to 0 (default behavior) to
+disable keepalive probes
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* enable TCP keep-alive for this transfer */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
+
+ /* keep-alive idle time to 120 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
+
+ /* interval time between keep-alive probes: 60 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.25.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3 b/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3
deleted file mode 100644
index b99ecdbd2..000000000
--- a/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TCP_KEEPIDLE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TCP_KEEPIDLE \- TCP keep-alive idle time wait
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPIDLE, long delay);
-.fi
-.SH DESCRIPTION
-Pass a long. Sets the \fIdelay\fP, in seconds, to wait while the connection is
-idle before sending keepalive probes. Not all operating systems support this
-option.
-
-The maximum value this accepts is 2147483648. Any larger value is capped to
-this amount.
-.SH DEFAULT
-60
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* enable TCP keep-alive for this transfer */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
-
- /* set keep-alive idle time to 120 seconds */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
-
- /* interval time between keep-alive probes: 60 seconds */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.25.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_TCP_KEEPALIVE (3),
-.BR CURLOPT_TCP_KEEPINTVL (3)
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md b/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md
new file mode 100644
index 000000000..d8418ffb2
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TCP_KEEPIDLE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TCP_KEEPALIVE (3)
+ - CURLOPT_TCP_KEEPINTVL (3)
+---
+
+# NAME
+
+CURLOPT_TCP_KEEPIDLE - TCP keep-alive idle time wait
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPIDLE, long delay);
+~~~
+
+# DESCRIPTION
+
+Pass a long. Sets the *delay*, in seconds, to wait while the connection is
+idle before sending keepalive probes. Not all operating systems support this
+option.
+
+The maximum value this accepts is 2147483648. Any larger value is capped to
+this amount.
+
+# DEFAULT
+
+60
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* enable TCP keep-alive for this transfer */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
+
+ /* set keep-alive idle time to 120 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
+
+ /* interval time between keep-alive probes: 60 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.25.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3 b/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3
deleted file mode 100644
index 86cc83e7e..000000000
--- a/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TCP_KEEPINTVL 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TCP_KEEPINTVL \- TCP keep-alive interval
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPINTVL, long interval);
-.fi
-.SH DESCRIPTION
-Pass a long. Sets the interval, in seconds, to wait between sending keepalive
-probes. Not all operating systems support this option. (Added in 7.25.0)
-
-The maximum value this accepts is 2147483648. Any larger value is capped to
-this amount.
-.SH DEFAULT
-60
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* enable TCP keep-alive for this transfer */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
-
- /* set keep-alive idle time to 120 seconds */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
-
- /* interval time between keep-alive probes: 60 seconds */
- curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_TCP_KEEPALIVE (3),
-.BR CURLOPT_TCP_KEEPIDLE (3)
diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md b/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md
new file mode 100644
index 000000000..d560cf516
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TCP_KEEPINTVL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TCP_KEEPALIVE (3)
+ - CURLOPT_TCP_KEEPIDLE (3)
+---
+
+# NAME
+
+CURLOPT_TCP_KEEPINTVL - TCP keep-alive interval
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPINTVL, long interval);
+~~~
+
+# DESCRIPTION
+
+Pass a long. Sets the interval, in seconds, to wait between sending keepalive
+probes. Not all operating systems support this option. (Added in 7.25.0)
+
+The maximum value this accepts is 2147483648. Any larger value is capped to
+this amount.
+
+# DEFAULT
+
+60
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* enable TCP keep-alive for this transfer */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
+
+ /* set keep-alive idle time to 120 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
+
+ /* interval time between keep-alive probes: 60 seconds */
+ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3 b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
deleted file mode 100644
index e0b79030e..000000000
--- a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TCP_NODELAY 3 "30 Jun 2016" libcurl libcurl
-.SH NAME
-CURLOPT_TCP_NODELAY \- the TCP_NODELAY option
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_NODELAY, long nodelay);
-.fi
-.SH DESCRIPTION
-Pass a long specifying whether the \fITCP_NODELAY\fP option is to be set or
-cleared (1L = set, 0 = clear). The option is set by default. This has no
-effect after the connection has been established.
-
-Setting this option to 1L disables TCP's Nagle algorithm on connections
-created using this handle. The purpose of this algorithm is to try to minimize
-the number of small packets on the network (where "small packets" means TCP
-segments less than the Maximum Segment Size for the network).
-
-Maximizing the amount of data sent per TCP segment is good because it
-amortizes the overhead of the send. However, in some cases small segments may
-need to be sent without delay. This is less efficient than sending larger
-amounts of data at a time, and can contribute to congestion on the network if
-overdone.
-.SH DEFAULT
-1
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- /* leave Nagle enabled */
- curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 0);
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always. The default was changed to 1 from 0 in 7.50.2.
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_BUFFERSIZE (3),
-.BR CURLOPT_SOCKOPTFUNCTION (3),
-.BR CURLOPT_TCP_KEEPALIVE (3)
diff --git a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.md b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.md
new file mode 100644
index 000000000..7fe286d26
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TCP_NODELAY
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_BUFFERSIZE (3)
+ - CURLOPT_SOCKOPTFUNCTION (3)
+ - CURLOPT_TCP_KEEPALIVE (3)
+---
+
+# NAME
+
+CURLOPT_TCP_NODELAY - the TCP_NODELAY option
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_NODELAY, long nodelay);
+~~~
+
+# DESCRIPTION
+
+Pass a long specifying whether the *TCP_NODELAY* option is to be set or
+cleared (1L = set, 0 = clear). The option is set by default. This has no
+effect after the connection has been established.
+
+Setting this option to 1L disables TCP's Nagle algorithm on connections
+created using this handle. The purpose of this algorithm is to try to minimize
+the number of small packets on the network (where "small packets" means TCP
+segments less than the Maximum Segment Size for the network).
+
+Maximizing the amount of data sent per TCP segment is good because it
+amortizes the overhead of the send. However, in some cases small segments may
+need to be sent without delay. This is less efficient than sending larger
+amounts of data at a time, and can contribute to congestion on the network if
+overdone.
+
+# DEFAULT
+
+1
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ /* leave Nagle enabled */
+ curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 0);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always. The default was changed to 1 from 0 in 7.50.2.
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3 b/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3
deleted file mode 100644
index 480314ff5..000000000
--- a/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TELNETOPTIONS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TELNETOPTIONS \- set of telnet options
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TELNETOPTIONS,
- struct curl_slist *cmds);
-.fi
-.SH DESCRIPTION
-Provide a pointer to a curl_slist with variables to pass to the telnet
-negotiations. The variables should be in the format <option=value>. libcurl
-supports the options \fBTTYPE\fP, \fBXDISPLOC\fP and \fBNEW_ENV\fP. See the
-TELNET standard for details.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-TELNET
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- struct curl_slist *options;
- options = curl_slist_append(NULL, "TTTYPE=vt100");
- options = curl_slist_append(options, "USER=foobar");
- curl_easy_setopt(curl, CURLOPT_URL, "telnet://example.com/");
- curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, options);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
- curl_slist_free_all(options);
-}
-.fi
-.SH AVAILABILITY
-Along with TELNET
-.SH RETURN VALUE
-Returns CURLE_OK if TELNET is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_HTTPHEADER (3),
-.BR CURLOPT_QUOTE (3)
diff --git a/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md b/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md
new file mode 100644
index 000000000..e1db12ed8
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TELNETOPTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPHEADER (3)
+ - CURLOPT_QUOTE (3)
+---
+
+# NAME
+
+CURLOPT_TELNETOPTIONS - set of telnet options
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TELNETOPTIONS,
+ struct curl_slist *cmds);
+~~~
+
+# DESCRIPTION
+
+Provide a pointer to a curl_slist with variables to pass to the telnet
+negotiations. The variables should be in the format <option=value>. libcurl
+supports the options **TTYPE**, **XDISPLOC** and **NEW_ENV**. See the
+TELNET standard for details.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+TELNET
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ struct curl_slist *options;
+ options = curl_slist_append(NULL, "TTTYPE=vt100");
+ options = curl_slist_append(options, "USER=foobar");
+ curl_easy_setopt(curl, CURLOPT_URL, "telnet://example.com/");
+ curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, options);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ curl_slist_free_all(options);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with TELNET
+
+# RETURN VALUE
+
+Returns CURLE_OK if TELNET is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3 b/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3
deleted file mode 100644
index b6daf806f..000000000
--- a/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TFTP_BLKSIZE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TFTP_BLKSIZE \- TFTP block size
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_BLKSIZE, long blocksize);
-.fi
-.SH DESCRIPTION
-Specify \fIblocksize\fP to use for TFTP data transmission. Valid range as per
-RFC 2348 is 8-65464 bytes. The default of 512 bytes is used if this option is
-not specified. The specified block size is only used if supported by the
-remote server. If the server does not return an option acknowledgment or
-returns an option acknowledgment with no block size, the default of 512 bytes
-is used.
-.SH DEFAULT
-512
-.SH PROTOCOLS
-TFTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "tftp://example.com/bootimage");
- /* try using larger blocks */
- curl_easy_setopt(curl, CURLOPT_TFTP_BLKSIZE, 2048L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_MAXFILESIZE (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md b/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md
new file mode 100644
index 000000000..07cbebae4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TFTP_BLKSIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAXFILESIZE (3)
+---
+
+# NAME
+
+CURLOPT_TFTP_BLKSIZE - TFTP block size
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_BLKSIZE, long blocksize);
+~~~
+
+# DESCRIPTION
+
+Specify *blocksize* to use for TFTP data transmission. Valid range as per
+RFC 2348 is 8-65464 bytes. The default of 512 bytes is used if this option is
+not specified. The specified block size is only used if supported by the
+remote server. If the server does not return an option acknowledgment or
+returns an option acknowledgment with no block size, the default of 512 bytes
+is used.
+
+# DEFAULT
+
+512
+
+# PROTOCOLS
+
+TFTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "tftp://example.com/bootimage");
+ /* try using larger blocks */
+ curl_easy_setopt(curl, CURLOPT_TFTP_BLKSIZE, 2048L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3
deleted file mode 100644
index fc3b3b3f8..000000000
--- a/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TFTP_NO_OPTIONS 3 "23 Feb 2016" libcurl libcurl
-.SH NAME
-CURLOPT_TFTP_NO_OPTIONS \- send no TFTP options requests
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_NO_OPTIONS, long onoff);
-.fi
-.SH DESCRIPTION
-Set \fIonoff\fP to 1L to exclude all TFTP options defined in RFC 2347,
-RFC 2348 and RFC 2349 from read and write requests.
-
-This option improves interoperability with legacy servers that do not
-acknowledge or properly implement TFTP options. When this option is used
-\fICURLOPT_TFTP_BLKSIZE(3)\fP is ignored.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-TFTP
-.SH EXAMPLE
-.nf
-size_t write_callback(char *ptr, size_t size, size_t nmemb, void *fp)
-{
- return fwrite(ptr, size, nmemb, (FILE *)fp);
-}
-
-CURL *curl = curl_easy_init();
-if(curl) {
- FILE *fp = fopen("foo.bin", "wb");
- if(fp) {
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)fp);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
-
- curl_easy_setopt(curl, CURLOPT_URL, "tftp://example.com/foo.bin");
-
- /* do not send TFTP options requests */
- curl_easy_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L);
-
- /* Perform the request */
- curl_easy_perform(curl);
-
- fclose(fp);
- }
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.48.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH SEE ALSO
-.BR CURLOPT_TFTP_BLKSIZE "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.md b/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.md
new file mode 100644
index 000000000..fd4e4921f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TFTP_NO_OPTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TFTP_BLKSIZE (3)
+---
+
+# NAME
+
+CURLOPT_TFTP_NO_OPTIONS - send no TFTP options requests
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_NO_OPTIONS, long onoff);
+~~~
+
+# DESCRIPTION
+
+Set *onoff* to 1L to exclude all TFTP options defined in RFC 2347,
+RFC 2348 and RFC 2349 from read and write requests.
+
+This option improves interoperability with legacy servers that do not
+acknowledge or properly implement TFTP options. When this option is used
+CURLOPT_TFTP_BLKSIZE(3) is ignored.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+TFTP
+
+# EXAMPLE
+
+~~~c
+size_t write_callback(char *ptr, size_t size, size_t nmemb, void *fp)
+{
+ return fwrite(ptr, size, nmemb, (FILE *)fp);
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ FILE *fp = fopen("foo.bin", "wb");
+ if(fp) {
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)fp);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
+
+ curl_easy_setopt(curl, CURLOPT_URL, "tftp://example.com/foo.bin");
+
+ /* do not send TFTP options requests */
+ curl_easy_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+
+ fclose(fp);
+ }
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.48.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TIMECONDITION.3 b/docs/libcurl/opts/CURLOPT_TIMECONDITION.3
deleted file mode 100644
index 4da79f5ef..000000000
--- a/docs/libcurl/opts/CURLOPT_TIMECONDITION.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TIMECONDITION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TIMECONDITION \- select condition for a time request
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMECONDITION, long cond);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE(3)\fP time
-value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
-or \fICURL_TIMECOND_IFUNMODSINCE\fP.
-
-The last modification time of a file is not always known and in such instances
-this feature has no effect even if the given time condition would not have
-been met. \fIcurl_easy_getinfo(3)\fP with the \fICURLINFO_CONDITION_UNMET\fP
-option can be used after a transfer to learn if a zero-byte successful
-"transfer" was due to this condition not matching.
-.SH DEFAULT
-CURL_TIMECOND_NONE (0)
-.SH PROTOCOLS
-HTTP, FTP, RTSP, and FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* January 1, 2020 is 1577833200 */
- curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
-
- /* If-Modified-Since the above time stamp */
- curl_easy_setopt(curl, CURLOPT_TIMECONDITION,
- (long)CURL_TIMECOND_IFMODSINCE);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_TIMEVALUE (3),
-.BR CURLINFO_FILETIME (3)
diff --git a/docs/libcurl/opts/CURLOPT_TIMECONDITION.md b/docs/libcurl/opts/CURLOPT_TIMECONDITION.md
new file mode 100644
index 000000000..80d93a516
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TIMECONDITION.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TIMECONDITION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_FILETIME (3)
+ - CURLOPT_TIMEVALUE (3)
+---
+
+# NAME
+
+CURLOPT_TIMECONDITION - select condition for a time request
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMECONDITION, long cond);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE(3) time
+value is treated. You can set this parameter to *CURL_TIMECOND_IFMODSINCE*
+or *CURL_TIMECOND_IFUNMODSINCE*.
+
+The last modification time of a file is not always known and in such instances
+this feature has no effect even if the given time condition would not have
+been met. curl_easy_getinfo(3) with the *CURLINFO_CONDITION_UNMET*
+option can be used after a transfer to learn if a zero-byte successful
+"transfer" was due to this condition not matching.
+
+# DEFAULT
+
+CURL_TIMECOND_NONE (0)
+
+# PROTOCOLS
+
+HTTP, FTP, RTSP, and FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* January 1, 2020 is 1577833200 */
+ curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
+
+ /* If-Modified-Since the above time stamp */
+ curl_easy_setopt(curl, CURLOPT_TIMECONDITION,
+ (long)CURL_TIMECOND_IFMODSINCE);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_TIMEOUT.3 b/docs/libcurl/opts/CURLOPT_TIMEOUT.3
deleted file mode 100644
index c9fa4e05e..000000000
--- a/docs/libcurl/opts/CURLOPT_TIMEOUT.3
+++ /dev/null
@@ -1,89 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TIMEOUT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TIMEOUT \- maximum time the transfer is allowed to complete
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT, long timeout);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter containing \fItimeout\fP - the maximum time in
-seconds that you allow the entire transfer operation to take. The whole thing,
-from start to end. Normally, name lookups can take a considerable time and
-limiting operations risk aborting perfectly normal operations.
-
-\fICURLOPT_TIMEOUT_MS(3)\fP is the same function but set in milliseconds.
-
-If both \fICURLOPT_TIMEOUT(3)\fP and \fICURLOPT_TIMEOUT_MS(3)\fP are set, the
-value set last is used.
-
-Since this option puts a hard limit on how long time a request is allowed to
-take, it has limited use in dynamic use cases with varying transfer
-times. That is especially apparent when using the multi interface, which may
-queue the transfer, and that time is included. You are advised to explore
-\fICURLOPT_LOW_SPEED_LIMIT(3)\fP, \fICURLOPT_LOW_SPEED_TIME(3)\fP or using
-\fICURLOPT_PROGRESSFUNCTION(3)\fP to implement your own timeout logic.
-
-The connection timeout set with \fICURLOPT_CONNECTTIMEOUT(3)\fP is included in
-this general all-covering timeout.
-
-With \fICURLOPT_CONNECTTIMEOUT(3)\fP set to 3 and \fICURLOPT_TIMEOUT(3)\fP set
-to 5, the operation can never last longer than 5 seconds.
-
-With \fICURLOPT_CONNECTTIMEOUT(3)\fP set to 4 and \fICURLOPT_TIMEOUT(3)\fP set
-to 2, the operation can never last longer than 2 seconds.
-
-This option may cause libcurl to use the SIGALRM signal to timeout system
-calls on builds not using asynch DNS. In unix-like systems, this might cause
-signals to be used unless \fICURLOPT_NOSIGNAL(3)\fP is set.
-.SH DEFAULT
-Default timeout is 0 (zero) which means it never times out during transfer.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* complete within 20 seconds */
- curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK. Returns CURLE_BAD_FUNCTION_ARGUMENT if set to a negative
-value or a value that when converted to milliseconds is too large.
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECTTIMEOUT (3),
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_TCP_KEEPALIVE (3),
-.BR CURLOPT_TIMEOUT_MS (3)
diff --git a/docs/libcurl/opts/CURLOPT_TIMEOUT.md b/docs/libcurl/opts/CURLOPT_TIMEOUT.md
new file mode 100644
index 000000000..02a3d3dbe
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TIMEOUT.md
@@ -0,0 +1,90 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TIMEOUT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT (3)
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_TCP_KEEPALIVE (3)
+ - CURLOPT_TIMEOUT_MS (3)
+---
+
+# NAME
+
+CURLOPT_TIMEOUT - maximum time the transfer is allowed to complete
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT, long timeout);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter containing *timeout* - the maximum time in
+seconds that you allow the entire transfer operation to take. The whole thing,
+from start to end. Normally, name lookups can take a considerable time and
+limiting operations risk aborting perfectly normal operations.
+
+CURLOPT_TIMEOUT_MS(3) is the same function but set in milliseconds.
+
+If both CURLOPT_TIMEOUT(3) and CURLOPT_TIMEOUT_MS(3) are set, the
+value set last is used.
+
+Since this option puts a hard limit on how long time a request is allowed to
+take, it has limited use in dynamic use cases with varying transfer
+times. That is especially apparent when using the multi interface, which may
+queue the transfer, and that time is included. You are advised to explore
+CURLOPT_LOW_SPEED_LIMIT(3), CURLOPT_LOW_SPEED_TIME(3) or using
+CURLOPT_PROGRESSFUNCTION(3) to implement your own timeout logic.
+
+The connection timeout set with CURLOPT_CONNECTTIMEOUT(3) is included in
+this general all-covering timeout.
+
+With CURLOPT_CONNECTTIMEOUT(3) set to 3 and CURLOPT_TIMEOUT(3) set
+to 5, the operation can never last longer than 5 seconds.
+
+With CURLOPT_CONNECTTIMEOUT(3) set to 4 and CURLOPT_TIMEOUT(3) set
+to 2, the operation can never last longer than 2 seconds.
+
+This option may cause libcurl to use the SIGALRM signal to timeout system
+calls on builds not using asynch DNS. In unix-like systems, this might cause
+signals to be used unless CURLOPT_NOSIGNAL(3) is set.
+
+# DEFAULT
+
+Default timeout is 0 (zero) which means it never times out during transfer.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* complete within 20 seconds */
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK. Returns CURLE_BAD_FUNCTION_ARGUMENT if set to a negative
+value or a value that when converted to milliseconds is too large.
diff --git a/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3 b/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3
deleted file mode 100644
index 4c0936c0f..000000000
--- a/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TIMEOUT_MS 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TIMEOUT_MS \- maximum time the transfer is allowed to complete
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT_MS, long timeout);
-.fi
-.SH DESCRIPTION
-Pass a long as parameter containing \fItimeout\fP - the maximum time in
-milliseconds that you allow the libcurl transfer operation to take.
-
-See \fICURLOPT_TIMEOUT(3)\fP for details.
-.SH DEFAULT
-Default timeout is 0 (zero) which means it never times out during transfer.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* complete within 20000 milliseconds */
- curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 20000L);
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_CONNECTTIMEOUT (3),
-.BR CURLOPT_LOW_SPEED_LIMIT (3),
-.BR CURLOPT_TCP_KEEPALIVE (3),
-.BR CURLOPT_TIMEOUT (3)
diff --git a/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.md b/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.md
new file mode 100644
index 000000000..0bb037f7c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TIMEOUT_MS.md
@@ -0,0 +1,64 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TIMEOUT_MS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECTTIMEOUT (3)
+ - CURLOPT_LOW_SPEED_LIMIT (3)
+ - CURLOPT_TCP_KEEPALIVE (3)
+ - CURLOPT_TIMEOUT (3)
+---
+
+# NAME
+
+CURLOPT_TIMEOUT_MS - maximum time the transfer is allowed to complete
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEOUT_MS, long timeout);
+~~~
+
+# DESCRIPTION
+
+Pass a long as parameter containing *timeout* - the maximum time in
+milliseconds that you allow the libcurl transfer operation to take.
+
+See CURLOPT_TIMEOUT(3) for details.
+
+# DEFAULT
+
+Default timeout is 0 (zero) which means it never times out during transfer.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* complete within 20000 milliseconds */
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 20000L);
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_TIMEVALUE.3 b/docs/libcurl/opts/CURLOPT_TIMEVALUE.3
deleted file mode 100644
index 9cca94228..000000000
--- a/docs/libcurl/opts/CURLOPT_TIMEVALUE.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TIMEVALUE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TIMEVALUE \- time value for conditional
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE, long val);
-.fi
-.SH DESCRIPTION
-Pass a long \fIval\fP as parameter. This should be the time counted as seconds
-since 1 Jan 1970, and the time is used in a condition as specified with
-\fICURLOPT_TIMECONDITION(3)\fP.
-
-On systems with 32 bit 'long' variables (such as Windows), this option cannot
-set dates beyond the year 2038. Consider \fICURLOPT_TIMEVALUE_LARGE(3)\fP
-instead.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP, FTP, RTSP, and FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* January 1, 2020 is 1577833200 */
- curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
-
- /* If-Modified-Since the above time stamp */
- curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_TIMECONDITION (3),
-.BR CURLOPT_TIMEVALUE_LARGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_TIMEVALUE.md b/docs/libcurl/opts/CURLOPT_TIMEVALUE.md
new file mode 100644
index 000000000..cc8f6032c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TIMEVALUE.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TIMEVALUE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TIMECONDITION (3)
+ - CURLOPT_TIMEVALUE_LARGE (3)
+---
+
+# NAME
+
+CURLOPT_TIMEVALUE - time value for conditional
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE, long val);
+~~~
+
+# DESCRIPTION
+
+Pass a long *val* as parameter. This should be the time counted as seconds
+since 1 Jan 1970, and the time is used in a condition as specified with
+CURLOPT_TIMECONDITION(3).
+
+On systems with 32 bit 'long' variables (such as Windows), this option cannot
+set dates beyond the year 2038. Consider CURLOPT_TIMEVALUE_LARGE(3)
+instead.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP, FTP, RTSP, and FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* January 1, 2020 is 1577833200 */
+ curl_easy_setopt(curl, CURLOPT_TIMEVALUE, 1577833200L);
+
+ /* If-Modified-Since the above time stamp */
+ curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3 b/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3
deleted file mode 100644
index 75c58a0a3..000000000
--- a/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TIMEVALUE_LARGE 3 "25 Jan 2018" libcurl libcurl
-.SH NAME
-CURLOPT_TIMEVALUE_LARGE \- time value for conditional
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE_LARGE,
- curl_off_t val);
-.fi
-.SH DESCRIPTION
-Pass a curl_off_t \fIval\fP as parameter. This should be the time counted as
-seconds since 1 Jan 1970, and the time is used in a condition as specified
-with \fICURLOPT_TIMECONDITION(3)\fP.
-
-The difference between this option and \fICURLOPT_TIMEVALUE(3)\fP is the type
-of the argument. On systems where 'long' is only 32 bit wide, this option has
-to be used to set dates beyond the year 2038.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP, FTP, RTSP, and FILE
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* January 1, 2020 is 1577833200 */
- curl_easy_setopt(curl, CURLOPT_TIMEVALUE_LARGE, (curl_off_t)1577833200);
-
- /* If-Modified-Since the above time stamp */
- curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.59.0.
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_TIMECONDITION (3),
-.BR CURLOPT_TIMEVALUE (3),
-.BR CURLINFO_FILETIME (3)
diff --git a/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.md b/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.md
new file mode 100644
index 000000000..1424f6617
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TIMEVALUE_LARGE.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TIMEVALUE_LARGE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_FILETIME (3)
+ - CURLOPT_TIMECONDITION (3)
+ - CURLOPT_TIMEVALUE (3)
+---
+
+# NAME
+
+CURLOPT_TIMEVALUE_LARGE - time value for conditional
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TIMEVALUE_LARGE,
+ curl_off_t val);
+~~~
+
+# DESCRIPTION
+
+Pass a curl_off_t *val* as parameter. This should be the time counted as
+seconds since 1 Jan 1970, and the time is used in a condition as specified
+with CURLOPT_TIMECONDITION(3).
+
+The difference between this option and CURLOPT_TIMEVALUE(3) is the type
+of the argument. On systems where 'long' is only 32 bit wide, this option has
+to be used to set dates beyond the year 2038.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP, FTP, RTSP, and FILE
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* January 1, 2020 is 1577833200 */
+ curl_easy_setopt(curl, CURLOPT_TIMEVALUE_LARGE, (curl_off_t)1577833200);
+
+ /* If-Modified-Since the above time stamp */
+ curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.59.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3 b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3
deleted file mode 100644
index 7e6ec19b0..000000000
--- a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TLS13_CIPHERS 3 "25 May 2018" libcurl libcurl
-.SH NAME
-CURLOPT_TLS13_CIPHERS \- ciphers suites to use for TLS 1.3
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLS13_CIPHERS, char *list);
-.fi
-.SH DESCRIPTION
-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.
-
-Find more details about cipher lists on this URL:
-
- https://curl.se/docs/ssl-ciphers.html
-
-This option is currently used only when curl is built to use OpenSSL 1.1.1 or
-later, or Schannel. If you are using a different SSL backend you can try
-setting TLS 1.3 cipher suites by using the \fICURLOPT_SSL_CIPHER_LIST(3)\fP
-option.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL, use internal default
-.SH PROTOCOLS
-All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- curl_easy_setopt(curl, CURLOPT_TLS13_CIPHERS,
- "TLS_CHACHA20_POLY1305_SHA256");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.61.0 for OpenSSL. Available when built with OpenSSL >= 1.1.1.
-
-Added in 7.85.0 for Schannel.
-.SH RETURN VALUE
-Returns CURLE_OK if supported, CURLE_NOT_BUILT_IN otherwise.
-.SH "SEE ALSO"
-.BR CURLOPT_PROXY_SSL_CIPHER_LIST (3),
-.BR CURLOPT_PROXY_SSLVERSION (3),
-.BR CURLOPT_PROXY_TLS13_CIPHERS (3),
-.BR CURLOPT_SSL_CIPHER_LIST (3),
-.BR CURLOPT_SSLVERSION (3),
-.BR CURLOPT_USE_SSL (3)
diff --git a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md
new file mode 100644
index 000000000..add1f2f8e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TLS13_CIPHERS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLVERSION (3)
+ - CURLOPT_PROXY_SSL_CIPHER_LIST (3)
+ - CURLOPT_PROXY_TLS13_CIPHERS (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_SSL_CIPHER_LIST (3)
+ - CURLOPT_USE_SSL (3)
+---
+
+# NAME
+
+CURLOPT_TLS13_CIPHERS - ciphers suites to use for TLS 1.3
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLS13_CIPHERS, char *list);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer, 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.
+
+Find more details about cipher lists on this URL:
+
+ https://curl.se/docs/ssl-ciphers.html
+
+This option is currently used only when curl is built to use OpenSSL 1.1.1 or
+later, or Schannel. If you are using a different SSL backend you can try
+setting TLS 1.3 cipher suites by using the CURLOPT_SSL_CIPHER_LIST(3)
+option.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL, use internal default
+
+# PROTOCOLS
+
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_TLS13_CIPHERS,
+ "TLS_CHACHA20_POLY1305_SHA256");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.61.0 for OpenSSL. Available when built with OpenSSL >= 1.1.1.
+
+Added in 7.85.0 for Schannel.
+
+# RETURN VALUE
+
+Returns CURLE_OK if supported, CURLE_NOT_BUILT_IN otherwise.
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3
deleted file mode 100644
index 6e77e80ef..000000000
--- a/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.3
+++ /dev/null
@@ -1,68 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TLSAUTH_PASSWORD 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TLSAUTH_PASSWORD \- password to use for TLS authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_PASSWORD, char *pwd);
-.fi
-.SH DESCRIPTION
-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.
-
-The application does not have to keep the string around after setting this
-option.
-
-This feature relies in TLS SRP which does not work with TLS 1.3.
-.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/");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_TYPE, "SRP");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_USERNAME, "user");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_PASSWORD, "secret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.4, with the OpenSSL and GnuTLS backends only
-.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_TLSAUTH_PASSWORD (3),
-.BR CURLOPT_TLSAUTH_TYPE (3),
-.BR CURLOPT_TLSAUTH_USERNAME (3)
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md b/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md
new file mode 100644
index 000000000..1d0e1d01d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md
@@ -0,0 +1,70 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TLSAUTH_PASSWORD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_TLSAUTH_PASSWORD (3)
+ - CURLOPT_TLSAUTH_TYPE (3)
+ - CURLOPT_TLSAUTH_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_TLSAUTH_PASSWORD - password to use for TLS authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_PASSWORD, char *pwd);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should point to the null-terminated
+password to use for the TLS authentication method specified with the
+CURLOPT_TLSAUTH_TYPE(3) option. Requires that the
+CURLOPT_TLSAUTH_USERNAME(3) option also be set.
+
+The application does not have to keep the string around after setting this
+option.
+
+This feature relies in TLS SRP which does not work with TLS 1.3.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_TYPE, "SRP");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_USERNAME, "user");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_PASSWORD, "secret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.4, with the OpenSSL and GnuTLS backends only
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3 b/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3
deleted file mode 100644
index c69185fbc..000000000
--- a/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TLSAUTH_TYPE 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TLSAUTH_TYPE \- TLS authentication methods
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_TYPE, char *type);
-.fi
-.SH DESCRIPTION
-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
-TLS-SRP authentication. Secure Remote Password authentication for TLS is
-defined in RFC 5054 and provides mutual authentication if both sides have a
-shared secret. To use TLS-SRP, you must also set the
-\fICURLOPT_TLSAUTH_USERNAME(3)\fP and \fICURLOPT_TLSAUTH_PASSWORD(3)\fP
-options.
-
-The application does not have to keep the string around after setting this
-option.
-
-TLS SRP does not work with TLS 1.3.
-.SH DEFAULT
-blank
-.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/");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_TYPE, "SRP");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_USERNAME, "user");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_PASSWORD, "secret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this
-to work. Added in 7.21.4
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_TLSAUTH_USERNAME (3),
-.BR CURLOPT_TLSAUTH_PASSWORD (3)
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md b/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md
new file mode 100644
index 000000000..f3e0803d4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TLSAUTH_TYPE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TLSAUTH_PASSWORD (3)
+ - CURLOPT_TLSAUTH_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_TLSAUTH_TYPE - TLS authentication methods
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_TYPE, char *type);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. The string should be
+the method of the TLS authentication. Supported method is "SRP".
+
+## SRP
+
+TLS-SRP authentication. Secure Remote Password authentication for TLS is
+defined in RFC 5054 and provides mutual authentication if both sides have a
+shared secret. To use TLS-SRP, you must also set the
+CURLOPT_TLSAUTH_USERNAME(3) and CURLOPT_TLSAUTH_PASSWORD(3)
+options.
+
+The application does not have to keep the string around after setting this
+option.
+
+TLS SRP does not work with TLS 1.3.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_TYPE, "SRP");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_USERNAME, "user");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_PASSWORD, "secret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this
+to work. Added in 7.21.4
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3
deleted file mode 100644
index 47593e923..000000000
--- a/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TLSAUTH_USERNAME 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TLSAUTH_USERNAME \- user name to use for TLS authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_USERNAME, char *user);
-.fi
-.SH DESCRIPTION
-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.
-
-The application does not have to keep the string around after setting this
-option.
-
-This feature relies in TLS SRP which does not work with TLS 1.3.
-.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/");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_TYPE, "SRP");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_USERNAME, "user");
- curl_easy_setopt(curl, CURLOPT_TLSAUTH_PASSWORD, "secret");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.4, with the OpenSSL and GnuTLS backends only
-.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_TLSAUTH_TYPE (3),
-.BR CURLOPT_TLSAUTH_PASSWORD (3)
diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md b/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md
new file mode 100644
index 000000000..1127046af
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md
@@ -0,0 +1,69 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TLSAUTH_USERNAME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TLSAUTH_PASSWORD (3)
+ - CURLOPT_TLSAUTH_TYPE (3)
+---
+
+# NAME
+
+CURLOPT_TLSAUTH_USERNAME - user name to use for TLS authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_USERNAME, char *user);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should point to the null-terminated
+username to use for the TLS authentication method specified with the
+CURLOPT_TLSAUTH_TYPE(3) option. Requires that the
+CURLOPT_TLSAUTH_PASSWORD(3) option also be set.
+
+The application does not have to keep the string around after setting this
+option.
+
+This feature relies in TLS SRP which does not work with TLS 1.3.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+All TLS-based protocols
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_TYPE, "SRP");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_USERNAME, "user");
+ curl_easy_setopt(curl, CURLOPT_TLSAUTH_PASSWORD, "secret");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.4, with the OpenSSL and GnuTLS backends only
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_TRAILERDATA.3 b/docs/libcurl/opts/CURLOPT_TRAILERDATA.3
deleted file mode 100644
index fd7830de5..000000000
--- a/docs/libcurl/opts/CURLOPT_TRAILERDATA.3
+++ /dev/null
@@ -1,56 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TRAILERDATA 3 "14 Aug 2018" libcurl libcurl
-.SH NAME
-CURLOPT_TRAILERDATA \- pointer passed to trailing headers callback
-.SH SYNOPSIS
-.nf
-#include <curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRAILERDATA, void *userdata);
-.fi
-.SH DESCRIPTION
-Data pointer to be passed to the HTTP trailer callback function.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-/* Assuming we have a CURL handle in the hndl variable. */
-
-struct MyData data;
-
-curl_easy_setopt(hndl, CURLOPT_TRAILERDATA, &data);
-.fi
-
-A more complete example can be found in examples/http_trailers.html
-.SH AVAILABILITY
-This option was added in curl 7.64.0 and is present if HTTP support is enabled
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_TRAILERFUNCTION (3),
-.BR CURLOPT_WRITEFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_TRAILERDATA.md b/docs/libcurl/opts/CURLOPT_TRAILERDATA.md
new file mode 100644
index 000000000..304b408e2
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TRAILERDATA.md
@@ -0,0 +1,59 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TRAILERDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TRAILERFUNCTION (3)
+ - CURLOPT_WRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_TRAILERDATA - pointer passed to trailing headers callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRAILERDATA, void *userdata);
+~~~
+
+# DESCRIPTION
+
+Data pointer to be passed to the HTTP trailer callback function.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+struct MyData {
+ void *custom;
+};
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct MyData data;
+ curl_easy_setopt(curl, CURLOPT_TRAILERDATA, &data);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+This option was added in curl 7.64.0 and is present if HTTP support is enabled
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3 b/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3
deleted file mode 100644
index ed910a3d7..000000000
--- a/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.3
+++ /dev/null
@@ -1,110 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TRAILERFUNCTION 3 "14 Aug 2018" libcurl libcurl
-.SH NAME
-CURLOPT_TRAILERFUNCTION \- callback for sending trailing headers
-.SH SYNOPSIS
-.nf
-#include <curl.h>
-
-int curl_trailer_callback(struct curl_slist ** list, void *userdata);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRAILERFUNCTION,
- curl_trailer_callback *func);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a callback function.
-
-This callback function is called once right before sending the final CR LF in
-an HTTP chunked transfer to fill a list of trailing headers to be sent before
-finishing the HTTP transfer.
-
-You can set the userdata argument with the \fICURLOPT_TRAILERDATA(3)\fP
-option.
-
-The trailing headers included in the linked list must not be CRLF-terminated,
-because libcurl adds the appropriate line termination characters after each
-header item.
-
-If you use curl_slist_append to add trailing headers to the curl_slist then
-libcurl duplicates the strings, and frees the curl_slist and the duplicates
-once the trailers have been sent.
-
-If one of the trailing header fields is not formatted correctly it is ignored
-and an info message is emitted.
-
-The return value can either be \fBCURL_TRAILERFUNC_OK\fP or
-\fBCURL_TRAILERFUNC_ABORT\fP which would respectively instruct libcurl to
-either continue with sending the trailers or to abort the request.
-
-If you set this option to NULL, then the transfer proceeds as usual
-without any interruptions.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-#include <curl/curl.h>
-
-static int trailer_cb(struct curl_slist **tr, void *data)
-{
- /* libcurl frees the list */
- *tr = curl_slist_append(*tr, "My-super-awesome-trailer: trailer-stuff");
- return CURL_TRAILERFUNC_OK;
-}
-
-CURL *curl = curl_easy_init();
-if(curl) {
- /* Set the URL of the request */
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
- /* Now set it as a put */
- curl_easy_setopt(curl, CURLOPT_PUT, 1L);
-
- /* Assuming we have a function that returns the data to be pushed
- Let that function be read_cb */
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb);
-
- struct curl_slist *headers = NULL;
- headers = curl_slist_append(headers, "Trailer: My-super-awesome-trailer");
- res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-
- /* Set the trailers filling callback */
- curl_easy_setopt(curl, CURLOPT_TRAILERFUNCTION, trailer_cb);
-
- /* Perform the transfer */
- res = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-
- curl_slist_free_all(headers);
-}
-.SH AVAILABILITY
-This option was added in curl 7.64.0 and is present if HTTP support is enabled
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_TRAILERDATA (3),
-.BR CURLOPT_WRITEFUNCTION (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md b/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md
new file mode 100644
index 000000000..5d79214bf
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md
@@ -0,0 +1,110 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TRAILERFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TRAILERDATA (3)
+ - CURLOPT_WRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_TRAILERFUNCTION - callback for sending trailing headers
+
+# SYNOPSIS
+
+~~~c
+#include <curl.h>
+
+int curl_trailer_callback(struct curl_slist ** list, void *userdata);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRAILERFUNCTION,
+ curl_trailer_callback *func);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a callback function.
+
+This callback function is called once right before sending the final CR LF in
+an HTTP chunked transfer to fill a list of trailing headers to be sent before
+finishing the HTTP transfer.
+
+You can set the userdata argument with the CURLOPT_TRAILERDATA(3)
+option.
+
+The trailing headers included in the linked list must not be CRLF-terminated,
+because libcurl adds the appropriate line termination characters after each
+header item.
+
+If you use curl_slist_append(3) to add trailing headers to the *curl_slist*
+then libcurl duplicates the strings, and frees the *curl_slist* once the
+trailers have been sent.
+
+If one of the trailing header fields is not formatted correctly it is ignored
+and an info message is emitted.
+
+The return value can either be **CURL_TRAILERFUNC_OK** or
+**CURL_TRAILERFUNC_ABORT** which would respectively instruct libcurl to
+either continue with sending the trailers or to abort the request.
+
+If you set this option to NULL, then the transfer proceeds as usual
+without any interruptions.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+~~~c
+static int trailer_cb(struct curl_slist **tr, void *data)
+{
+ /* libcurl frees the list */
+ *tr = curl_slist_append(*tr, "My-super-awesome-trailer: trailer-stuff");
+ return CURL_TRAILERFUNC_OK;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+
+ /* Set the URL of the request */
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* Now set it as a put */
+ curl_easy_setopt(curl, CURLOPT_PUT, 1L);
+
+ /* Assuming we have a function that returns the data to be pushed
+ Let that function be read_cb */
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, trailer_cb);
+
+ struct curl_slist *headers = NULL;
+ headers = curl_slist_append(headers, "Trailer: My-super-awesome-trailer");
+ res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+ /* Set the trailers filling callback */
+ curl_easy_setopt(curl, CURLOPT_TRAILERFUNCTION, trailer_cb);
+
+ /* Perform the transfer */
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+
+ curl_slist_free_all(headers);
+ }
+}
+~~~
+# AVAILABILITY
+
+This option was added in curl 7.64.0 and is present if HTTP support is enabled.
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3 b/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3
deleted file mode 100644
index 6c70b5e9c..000000000
--- a/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TRANSFERTEXT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TRANSFERTEXT \- request a text based transfer for FTP
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFERTEXT, long text);
-.fi
-.SH DESCRIPTION
-A parameter set to 1 tells the library to use ASCII mode for FTP transfers,
-instead of the default binary transfer. For win32 systems it does not set the
-stdout to binary mode. This option can be usable when transferring text data
-between systems with different views on certain characters, such as newlines
-or similar.
-
-libcurl does not do a complete ASCII conversion when doing ASCII transfers
-over FTP. This is a known limitation/flaw that nobody has rectified. libcurl
-simply sets the mode to ASCII and performs a standard transfer.
-.SH DEFAULT
-0, disabled
-.SH PROTOCOLS
-FTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/textfile");
- curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with FTP
-.SH RETURN VALUE
-Returns CURLE_OK if FTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CRLF (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md b/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md
new file mode 100644
index 000000000..4f6d00485
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md
@@ -0,0 +1,65 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TRANSFERTEXT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CRLF (3)
+---
+
+# NAME
+
+CURLOPT_TRANSFERTEXT - request a text based transfer for FTP
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFERTEXT, long text);
+~~~
+
+# DESCRIPTION
+
+A parameter set to 1 tells the library to use ASCII mode for FTP transfers,
+instead of the default binary transfer. For win32 systems it does not set the
+stdout to binary mode. This option can be usable when transferring text data
+between systems with different views on certain characters, such as newlines
+or similar.
+
+libcurl does not do a complete ASCII conversion when doing ASCII transfers
+over FTP. This is a known limitation/flaw that nobody has rectified. libcurl
+simply sets the mode to ASCII and performs a standard transfer.
+
+# DEFAULT
+
+0, disabled
+
+# PROTOCOLS
+
+FTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/textfile");
+ curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with FTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if FTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3 b/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3
deleted file mode 100644
index 9795174b9..000000000
--- a/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TRANSFER_ENCODING 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TRANSFER_ENCODING \- ask for HTTP Transfer Encoding
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFER_ENCODING,
- long enable);
-.fi
-.SH DESCRIPTION
-Pass a long set to 1L to \fIenable\fP or 0 to disable.
-
-Adds a request for compressed Transfer Encoding in the outgoing HTTP
-request. If the server supports this and so desires, it can respond with the
-HTTP response sent using a compressed Transfer-Encoding that is automatically
-uncompressed by libcurl on reception.
-
-Transfer-Encoding differs slightly from the Content-Encoding you ask for with
-\fICURLOPT_ACCEPT_ENCODING(3)\fP in that a Transfer-Encoding is strictly meant
-to be for the transfer and thus MUST be decoded before the data arrives in the
-client. Traditionally, Transfer-Encoding has been much less used and supported
-by both HTTP clients and HTTP servers.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.21.6
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ACCEPT_ENCODING (3),
-.BR CURLOPT_HTTP_TRANSFER_DECODING (3)
diff --git a/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.md b/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.md
new file mode 100644
index 000000000..7fd38487a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_TRANSFER_ENCODING.md
@@ -0,0 +1,68 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_TRANSFER_ENCODING
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ACCEPT_ENCODING (3)
+ - CURLOPT_HTTP_TRANSFER_DECODING (3)
+---
+
+# NAME
+
+CURLOPT_TRANSFER_ENCODING - ask for HTTP Transfer Encoding
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TRANSFER_ENCODING,
+ long enable);
+~~~
+
+# DESCRIPTION
+
+Pass a long set to 1L to *enable* or 0 to disable.
+
+Adds a request for compressed Transfer Encoding in the outgoing HTTP
+request. If the server supports this and so desires, it can respond with the
+HTTP response sent using a compressed Transfer-Encoding that is automatically
+uncompressed by libcurl on reception.
+
+Transfer-Encoding differs slightly from the Content-Encoding you ask for with
+CURLOPT_ACCEPT_ENCODING(3) in that a Transfer-Encoding is strictly meant
+to be for the transfer and thus MUST be decoded before the data arrives in the
+client. Traditionally, Transfer-Encoding has been much less used and supported
+by both HTTP clients and HTTP servers.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.6
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3 b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
deleted file mode 100644
index 8b988f390..000000000
--- a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.3
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_UNIX_SOCKET_PATH 3 "09 Oct 2014" libcurl libcurl
-.SH NAME
-CURLOPT_UNIX_SOCKET_PATH \- Unix domain socket
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UNIX_SOCKET_PATH, char *path);
-.fi
-.SH DESCRIPTION
-Enables the use of Unix domain sockets as connection endpoint and sets the
-path to \fIpath\fP. If \fIpath\fP is NULL, then Unix domain sockets are
-disabled.
-
-When enabled, curl connects to the Unix domain socket instead of establishing
-a TCP connection to the host. Since no network connection is created, curl
-does not resolve the DNS hostname in the URL.
-
-The maximum path length on Cygwin, Linux and Solaris is 107. On other platforms
-it might be even less.
-
-Proxy and TCP options such as \fICURLOPT_TCP_NODELAY(3)\fP are not
-supported. Proxy options such as \fICURLOPT_PROXY(3)\fP have no effect either
-as these are TCP-oriented, and asking a proxy server to connect to a certain
-Unix domain socket is not possible.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-Default is NULL, meaning that no Unix domain sockets are used.
-.SH PROTOCOLS
-All protocols except for FILE and FTP are supported in theory. HTTP, IMAP,
-POP3 and SMTP should in particular work (including their SSL/TLS variants).
-.SH EXAMPLE
-Given that you have an HTTP server running listening on /tmp/httpd.sock, you
-can request an HTTP resource with:
-
-.nf
- curl_easy_setopt(curl_handle, CURLOPT_UNIX_SOCKET_PATH, "/tmp/httpd.sock");
- curl_easy_setopt(curl_handle, CURLOPT_URL, "http://localhost/");
-.fi
-
-If you are on Linux and somehow have a need for paths larger than 107 bytes,
-you could use the proc filesystem to bypass the limitation:
-
-.nf
- int dirfd = open(long_directory_path_to_socket, O_DIRECTORY | O_RDONLY);
- char path[108];
- snprintf(path, sizeof(path), "/proc/self/fd/%d/httpd.sock", dirfd);
- curl_easy_setopt(curl_handle, CURLOPT_UNIX_SOCKET_PATH, path);
- /* Be sure to keep dirfd valid until you discard the handle */
-.fi
-.SH AVAILABILITY
-Added in 7.40.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_ABSTRACT_UNIX_SOCKET (3),
-.BR CURLOPT_OPENSOCKETFUNCTION (3),
-.BR unix (7)
diff --git a/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.md b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.md
new file mode 100644
index 000000000..0ef3ec176
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_UNIX_SOCKET_PATH.md
@@ -0,0 +1,87 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_UNIX_SOCKET_PATH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_ABSTRACT_UNIX_SOCKET (3)
+ - CURLOPT_OPENSOCKETFUNCTION (3)
+ - unix (7)
+---
+
+# NAME
+
+CURLOPT_UNIX_SOCKET_PATH - Unix domain socket
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UNIX_SOCKET_PATH, char *path);
+~~~
+
+# DESCRIPTION
+
+Enables the use of Unix domain sockets as connection endpoint and sets the
+path to *path*. If *path* is NULL, then Unix domain sockets are
+disabled.
+
+When enabled, curl connects to the Unix domain socket instead of establishing
+a TCP connection to the host. Since no network connection is created, curl
+does not resolve the DNS hostname in the URL.
+
+The maximum path length on Cygwin, Linux and Solaris is 107. On other platforms
+it might be even less.
+
+Proxy and TCP options such as CURLOPT_TCP_NODELAY(3) are not
+supported. Proxy options such as CURLOPT_PROXY(3) have no effect either
+as these are TCP-oriented, and asking a proxy server to connect to a certain
+Unix domain socket is not possible.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+Default is NULL, meaning that no Unix domain sockets are used.
+
+# PROTOCOLS
+
+All protocols except for FILE and FTP are supported in theory. HTTP, IMAP,
+POP3 and SMTP should in particular work (including their SSL/TLS variants).
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, "/tmp/httpd.sock");
+ curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/");
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+If you are on Linux and somehow have a need for paths larger than 107 bytes,
+you can use the proc filesystem to bypass the limitation:
+
+~~~c
+ int dirfd = open(long_directory_path_to_socket, O_DIRECTORY | O_RDONLY);
+ char path[108];
+ snprintf(path, sizeof(path), "/proc/self/fd/%d/httpd.sock", dirfd);
+ curl_easy_setopt(curl_handle, CURLOPT_UNIX_SOCKET_PATH, path);
+ /* Be sure to keep dirfd valid until you discard the handle */
+~~~
+
+# AVAILABILITY
+
+Added in 7.40.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3 b/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3
deleted file mode 100644
index 64fac48e3..000000000
--- a/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_UNRESTRICTED_AUTH 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_UNRESTRICTED_AUTH \- send credentials to other hosts too
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UNRESTRICTED_AUTH,
- long goahead);
-.SH DESCRIPTION
-Set the long \fIgohead\fP parameter to 1L to make libcurl continue to send
-authentication (user+password) credentials when following locations, even when
-hostname changed. This option is meaningful only when setting
-\fICURLOPT_FOLLOWLOCATION(3)\fP.
-
-Further, when this option is not used or set to \fB0L\fP, libcurl does not
-send custom nor internally generated Authentication: headers on requests done
-to other hosts than the one used for the initial URL.
-
-By default, libcurl only sends credentials and Authentication headers to the
-initial host name as given in the original URL, to avoid leaking username +
-password to other sites.
-
-This option should be used with caution: when curl follows redirects it
-blindly fetches the next URL as instructed by the server. Setting
-\fICURLOPT_UNRESTRICTED_AUTH(3)\fP to 1L therefore also makes curl trust the
-server and sends possibly sensitive credentials to any host the server points
-out. And then maybe again and again as the following hosts can keep
-redirecting to new hosts.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
- curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L);
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Along with HTTP
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_FOLLOWLOCATION (3),
-.BR CURLOPT_USERPWD (3),
-.BR CURLOPT_MAXREDIRS (3),
-.BR CURLOPT_REDIR_PROTOCOLS_STR (3),
-.BR CURLINFO_REDIRECT_COUNT (3)
diff --git a/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.md b/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.md
new file mode 100644
index 000000000..53b584fd0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_UNRESTRICTED_AUTH.md
@@ -0,0 +1,78 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_UNRESTRICTED_AUTH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_COUNT (3)
+ - CURLOPT_FOLLOWLOCATION (3)
+ - CURLOPT_MAXREDIRS (3)
+ - CURLOPT_REDIR_PROTOCOLS_STR (3)
+ - CURLOPT_USERPWD (3)
+---
+
+# NAME
+
+CURLOPT_UNRESTRICTED_AUTH - send credentials to other hosts too
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UNRESTRICTED_AUTH,
+ long goahead);
+~~~
+
+# DESCRIPTION
+
+Set the long *gohead* parameter to 1L to make libcurl continue to send
+authentication (user+password) credentials when following locations, even when
+hostname changed. This option is meaningful only when setting
+CURLOPT_FOLLOWLOCATION(3).
+
+Further, when this option is not used or set to **0L**, libcurl does not
+send custom nor internally generated Authentication: headers on requests done
+to other hosts than the one used for the initial URL.
+
+By default, libcurl only sends credentials and Authentication headers to the
+initial hostname as given in the original URL, to avoid leaking username +
+password to other sites.
+
+This option should be used with caution: when curl follows redirects it
+blindly fetches the next URL as instructed by the server. Setting
+CURLOPT_UNRESTRICTED_AUTH(3) to 1L makes curl trust the server and sends
+possibly sensitive credentials to any host the server points to, possibly
+again and again as the following hosts can keep redirecting to new hosts.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+HTTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+ curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L);
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Along with HTTP
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3 b/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3
deleted file mode 100644
index 9b3519464..000000000
--- a/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.3
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_UPKEEP_INTERVAL_MS 3 "31 Oct 2018" libcurl libcurl
-.SH NAME
-CURLOPT_UPKEEP_INTERVAL_MS \- connection upkeep interval
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPKEEP_INTERVAL_MS,
- long upkeep_interval_ms);
-.fi
-.SH DESCRIPTION
-Some protocols have "connection upkeep" mechanisms. These mechanisms usually
-send some traffic on existing connections in order to keep them alive; this
-can prevent connections from being closed due to overzealous firewalls, for
-example.
-
-The user needs to explicitly call \fIcurl_easy_upkeep(3)\fP in order to
-perform the upkeep work.
-
-Currently the only protocol with a connection upkeep mechanism is HTTP/2: when
-the connection upkeep interval is exceeded and \fIcurl_easy_upkeep(3)\fP
-is called, an HTTP/2 PING frame is sent on the connection.
-
-.SH DEFAULT
-CURL_UPKEEP_INTERVAL_DEFAULT (currently defined as 60000L, which is 60 seconds)
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- /* Make a connection to an HTTP/2 server. */
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* Set the interval to 30000ms / 30s */
- curl_easy_setopt(curl, CURLOPT_UPKEEP_INTERVAL_MS, 30000L);
-
- curl_easy_perform(curl);
-
- /* Perform more work here. */
-
- /* While the connection is being held open, curl_easy_upkeep() can be
- called. If curl_easy_upkeep() is called and the time since the last
- upkeep exceeds the interval, then an HTTP/2 PING is sent. */
- curl_easy_upkeep(curl);
-
- /* Perform more work here. */
-
- /* always cleanup */
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.62.0
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH SEE ALSO
-.BR CURLOPT_TCP_KEEPALIVE "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.md b/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.md
new file mode 100644
index 000000000..283efa73e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_UPKEEP_INTERVAL_MS.md
@@ -0,0 +1,82 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_UPKEEP_INTERVAL_MS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_TCP_KEEPALIVE (3)
+---
+
+# NAME
+
+CURLOPT_UPKEEP_INTERVAL_MS - connection upkeep interval
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPKEEP_INTERVAL_MS,
+ long upkeep_interval_ms);
+~~~
+
+# DESCRIPTION
+
+Some protocols have "connection upkeep" mechanisms. These mechanisms usually
+send some traffic on existing connections in order to keep them alive; this
+can prevent connections from being closed due to overzealous firewalls, for
+example.
+
+The user needs to explicitly call curl_easy_upkeep(3) in order to
+perform the upkeep work.
+
+Currently the only protocol with a connection upkeep mechanism is HTTP/2: when
+the connection upkeep interval is exceeded and curl_easy_upkeep(3)
+is called, an HTTP/2 PING frame is sent on the connection.
+
+# DEFAULT
+
+CURL_UPKEEP_INTERVAL_DEFAULT (currently defined as 60000L, which is 60 seconds)
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* Make a connection to an HTTP/2 server. */
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* Set the interval to 30000ms / 30s */
+ curl_easy_setopt(curl, CURLOPT_UPKEEP_INTERVAL_MS, 30000L);
+
+ curl_easy_perform(curl);
+
+ /* Perform more work here. */
+
+ /* While the connection is being held open, curl_easy_upkeep() can be
+ called. If curl_easy_upkeep() is called and the time since the last
+ upkeep exceeds the interval, then an HTTP/2 PING is sent. */
+ curl_easy_upkeep(curl);
+
+ /* Perform more work here. */
+
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD.3 b/docs/libcurl/opts/CURLOPT_UPLOAD.3
deleted file mode 100644
index 14c67d496..000000000
--- a/docs/libcurl/opts/CURLOPT_UPLOAD.3
+++ /dev/null
@@ -1,83 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_UPLOAD 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_UPLOAD \- data upload
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD, long upload);
-.fi
-.SH DESCRIPTION
-The long parameter \fIupload\fP set to 1 tells the library to prepare for and
-perform an upload. The \fICURLOPT_READDATA(3)\fP and
-\fICURLOPT_INFILESIZE(3)\fP or \fICURLOPT_INFILESIZE_LARGE(3)\fP options are
-also interesting for uploads. If the protocol is HTTP, uploading means using
-the PUT request unless you tell libcurl otherwise.
-
-Using PUT with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
-You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
-
-If you use PUT to an HTTP 1.1 server, you can upload data without knowing the
-size before starting the transfer. The library enables this by adding a header
-"Transfer-Encoding: chunked". With HTTP 1.0 or if you prefer not to use chunked
-transfer, you must specify the size of the data with
-\fICURLOPT_INFILESIZE(3)\fP or \fICURLOPT_INFILESIZE_LARGE(3)\fP.
-.SH DEFAULT
-0, default is download
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- /* we want to use our own read function */
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
-
- /* enable uploading */
- curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
-
- /* specify target */
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/to/newfile");
-
- /* now specify which pointer to pass to our callback */
- curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
-
- /* Set the size of the file to upload */
- curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize);
-
- /* Now run off and do what you have been told! */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_PUT (3),
-.BR CURLOPT_READFUNCTION (3),
-.BR CURLOPT_INFILESIZE_LARGE (3)
diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD.md b/docs/libcurl/opts/CURLOPT_UPLOAD.md
new file mode 100644
index 000000000..a54f2fd9f
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_UPLOAD.md
@@ -0,0 +1,97 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_UPLOAD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_INFILESIZE_LARGE (3)
+ - CURLOPT_PUT (3)
+ - CURLOPT_READFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_UPLOAD - data upload
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD, long upload);
+~~~
+
+# DESCRIPTION
+
+The long parameter *upload* set to 1 tells the library to prepare for and
+perform an upload. The CURLOPT_READDATA(3) and
+CURLOPT_INFILESIZE(3) or CURLOPT_INFILESIZE_LARGE(3) options are
+also interesting for uploads. If the protocol is HTTP, uploading means using
+the PUT request unless you tell libcurl otherwise.
+
+Using PUT with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
+You can disable this header with CURLOPT_HTTPHEADER(3) as usual.
+
+If you use PUT to an HTTP 1.1 server, you can upload data without knowing the
+size before starting the transfer. The library enables this by adding a header
+"Transfer-Encoding: chunked". With HTTP 1.0 or if you prefer not to use chunked
+transfer, you must specify the size of the data with
+CURLOPT_INFILESIZE(3) or CURLOPT_INFILESIZE_LARGE(3).
+
+# DEFAULT
+
+0, default is download
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ FILE *src = userdata;
+ /* copy as much data as possible into the 'ptr' buffer, but no more than
+ 'size' * 'nmemb' bytes */
+ size_t retcode = fread(ptr, size, nmemb, src);
+
+ return retcode;
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ FILE *src = fopen("local-file", "r");
+ curl_off_t fsize; /* set this to the size of the input file */
+
+ /* we want to use our own read function */
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb);
+
+ /* enable uploading */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+
+ /* specify target */
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/to/newfile");
+
+ /* now specify which pointer to pass to our callback */
+ curl_easy_setopt(curl, CURLOPT_READDATA, src);
+
+ /* Set the size of the file to upload */
+ curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize);
+
+ /* Now run off and do what you have been told! */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3 b/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3
deleted file mode 100644
index f57134680..000000000
--- a/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_UPLOAD_BUFFERSIZE 3 "18 Aug 2018" libcurl libcurl
-.SH NAME
-CURLOPT_UPLOAD_BUFFERSIZE \- upload buffer size
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD_BUFFERSIZE, long size);
-.fi
-.SH DESCRIPTION
-Pass a long specifying your preferred \fIsize\fP (in bytes) for the upload
-buffer in libcurl. It makes libcurl uses a larger buffer that gets passed to
-the next layer in the stack to get sent off. In some setups and for some
-protocols, there is a huge performance benefit of having a larger upload
-buffer.
-
-This is just treated as a request, not an order. You cannot be guaranteed to
-actually get the given size.
-
-The upload buffer size is by default 64 kilobytes. The maximum buffer size
-allowed to be set is 2 megabytes. The minimum buffer size allowed to be set is
-16 kilobytes.
-
-The upload buffer is allocated on-demand - so if the handle is not used for
-upload, this buffer is not allocated at all.
-
-DO NOT set this option on a handle that is currently used for an active
-transfer as that may lead to unintended consequences.
-.SH DEFAULT
-65536 bytes
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/foo.bin");
-
- /* ask libcurl to allocate a larger upload buffer */
- curl_easy_setopt(curl, CURLOPT_UPLOAD_BUFFERSIZE, 120000L);
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.62.0.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_BUFFERSIZE (3),
-.BR CURLOPT_READFUNCTION (3),
-.BR CURLOPT_TCP_NODELAY (3)
diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md b/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md
new file mode 100644
index 000000000..f32a45f98
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_UPLOAD_BUFFERSIZE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_BUFFERSIZE (3)
+ - CURLOPT_READFUNCTION (3)
+ - CURLOPT_TCP_NODELAY (3)
+---
+
+# NAME
+
+CURLOPT_UPLOAD_BUFFERSIZE - upload buffer size
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD_BUFFERSIZE, long size);
+~~~
+
+# DESCRIPTION
+
+Pass a long specifying your preferred *size* (in bytes) for the upload
+buffer in libcurl. It makes libcurl uses a larger buffer that gets passed to
+the next layer in the stack to get sent off. In some setups and for some
+protocols, there is a huge performance benefit of having a larger upload
+buffer.
+
+This is just treated as a request, not an order. You cannot be guaranteed to
+actually get the given size.
+
+The upload buffer size is by default 64 kilobytes. The maximum buffer size
+allowed to be set is 2 megabytes. The minimum buffer size allowed to be set is
+16 kilobytes.
+
+The upload buffer is allocated on-demand - so if the handle is not used for
+upload, this buffer is not allocated at all.
+
+DO NOT set this option on a handle that is currently used for an active
+transfer as that may lead to unintended consequences.
+
+# DEFAULT
+
+65536 bytes
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com/foo.bin");
+
+ /* ask libcurl to allocate a larger upload buffer */
+ curl_easy_setopt(curl, CURLOPT_UPLOAD_BUFFERSIZE, 120000L);
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.62.0.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_URL.3 b/docs/libcurl/opts/CURLOPT_URL.3
deleted file mode 100644
index b53025b6d..000000000
--- a/docs/libcurl/opts/CURLOPT_URL.3
+++ /dev/null
@@ -1,141 +0,0 @@
-
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_URL 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_URL \- URL for this transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);
-.fi
-.SH DESCRIPTION
-Pass in a pointer to the \fIURL\fP to work with. The parameter should be a
-char * to a null-terminated string which must be URL-encoded in the following
-format:
-
-scheme://host:port/path
-
-For a greater explanation of the format please see RFC 3986.
-
-libcurl does not validate the syntax or use the URL until the transfer is
-started. Even if you set a crazy value here, \fIcurl_easy_setopt(3)\fP might
-still return \fICURLE_OK\fP.
-
-If the given URL is missing a scheme name (such as "http://" or "ftp://" etc)
-then libcurl guesses based on the host. If the outermost subdomain name
-matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that protocol gets used,
-otherwise HTTP is used. Since 7.45.0 guessing can be disabled by setting a
-default protocol, see \fICURLOPT_DEFAULT_PROTOCOL(3)\fP for details.
-
-Should the protocol, either as specified by the URL scheme or deduced by
-libcurl from the host name, not be supported by libcurl then
-\fICURLE_UNSUPPORTED_PROTOCOL\fP is returned from either the
-\fIcurl_easy_perform(3)\fP or \fIcurl_multi_perform(3)\fP functions when you
-call them. Use \fIcurl_version_info(3)\fP for detailed information of which
-protocols are supported by the build of libcurl you are using.
-
-\fICURLOPT_PROTOCOLS_STR(3)\fP can be used to limit what protocols libcurl may
-use for this transfer, independent of what libcurl has been compiled to
-support. That may be useful if you accept the URL from an external source and
-want to limit the accessibility.
-
-The \fICURLOPT_URL(3)\fP string is ignored if \fICURLOPT_CURLU(3)\fP is set.
-
-Either \fICURLOPT_URL(3)\fP or \fICURLOPT_CURLU(3)\fP must be set before a
-transfer is started.
-
-The application does not have to keep the string around after setting this
-option.
-
-The parser used for handling the URL set with \fICURLOPT_URL(3)\fP is the same
-that \fIcurl_url_set(3)\fP uses.
-.SH ENCODING
-The string pointed to in the \fICURLOPT_URL(3)\fP argument is generally
-expected to be a sequence of characters using an ASCII compatible encoding.
-
-If libcurl is built with IDN support, the server name part of the URL can use
-an "international name" by using the current encoding (according to locale) or
-UTF-8 (when winidn is used; or a Windows Unicode build using libidn2).
-
-If libcurl is built without IDN support, the server name is used exactly as
-specified when passed to the name resolver functions.
-.SH DEFAULT
-There is no default URL. If this option is not set, no transfer can be
-performed.
-.SH SECURITY CONCERNS
-Applications may at times find it convenient to allow users to specify URLs
-for various purposes and that string would then end up fed to this option.
-
-Getting a URL from an external untrusted party brings several security
-concerns:
-
-If you have an application that runs as or in a server application, getting an
-unfiltered URL can easily trick your application to access a local resource
-instead of a remote. Protecting yourself against localhost accesses is hard
-when accepting user provided URLs.
-
-Such custom URLs can also access other ports than you planned as port numbers
-are part of the regular URL format. The combination of a local host and a
-custom port number can allow external users to play tricks with your local
-services.
-
-Accepting external URLs may also use other protocols than http:// or other
-common ones. Restrict what accept with \fICURLOPT_PROTOCOLS(3)\fP.
-
-User provided URLs can also be made to point to sites that redirect further on
-(possibly to other protocols too). Consider your
-\fICURLOPT_FOLLOWLOCATION(3)\fP and \fICURLOPT_REDIR_PROTOCOLS(3)\fP settings.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-POP3 and SMTP were added in 7.31.0
-.SH RETURN VALUE
-Returns CURLE_OK on success or CURLE_OUT_OF_MEMORY if there was insufficient
-heap space.
-
-Note that \fIcurl_easy_setopt(3)\fP does not parse the given string so given a
-bad URL, it is not detected until \fIcurl_easy_perform(3)\fP or similar is
-called.
-.SH "SEE ALSO"
-.BR curl_easy_perform (3),
-.BR curl_url_get (3),
-.BR curl_url_set (3),
-.BR CURLINFO_REDIRECT_URL (3),
-.BR CURLOPT_CURLU (3),
-.BR CURLOPT_FORBID_REUSE (3),
-.BR CURLOPT_FRESH_CONNECT (3),
-.BR CURLOPT_PATH_AS_IS (3),
-.BR CURLOPT_PROTOCOLS (3)
diff --git a/docs/libcurl/opts/CURLOPT_URL.md b/docs/libcurl/opts/CURLOPT_URL.md
new file mode 100644
index 000000000..3a0691bfc
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_URL.md
@@ -0,0 +1,145 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_URL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLINFO_REDIRECT_URL (3)
+ - CURLOPT_CURLU (3)
+ - CURLOPT_FORBID_REUSE (3)
+ - CURLOPT_FRESH_CONNECT (3)
+ - CURLOPT_PATH_AS_IS (3)
+ - CURLOPT_PROTOCOLS (3)
+ - curl_easy_perform (3)
+ - curl_url_get (3)
+ - curl_url_set (3)
+---
+
+# NAME
+
+CURLOPT_URL - URL for this transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);
+~~~
+
+# DESCRIPTION
+
+Pass in a pointer to the *URL* to work with. The parameter should be a
+char * to a null-terminated string which must be URL-encoded in the following
+format:
+
+scheme://host:port/path
+
+For a greater explanation of the format please see RFC 3986.
+
+libcurl does not validate the syntax or use the URL until the transfer is
+started. Even if you set a crazy value here, curl_easy_setopt(3) might
+still return *CURLE_OK*.
+
+If the given URL is missing a scheme name (such as "http://" or "ftp://" etc)
+then libcurl guesses based on the host. If the outermost subdomain name
+matches DICT, FTP, IMAP, LDAP, POP3 or SMTP then that protocol gets used,
+otherwise HTTP is used. Since 7.45.0 guessing can be disabled by setting a
+default protocol, see CURLOPT_DEFAULT_PROTOCOL(3) for details.
+
+Should the protocol, either as specified by the URL scheme or deduced by
+libcurl from the hostname, not be supported by libcurl then
+*CURLE_UNSUPPORTED_PROTOCOL* is returned from either the curl_easy_perform(3)
+or curl_multi_perform(3) functions when you call them. Use
+curl_version_info(3) for detailed information of which protocols are supported
+by the build of libcurl you are using.
+
+CURLOPT_PROTOCOLS_STR(3) can be used to limit what protocols libcurl may
+use for this transfer, independent of what libcurl has been compiled to
+support. That may be useful if you accept the URL from an external source and
+want to limit the accessibility.
+
+The CURLOPT_URL(3) string is ignored if CURLOPT_CURLU(3) is set.
+
+Either CURLOPT_URL(3) or CURLOPT_CURLU(3) must be set before a
+transfer is started.
+
+The application does not have to keep the string around after setting this
+option.
+
+The parser used for handling the URL set with CURLOPT_URL(3) is the same
+that curl_url_set(3) uses.
+
+# ENCODING
+
+The string pointed to in the CURLOPT_URL(3) argument is generally
+expected to be a sequence of characters using an ASCII compatible encoding.
+
+If libcurl is built with IDN support, the server name part of the URL can use
+an "international name" by using the current encoding (according to locale) or
+UTF-8 (when winidn is used; or a Windows Unicode build using libidn2).
+
+If libcurl is built without IDN support, the server name is used exactly as
+specified when passed to the name resolver functions.
+
+# DEFAULT
+
+There is no default URL. If this option is not set, no transfer can be
+performed.
+
+# SECURITY CONCERNS
+
+Applications may at times find it convenient to allow users to specify URLs
+for various purposes and that string would then end up fed to this option.
+
+Getting a URL from an external untrusted party brings several security
+concerns:
+
+If you have an application that runs as or in a server application, getting an
+unfiltered URL can easily trick your application to access a local resource
+instead of a remote. Protecting yourself against localhost accesses is hard
+when accepting user provided URLs.
+
+Such custom URLs can also access other ports than you planned as port numbers
+are part of the regular URL format. The combination of a local host and a
+custom port number can allow external users to play tricks with your local
+services.
+
+Accepting external URLs may also use other protocols than http:// or other
+common ones. Restrict what accept with CURLOPT_PROTOCOLS(3).
+
+User provided URLs can also be made to point to sites that redirect further on
+(possibly to other protocols too). Consider your
+CURLOPT_FOLLOWLOCATION(3) and CURLOPT_REDIR_PROTOCOLS(3) settings.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+POP3 and SMTP were added in 7.31.0
+
+# RETURN VALUE
+
+Returns CURLE_OK on success or CURLE_OUT_OF_MEMORY if there was insufficient
+heap space.
+
+Note that curl_easy_setopt(3) does not parse the given string so given a
+bad URL, it is not detected until curl_easy_perform(3) or similar is
+called.
diff --git a/docs/libcurl/opts/CURLOPT_USERAGENT.3 b/docs/libcurl/opts/CURLOPT_USERAGENT.3
deleted file mode 100644
index b8955aaec..000000000
--- a/docs/libcurl/opts/CURLOPT_USERAGENT.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_USERAGENT 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_USERAGENT \- HTTP user-agent header
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERAGENT, char *ua);
-.fi
-.SH DESCRIPTION
-Pass a pointer to a null-terminated string as parameter. It is used to set the
-User-Agent: header field in the HTTP request sent to the remote server. You
-can also set any custom header with \fICURLOPT_HTTPHEADER(3)\fP.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL, no User-Agent: header is used by default.
-.SH PROTOCOLS
-HTTP, HTTPS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- curl_easy_setopt(curl, CURLOPT_USERAGENT, "Dark Secret Ninja/1.0");
-
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-As long as HTTP is supported
-.SH RETURN VALUE
-Returns CURLE_OK if HTTP is supported, CURLE_UNKNOWN_OPTION if not, or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_CUSTOMREQUEST (3),
-.BR CURLOPT_HTTPHEADER (3),
-.BR CURLOPT_REFERER (3),
-.BR CURLOPT_REQUEST_TARGET (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_USERAGENT.md b/docs/libcurl/opts/CURLOPT_USERAGENT.md
new file mode 100644
index 000000000..a5423def0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_USERAGENT.md
@@ -0,0 +1,66 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_USERAGENT
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CUSTOMREQUEST (3)
+ - CURLOPT_HTTPHEADER (3)
+ - CURLOPT_REFERER (3)
+ - CURLOPT_REQUEST_TARGET (3)
+---
+
+# NAME
+
+CURLOPT_USERAGENT - HTTP user-agent header
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERAGENT, char *ua);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to a null-terminated string as parameter. It is used to set the
+User-Agent: header field in the HTTP request sent to the remote server. You
+can also set any custom header with CURLOPT_HTTPHEADER(3).
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL, no User-Agent: header is used by default.
+
+# PROTOCOLS
+
+HTTP, HTTPS
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "Dark Secret Ninja/1.0");
+
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+As long as HTTP is supported
+
+# RETURN VALUE
+
+Returns CURLE_OK if HTTP is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_USERNAME.3 b/docs/libcurl/opts/CURLOPT_USERNAME.3
deleted file mode 100644
index d72741e85..000000000
--- a/docs/libcurl/opts/CURLOPT_USERNAME.3
+++ /dev/null
@@ -1,89 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_USERNAME 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_USERNAME \- user name to use in authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERNAME,
- char *username);
-.SH DESCRIPTION
-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
-authentication. You should not use this option together with the (older)
-\fICURLOPT_USERPWD(3)\fP option.
-
-When using Kerberos V5 authentication with a Windows based server, you should
-include the domain name in order for the server to successfully obtain a
-Kerberos Ticket. If you do not then the initial part of the authentication
-handshake may fail.
-
-When using NTLM, the user name can be specified simply as the user name
-without the domain name should the server be part of a single domain and
-forest.
-
-To include the domain name use either Down-Level Logon Name or UPN (User
-Principal Name) formats. For example, EXAMPLE\\user and user@example.com
-respectively.
-
-Some HTTP servers (on Windows) support inclusion of the domain for Basic
-authentication as well.
-
-To specify the password and login options, along with the user name, use the
-\fICURLOPT_PASSWORD(3)\fP and \fICURLOPT_LOGIN_OPTIONS(3)\fP options.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-blank
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- curl_easy_setopt(curl, CURLOPT_USERNAME, "clark");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.19.1
-.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_USERPWD (3),
-.BR CURLOPT_PASSWORD (3),
-.BR CURLOPT_HTTPAUTH (3),
-.BR CURLOPT_PROXYAUTH (3)
diff --git a/docs/libcurl/opts/CURLOPT_USERNAME.md b/docs/libcurl/opts/CURLOPT_USERNAME.md
new file mode 100644
index 000000000..f74817801
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_USERNAME.md
@@ -0,0 +1,92 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_USERNAME
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HTTPAUTH (3)
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_PROXYAUTH (3)
+ - CURLOPT_USERPWD (3)
+---
+
+# NAME
+
+CURLOPT_USERNAME - user name to use in authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERNAME,
+ char *username);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should be pointing to the
+null-terminated user name to use for the transfer.
+
+CURLOPT_USERNAME(3) sets the user name to be used in protocol
+authentication. You should not use this option together with the (older)
+CURLOPT_USERPWD(3) option.
+
+When using Kerberos V5 authentication with a Windows based server, you should
+include the domain name in order for the server to successfully obtain a
+Kerberos Ticket. If you do not then the initial part of the authentication
+handshake may fail.
+
+When using NTLM, the user name can be specified simply as the user name
+without the domain name should the server be part of a single domain and
+forest.
+
+To include the domain name use either Down-Level Logon Name or UPN (User
+Principal Name) formats. For example, **EXAMPLE\user** and
+**user@example.com** respectively.
+
+Some HTTP servers (on Windows) support inclusion of the domain for Basic
+authentication as well.
+
+To specify the password and login options, along with the user name, use the
+CURLOPT_PASSWORD(3) and CURLOPT_LOGIN_OPTIONS(3) options.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+blank
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ curl_easy_setopt(curl, CURLOPT_USERNAME, "clark");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.19.1
+
+# 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.
diff --git a/docs/libcurl/opts/CURLOPT_USERPWD.3 b/docs/libcurl/opts/CURLOPT_USERPWD.3
deleted file mode 100644
index cbb1e00b2..000000000
--- a/docs/libcurl/opts/CURLOPT_USERPWD.3
+++ /dev/null
@@ -1,96 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_USERPWD 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_USERPWD \- user name and password to use in authentication
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERPWD, char *userpwd);
-.fi
-.SH DESCRIPTION
-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
-specify the user name part with the domain name in order for the server to
-successfully obtain a Kerberos Ticket. If you do not then the initial part of
-the authentication handshake may fail.
-
-When using NTLM, the user name can be specified simply as the user name
-without the domain name should the server be part of a single domain and
-forest.
-
-To specify the domain name use either Down-Level Logon Name or UPN (User
-Principal Name) formats. For example, EXAMPLE\\user and user@example.com
-respectively.
-
-Some HTTP servers (on Windows) support inclusion of the domain for Basic
-authentication as well.
-
-When using HTTP and \fICURLOPT_FOLLOWLOCATION(3)\fP, libcurl might perform
-several requests to possibly different hosts. libcurl only sends this user and
-password information to hosts using the initial host name (unless
-\fICURLOPT_UNRESTRICTED_AUTH(3)\fP is set), so if libcurl follows redirects to
-other hosts, it does not send the user and password to those. This is enforced
-to prevent accidental information leakage.
-
-Use \fICURLOPT_HTTPAUTH(3)\fP to specify the authentication method for HTTP
-based connections or \fICURLOPT_LOGIN_OPTIONS(3)\fP to control IMAP, POP3 and
-SMTP options.
-
-The user and password strings are not URL decoded, so there is no way to send
-in a user name containing a colon using this option. Use
-\fICURLOPT_USERNAME(3)\fP for that, or include it in the URL.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-Most
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
-
- curl_easy_setopt(curl, CURLOPT_USERPWD, "clark:kent");
-
- ret = curl_easy_perform(curl);
-
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK on success or
-CURLE_OUT_OF_MEMORY if there was insufficient heap space.
-.SH "SEE ALSO"
-.BR CURLOPT_USERNAME (3),
-.BR CURLOPT_PASSWORD (3),
-.BR CURLOPT_PROXYUSERPWD (3)
diff --git a/docs/libcurl/opts/CURLOPT_USERPWD.md b/docs/libcurl/opts/CURLOPT_USERPWD.md
new file mode 100644
index 000000000..01c65207a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_USERPWD.md
@@ -0,0 +1,98 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_USERPWD
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PASSWORD (3)
+ - CURLOPT_PROXYUSERPWD (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_USERPWD - user name and password to use in authentication
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERPWD, char *userpwd);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer 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
+specify the user name part with the domain name in order for the server to
+successfully obtain a Kerberos Ticket. If you do not then the initial part of
+the authentication handshake may fail.
+
+When using NTLM, the user name can be specified simply as the user name
+without the domain name should the server be part of a single domain and
+forest.
+
+To specify the domain name use either Down-Level Logon Name or UPN (User
+Principal Name) formats. For example **EXAMPLE\user** and **user@example.com**
+respectively.
+
+Some HTTP servers (on Windows) support inclusion of the domain for Basic
+authentication as well.
+
+When using HTTP and CURLOPT_FOLLOWLOCATION(3), libcurl might perform several
+requests to possibly different hosts. libcurl only sends this user and
+password information to hosts using the initial hostname (unless
+CURLOPT_UNRESTRICTED_AUTH(3) is set), so if libcurl follows redirects to other
+hosts, it does not send the user and password to those. This is enforced to
+prevent accidental information leakage.
+
+Use CURLOPT_HTTPAUTH(3) to specify the authentication method for HTTP
+based connections or CURLOPT_LOGIN_OPTIONS(3) to control IMAP, POP3 and
+SMTP options.
+
+The user and password strings are not URL decoded, so there is no way to send
+in a user name containing a colon using this option. Use
+CURLOPT_USERNAME(3) for that, or include it in the URL.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+Most
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin");
+
+ curl_easy_setopt(curl, CURLOPT_USERPWD, "clark:kent");
+
+ res = curl_easy_perform(curl);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK on success or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
diff --git a/docs/libcurl/opts/CURLOPT_USE_SSL.3 b/docs/libcurl/opts/CURLOPT_USE_SSL.3
deleted file mode 100644
index 22465755e..000000000
--- a/docs/libcurl/opts/CURLOPT_USE_SSL.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_USE_SSL 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_USE_SSL \- request using SSL / TLS for the transfer
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USE_SSL, long level);
-.fi
-.SH DESCRIPTION
-Pass a long using one of the values from below, to make libcurl use your
-desired \fIlevel\fP of SSL for the transfer.
-
-These are all protocols that start out plain text and get "upgraded" to SSL
-using the STARTTLS command.
-
-This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc.
-.IP CURLUSESSL_NONE
-do not attempt to use SSL.
-.IP CURLUSESSL_TRY
-Try using SSL, proceed as normal otherwise. Note that server may close the
-connection if the negotiation does not succeed.
-.IP CURLUSESSL_CONTROL
-Require SSL for the control connection or fail with \fICURLE_USE_SSL_FAILED\fP.
-.IP CURLUSESSL_ALL
-Require SSL for all communication or fail with \fICURLE_USE_SSL_FAILED\fP.
-.SH DEFAULT
-CURLUSESSL_NONE
-.SH PROTOCOLS
-FTP, SMTP, POP3, IMAP, LDAP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/file.ext");
-
- /* require use of SSL for this, or fail */
- curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.11.0. This option was known as CURLOPT_FTP_SSL up to 7.16.4, and
-the constants were known as CURLFTPSSL_*
-Handled by LDAP since 7.81.0. Fully supported by the OpenLDAP backend only.
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_SSLVERSION (3),
-.BR CURLOPT_PROXY_SSLVERSION (3),
-.BR CURLOPT_SSL_OPTIONS (3)
diff --git a/docs/libcurl/opts/CURLOPT_USE_SSL.md b/docs/libcurl/opts/CURLOPT_USE_SSL.md
new file mode 100644
index 000000000..3e227fcfd
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_USE_SSL.md
@@ -0,0 +1,86 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_USE_SSL
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_PROXY_SSLVERSION (3)
+ - CURLOPT_SSLVERSION (3)
+ - CURLOPT_SSL_OPTIONS (3)
+---
+
+# NAME
+
+CURLOPT_USE_SSL - request using SSL / TLS for the transfer
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USE_SSL, long level);
+~~~
+
+# DESCRIPTION
+
+Pass a long using one of the values from below, to make libcurl use your
+desired *level* of SSL for the transfer.
+
+These are all protocols that start out plain text and get "upgraded" to SSL
+using the STARTTLS command.
+
+This is for enabling SSL/TLS when you use FTP, SMTP, POP3, IMAP etc.
+
+## CURLUSESSL_NONE
+
+do not attempt to use SSL.
+
+## CURLUSESSL_TRY
+
+Try using SSL, proceed as normal otherwise. Note that server may close the
+connection if the negotiation does not succeed.
+
+## CURLUSESSL_CONTROL
+
+Require SSL for the control connection or fail with *CURLE_USE_SSL_FAILED*.
+
+## CURLUSESSL_ALL
+
+Require SSL for all communication or fail with *CURLE_USE_SSL_FAILED*.
+
+# DEFAULT
+
+CURLUSESSL_NONE
+
+# PROTOCOLS
+
+FTP, SMTP, POP3, IMAP, LDAP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/file.ext");
+
+ /* require use of SSL for this, or fail */
+ curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.11.0. This option was known as CURLOPT_FTP_SSL up to 7.16.4, and
+the constants were known as CURLFTPSSL_*
+Handled by LDAP since 7.81.0. Fully supported by the OpenLDAP backend only.
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_VERBOSE.3 b/docs/libcurl/opts/CURLOPT_VERBOSE.3
deleted file mode 100644
index 003a5eb1e..000000000
--- a/docs/libcurl/opts/CURLOPT_VERBOSE.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_VERBOSE 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_VERBOSE \- verbose mode
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_VERBOSE, long onoff);
-.fi
-.SH DESCRIPTION
-Set the \fIonoff\fP parameter to 1 to make the library display a lot of
-verbose information about its operations on this \fIhandle\fP. Useful for
-libcurl and/or protocol debugging and understanding. The verbose information
-is sent to stderr, or the stream set with \fICURLOPT_STDERR(3)\fP.
-
-You hardly ever want this enabled in production use, you almost always want
-this used when you debug/report problems.
-
-To also get all the protocol data sent and received, consider using the
-\fICURLOPT_DEBUGFUNCTION(3)\fP.
-.SH DEFAULT
-0, meaning disabled.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
-
- /* ask libcurl to show us the verbose output */
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-
- /* Perform the request */
- curl_easy_perform(curl);
-}
-.fi
-.SH AVAILABILITY
-Always
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_STDERR (3),
-.BR CURLOPT_DEBUGFUNCTION (3),
-.BR CURLOPT_ERRORBUFFER (3),
-.BR curl_global_trace (3)
diff --git a/docs/libcurl/opts/CURLOPT_VERBOSE.md b/docs/libcurl/opts/CURLOPT_VERBOSE.md
new file mode 100644
index 000000000..5ecc4b11a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_VERBOSE.md
@@ -0,0 +1,71 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_VERBOSE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_DEBUGFUNCTION (3)
+ - CURLOPT_ERRORBUFFER (3)
+ - CURLOPT_STDERR (3)
+ - curl_global_trace (3)
+---
+
+# NAME
+
+CURLOPT_VERBOSE - verbose mode
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_VERBOSE, long onoff);
+~~~
+
+# DESCRIPTION
+
+Set the *onoff* parameter to 1 to make the library display a lot of
+verbose information about its operations on this *handle*. Useful for
+libcurl and/or protocol debugging and understanding. The verbose information
+is sent to stderr, or the stream set with CURLOPT_STDERR(3).
+
+You hardly ever want this enabled in production use, you almost always want
+this used when you debug/report problems.
+
+To also get all the protocol data sent and received, consider using the
+CURLOPT_DEBUGFUNCTION(3).
+
+# DEFAULT
+
+0, meaning disabled.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
+
+ /* ask libcurl to show us the verbose output */
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+ /* Perform the request */
+ curl_easy_perform(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Always
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3 b/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3
deleted file mode 100644
index be1c465a4..000000000
--- a/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.3
+++ /dev/null
@@ -1,111 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_WILDCARDMATCH 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_WILDCARDMATCH \- directory wildcard transfers
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WILDCARDMATCH, long onoff);
-.fi
-.SH DESCRIPTION
-Set \fIonoff\fP to 1 if you want to transfer multiple files according to a
-file name pattern. The pattern can be specified as part of the
-\fICURLOPT_URL(3)\fP option, using an \fBfnmatch\fP-like pattern (Shell
-Pattern Matching) in the last part of URL (file name).
-
-By default, libcurl uses its internal wildcard matching implementation. You
-can provide your own matching function by the
-\fICURLOPT_FNMATCH_FUNCTION(3)\fP option.
-
-A brief introduction of its syntax follows:
-.RS
-.IP "* - ASTERISK"
-.nf
- ftp://example.com/some/path/*.txt
-.fi
-for all txt's from the root directory. Only two asterisks are allowed within
-the same pattern string.
-.RE
-.RS
-.IP "? - QUESTION MARK"
-Question mark matches any (exactly one) character.
-.nf
- ftp://example.com/some/path/photo?.jpg
-.fi
-.RE
-.RS
-.IP "[ - BRACKET EXPRESSION"
-The left bracket opens a bracket expression. The question mark and asterisk have
-no special meaning in a bracket expression. Each bracket expression ends by the
-right bracket and matches exactly one character. Some examples follow:
-
-\fB[a-zA-Z0\-9]\fP or \fB[f\-gF\-G]\fP \- character interval
-
-\fB[abc]\fP - character enumeration
-
-\fB[^abc]\fP or \fB[!abc]\fP - negation
-
-\fB[[:name:]]\fP class expression. Supported classes are
-\fBalnum\fP,\fBlower\fP, \fBspace\fP, \fBalpha\fP, \fBdigit\fP, \fBprint\fP,
-\fBupper\fP, \fBblank\fP, \fBgraph\fP, \fBxdigit\fP.
-
-\fB[][-!^]\fP - special case \- matches only '\-', ']', '[', '!' or '^'. These
-characters have no special purpose.
-
-\fB[\\[\\]\\\\]\fP - escape syntax. Matches '[', ']' or '\e'.
-
-Using the rules above, a file name pattern can be constructed:
-.nf
- ftp://example.com/some/path/[a-z[:upper:]\\\\].jpg
-.fi
-.SH PROTOCOLS
-This feature is only supported for FTP download.
-.SH EXAMPLE
-.nf
-/* initialization of easy handle */
-handle = curl_easy_init();
-
-/* turn on wildcard matching */
-curl_easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L);
-
-/* callback is called before download of concrete file started */
-curl_easy_setopt(handle, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming);
-
-/* callback is called after data from the file have been transferred */
-curl_easy_setopt(handle, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);
-
-/* See more on https://curl.se/libcurl/c/ftp-wildcard.html */
-.fi
-.SH AVAILABILITY
-Added in 7.21.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_CHUNK_BGN_FUNCTION (3),
-.BR CURLOPT_CHUNK_END_FUNCTION (3),
-.BR CURLOPT_FNMATCH_FUNCTION (3),
-.BR CURLOPT_URL (3)
diff --git a/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.md b/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.md
new file mode 100644
index 000000000..754126567
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_WILDCARDMATCH.md
@@ -0,0 +1,111 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_WILDCARDMATCH
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CHUNK_BGN_FUNCTION (3)
+ - CURLOPT_CHUNK_END_FUNCTION (3)
+ - CURLOPT_FNMATCH_FUNCTION (3)
+ - CURLOPT_URL (3)
+---
+
+# NAME
+
+CURLOPT_WILDCARDMATCH - directory wildcard transfers
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WILDCARDMATCH, long onoff);
+~~~
+
+# DESCRIPTION
+
+Set *onoff* to 1 if you want to transfer multiple files according to a
+filename pattern. The pattern can be specified as part of the CURLOPT_URL(3)
+option, using an **fnmatch**-like pattern (Shell Pattern Matching) in the last
+part of URL (filename).
+
+By default, libcurl uses its internal wildcard matching implementation. You
+can provide your own matching function by the
+CURLOPT_FNMATCH_FUNCTION(3) option.
+
+A brief introduction of its syntax follows:
+
+## * - ASTERISK
+
+ ftp://example.com/some/path/*.txt
+
+for all txt's from the root directory. Only two asterisks are allowed within
+the same pattern string.
+
+## ? - QUESTION MARK
+
+Question mark matches any (exactly one) character.
+
+ ftp://example.com/some/path/photo?.jpg
+
+## [ - BRACKET EXPRESSION
+
+The left bracket opens a bracket expression. The question mark and asterisk have
+no special meaning in a bracket expression. Each bracket expression ends by the
+right bracket and matches exactly one character. Some examples follow:
+
+**[a-zA-Z0-9]** or **[f-gF-G]** - character interval
+
+**[abc]** - character enumeration
+
+**[^abc]** or **[!abc]** - negation
+
+**[[:name:]]** class expression. Supported classes are **alnum**,**lower**,
+**space**, **alpha**, **digit**, **print**, **upper**, **blank**, **graph**,
+**xdigit**.
+
+**[][-!^]** - special case - matches only '-', ']', '[', '!' or '^'. These
+characters have no special purpose.
+
+**[[]]** - escape syntax. Matches '[', ']' or 'e'.
+
+Using the rules above, a filename pattern can be constructed:
+
+ ftp://example.com/some/path/[a-z[:upper:]\\].jpg
+
+# PROTOCOLS
+
+This feature is only supported for FTP download.
+
+# EXAMPLE
+
+~~~c
+extern long begin_cb(struct curl_fileinfo *, void *, int);
+extern long end_cb(void *ptr);
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* turn on wildcard matching */
+ curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L);
+
+ /* callback is called before download of concrete file started */
+ curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, begin_cb);
+
+ /* callback is called after data from the file have been transferred */
+ curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, end_cb);
+
+ /* See more on https://curl.se/libcurl/c/ftp-wildcard.html */
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.21.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_WRITEDATA.3 b/docs/libcurl/opts/CURLOPT_WRITEDATA.3
deleted file mode 100644
index 6dc099506..000000000
--- a/docs/libcurl/opts/CURLOPT_WRITEDATA.3
+++ /dev/null
@@ -1,65 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_WRITEDATA 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_WRITEDATA \- pointer passed to the write callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);
-.fi
-.SH DESCRIPTION
-A data \fIpointer\fP to pass to the write callback. If you use the
-\fICURLOPT_WRITEFUNCTION(3)\fP option, this is the pointer you get in that
-callback's fourth and last argument. If you do not use a write callback, you
-must make \fIpointer\fP a 'FILE *' (cast to 'void *') as libcurl passes this
-to \fIfwrite(3)\fP when writing data.
-
-The internal \fICURLOPT_WRITEFUNCTION(3)\fP writes the data to the FILE *
-given with this option, or to stdout if this option has not been set.
-
-If you are using libcurl as a Windows DLL, you \fBMUST\fP use a
-\fICURLOPT_WRITEFUNCTION(3)\fP if you set this option or you might experience
-crashes.
-.SH DEFAULT
-By default, this is a FILE * to stdout.
-.SH PROTOCOLS
-Used for all protocols.
-.SH EXAMPLE
-A common technique is to use the write callback to store the incoming data
-into a dynamically growing allocated buffer, and then this
-\fICURLOPT_WRITEDATA(3)\fP is used to point to a struct or the buffer to store
-data in. Like in the getinmemory example:
-https://curl.se/libcurl/c/getinmemory.html
-.SH AVAILABILITY
-Available in all libcurl versions. This option was formerly known as
-CURLOPT_FILE, the name \fICURLOPT_WRITEDATA(3)\fP was added in 7.9.7.
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_WRITEFUNCTION (3),
-.BR CURLOPT_HEADERDATA (3),
-.BR CURLOPT_READDATA (3)
diff --git a/docs/libcurl/opts/CURLOPT_WRITEDATA.md b/docs/libcurl/opts/CURLOPT_WRITEDATA.md
new file mode 100644
index 000000000..495c6bf9c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_WRITEDATA.md
@@ -0,0 +1,63 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_WRITEDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERDATA (3)
+ - CURLOPT_READDATA (3)
+ - CURLOPT_WRITEFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_WRITEDATA - pointer passed to the write callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEDATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+A data *pointer* to pass to the write callback. If you use the
+CURLOPT_WRITEFUNCTION(3) option, this is the pointer you get in that
+callback's fourth and last argument. If you do not use a write callback, you
+must make *pointer* a 'FILE *' (cast to 'void *') as libcurl passes this
+to *fwrite(3)* when writing data.
+
+The internal CURLOPT_WRITEFUNCTION(3) writes the data to the FILE *
+given with this option, or to stdout if this option has not been set.
+
+If you are using libcurl as a Windows DLL, you **MUST** use a
+CURLOPT_WRITEFUNCTION(3) if you set this option or you might experience
+crashes.
+
+# DEFAULT
+
+By default, this is a FILE * to stdout.
+
+# PROTOCOLS
+
+Used for all protocols.
+
+# EXAMPLE
+
+A common technique is to use the write callback to store the incoming data
+into a dynamically growing allocated buffer, and then this
+CURLOPT_WRITEDATA(3) is used to point to a struct or the buffer to store
+data in. Like in the getinmemory example:
+https://curl.se/libcurl/c/getinmemory.html
+
+# AVAILABILITY
+
+Available in all libcurl versions. This option was formerly known as
+CURLOPT_FILE, the name CURLOPT_WRITEDATA(3) was added in 7.9.7.
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3 b/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3
deleted file mode 100644
index 083b008b4..000000000
--- a/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.3
+++ /dev/null
@@ -1,133 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_WRITEFUNCTION 3 "16 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_WRITEFUNCTION \- callback for writing received data
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This callback function gets called by libcurl as soon as there is data
-received that needs to be saved. For most transfers, this callback gets called
-many times and each invoke delivers another chunk of data. \fIptr\fP points to
-the delivered data, and the size of that data is \fInmemb\fP; \fIsize\fP is
-always 1.
-
-The callback function is passed as much data as possible in all invokes, but
-you must not make any assumptions. It may be one byte, it may be
-thousands. The maximum amount of body data that is be passed to the write
-callback is defined in the curl.h header file: \fICURL_MAX_WRITE_SIZE\fP (the
-usual default is 16K). If \fICURLOPT_HEADER(3)\fP is enabled, which makes
-header data get passed to the write callback, you can get up to
-\fICURL_MAX_HTTP_HEADER\fP bytes of header data passed into it. This usually
-means 100K.
-
-This function may be called with zero bytes data if the transferred file is
-empty.
-
-The data passed to this function is not null-terminated!
-
-Set the \fIuserdata\fP argument with the \fICURLOPT_WRITEDATA(3)\fP option.
-
-Your callback should return the number of bytes actually taken care of. If
-that amount differs from the amount passed to your callback function, it
-signals an error condition to the library. This causes the transfer to get
-aborted and the libcurl function used returns \fICURLE_WRITE_ERROR\fP.
-
-You can also abort the transfer by returning CURL_WRITEFUNC_ERROR. (7.87.0)
-
-If the callback function returns CURL_WRITEFUNC_PAUSE it pauses this
-transfer. See \fIcurl_easy_pause(3)\fP for further details.
-
-Set this option to NULL to get the internal default function used instead of
-your callback. The internal default function writes the data to the FILE *
-given with \fICURLOPT_WRITEDATA(3)\fP.
-
-This option does not enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
-do that.
-.SH DEFAULT
-libcurl uses 'fwrite' as a callback by default.
-.SH PROTOCOLS
-For all protocols
-.SH EXAMPLE
-.nf
-struct memory {
- char *response;
- size_t size;
-};
-
-static size_t cb(void *data, size_t size, size_t nmemb, void *clientp)
-{
- size_t realsize = size * nmemb;
- struct memory *mem = (struct memory *)clientp;
-
- char *ptr = realloc(mem->response, mem->size + realsize + 1);
- if(ptr == NULL)
- return 0; /* out of memory! */
-
- mem->response = ptr;
- memcpy(&(mem->response[mem->size]), data, realsize);
- mem->size += realsize;
- mem->response[mem->size] = 0;
-
- return realsize;
-}
-
-struct memory chunk = {0};
-CURLcode res;
-CURL *curl_handle = curl_easy_init();
-
-if (curl_handle)
-{
- /* send all data to this function */
- curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, cb);
-
- /* we pass our 'chunk' struct to the callback function */
- curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
-
- /* send a request */
- res = curl_easy_perform(curl_handle);
-
- /* remember to free the buffer */
- free(chunk.response);
-
- curl_easy_cleanup(curl_handle);
-}
-.fi
-.SH AVAILABILITY
-Support for the CURL_WRITEFUNC_PAUSE return code was added in version 7.18.0.
-.SH RETURN VALUE
-This returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_WRITEDATA (3),
-.BR CURLOPT_READFUNCTION (3),
-.BR CURLOPT_HEADERFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md b/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md
new file mode 100644
index 000000000..8957439d3
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md
@@ -0,0 +1,136 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_WRITEFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_HEADERFUNCTION (3)
+ - CURLOPT_READFUNCTION (3)
+ - CURLOPT_WRITEDATA (3)
+---
+
+# NAME
+
+CURLOPT_WRITEFUNCTION - callback for writing received data
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This callback function gets called by libcurl as soon as there is data
+received that needs to be saved. For most transfers, this callback gets called
+many times and each invoke delivers another chunk of data. *ptr* points to the
+delivered data, and the size of that data is *nmemb*; *size* is always 1.
+
+The data passed to this function is not null-terminated.
+
+The callback function is passed as much data as possible in all invokes, but
+you must not make any assumptions. It may be one byte, it may be
+thousands. The maximum amount of body data that is be passed to the write
+callback is defined in the curl.h header file: *CURL_MAX_WRITE_SIZE* (the
+usual default is 16K). If CURLOPT_HEADER(3) is enabled, which makes header
+data get passed to the write callback, you can get up to
+*CURL_MAX_HTTP_HEADER* bytes of header data passed into it. This usually means
+100K.
+
+This function may be called with zero bytes data if the transferred file is
+empty.
+
+Set the *userdata* argument with the CURLOPT_WRITEDATA(3) option.
+
+Your callback should return the number of bytes actually taken care of. If
+that amount differs from the amount passed to your callback function, it
+signals an error condition to the library. This causes the transfer to get
+aborted and the libcurl function used returns *CURLE_WRITE_ERROR*.
+
+You can also abort the transfer by returning CURL_WRITEFUNC_ERROR (added in
+7.87.0), which makes *CURLE_WRITE_ERROR* get returned.
+
+If the callback function returns CURL_WRITEFUNC_PAUSE it pauses this
+transfer. See curl_easy_pause(3) for further details.
+
+Set this option to NULL to get the internal default function used instead of
+your callback. The internal default function writes the data to the FILE *
+given with CURLOPT_WRITEDATA(3).
+
+This option does not enable HSTS, you need to use CURLOPT_HSTS_CTRL(3) to
+do that.
+
+# DEFAULT
+
+libcurl uses 'fwrite' as a callback by default.
+
+# PROTOCOLS
+
+For all protocols
+
+# EXAMPLE
+
+~~~c
+#include <stdlib.h> /* for realloc */
+#include <string.h> /* for memcpy */
+
+struct memory {
+ char *response;
+ size_t size;
+};
+
+static size_t cb(void *data, size_t size, size_t nmemb, void *clientp)
+{
+ size_t realsize = size * nmemb;
+ struct memory *mem = (struct memory *)clientp;
+
+ char *ptr = realloc(mem->response, mem->size + realsize + 1);
+ if(!ptr)
+ return 0; /* out of memory! */
+
+ mem->response = ptr;
+ memcpy(&(mem->response[mem->size]), data, realsize);
+ mem->size += realsize;
+ mem->response[mem->size] = 0;
+
+ return realsize;
+}
+
+int main(void)
+{
+ struct memory chunk = {0};
+ CURLcode res;
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ /* send all data to this function */
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb);
+
+ /* we pass our 'chunk' struct to the callback function */
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+
+ /* send a request */
+ res = curl_easy_perform(curl);
+
+ /* remember to free the buffer */
+ free(chunk.response);
+
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Support for the CURL_WRITEFUNC_PAUSE return code was added in version 7.18.0.
+
+# RETURN VALUE
+
+This returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_WS_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_WS_OPTIONS.3
deleted file mode 100644
index 8321ec66b..000000000
--- a/docs/libcurl/opts/CURLOPT_WS_OPTIONS.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_WS_OPTIONS 3 "10 Jun 2022" libcurl libcurl
-.SH NAME
-CURLOPT_WS_OPTIONS \- WebSocket behavior options
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WS_OPTIONS, long bitmask);
-.fi
-.SH DESCRIPTION
-Pass a long with a bitmask to tell libcurl about specific WebSocket
-behaviors.
-
-To detach a WebSocket connection and use the \fIcurl_ws_send(3)\fP and
-\fIcurl_ws_recv(3)\fP functions after the HTTP upgrade procedure, set the
-\fICURLOPT_CONNECT_ONLY(3)\fP option to 2L.
-
-Available bits in the bitmask
-.IP "CURLWS_RAW_MODE (1)"
-Deliver "raw" WebSocket traffic to the \fICURLOPT_WRITEFUNCTION(3)\fP
-callback.
-
-In raw mode, libcurl does not handle pings or any other frame for the
-application.
-.SH DEFAULT
-0
-.SH PROTOCOLS
-WebSocket
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "ws://example.com/");
- /* tell curl we deal with all the WebSocket magic ourselves */
- curl_easy_setopt(curl, CURLOPT_WS_OPTIONS, (long)CURLWS_RAW_MODE);
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.86.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR curl_ws_recv (3),
-.BR curl_ws_send (3),
-.BR CURLOPT_CONNECT_ONLY (3)
diff --git a/docs/libcurl/opts/CURLOPT_WS_OPTIONS.md b/docs/libcurl/opts/CURLOPT_WS_OPTIONS.md
new file mode 100644
index 000000000..04af5bca8
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_WS_OPTIONS.md
@@ -0,0 +1,75 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_WS_OPTIONS
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_CONNECT_ONLY (3)
+ - curl_ws_recv (3)
+ - curl_ws_send (3)
+---
+
+# NAME
+
+CURLOPT_WS_OPTIONS - WebSocket behavior options
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WS_OPTIONS, long bitmask);
+~~~
+
+# DESCRIPTION
+
+Pass a long with a bitmask to tell libcurl about specific WebSocket
+behaviors.
+
+To detach a WebSocket connection and use the curl_ws_send(3) and
+curl_ws_recv(3) functions after the HTTP upgrade procedure, set the
+CURLOPT_CONNECT_ONLY(3) option to 2L.
+
+Available bits in the bitmask
+
+## CURLWS_RAW_MODE (1)
+
+Deliver "raw" WebSocket traffic to the CURLOPT_WRITEFUNCTION(3)
+callback.
+
+In raw mode, libcurl does not handle pings or any other frame for the
+application.
+
+# DEFAULT
+
+0
+
+# PROTOCOLS
+
+WebSocket
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "ws://example.com/");
+ /* tell curl we deal with all the WebSocket magic ourselves */
+ curl_easy_setopt(curl, CURLOPT_WS_OPTIONS, (long)CURLWS_RAW_MODE);
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.86.0
+
+# RETURN VALUE
+
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
diff --git a/docs/libcurl/opts/CURLOPT_XFERINFODATA.3 b/docs/libcurl/opts/CURLOPT_XFERINFODATA.3
deleted file mode 100644
index 5f04f9671..000000000
--- a/docs/libcurl/opts/CURLOPT_XFERINFODATA.3
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_XFERINFODATA 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_XFERINFODATA \- pointer passed to the progress callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XFERINFODATA, void *pointer);
-.fi
-.SH DESCRIPTION
-Pass a \fIpointer\fP that is untouched by libcurl and passed as the first
-argument in the progress callback set with \fICURLOPT_XFERINFOFUNCTION(3)\fP.
-
-This is an alias for \fICURLOPT_PROGRESSDATA(3)\fP.
-.SH DEFAULT
-The default value of this parameter is NULL.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- struct progress {
- char *private;
- size_t size;
- };
-
- static size_t progress_callback(void *clientp,
- curl_off_t dltotal,
- curl_off_t dlnow,
- curl_off_t ultotal,
- curl_off_t ulnow)
- {
- struct memory *progress = (struct progress *)clientp;
-
- /* use the values */
-
- return 0; /* all is good */
- }
-
- struct progress data;
-
- /* pass struct to callback */
- curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, &data);
-
- curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, progress_callback);
-.fi
-.SH AVAILABILITY
-Added in 7.32.0
-.SH RETURN VALUE
-Returns CURLE_OK
-.SH "SEE ALSO"
-.BR CURLOPT_NOPROGRESS (3),
-.BR CURLOPT_VERBOSE (3),
-.BR CURLOPT_XFERINFOFUNCTION (3)
diff --git a/docs/libcurl/opts/CURLOPT_XFERINFODATA.md b/docs/libcurl/opts/CURLOPT_XFERINFODATA.md
new file mode 100644
index 000000000..145057c5c
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_XFERINFODATA.md
@@ -0,0 +1,80 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_XFERINFODATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_NOPROGRESS (3)
+ - CURLOPT_VERBOSE (3)
+ - CURLOPT_XFERINFOFUNCTION (3)
+---
+
+# NAME
+
+CURLOPT_XFERINFODATA - pointer passed to the progress callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XFERINFODATA, void *pointer);
+~~~
+
+# DESCRIPTION
+
+Pass a *pointer* that is untouched by libcurl and passed as the first
+argument in the progress callback set with CURLOPT_XFERINFOFUNCTION(3).
+
+This is an alias for CURLOPT_PROGRESSDATA(3).
+
+# DEFAULT
+
+The default value of this parameter is NULL.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct progress {
+ char *private;
+ size_t size;
+};
+
+static size_t progress_cb(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow)
+{
+ struct progress *memory = clientp;
+ printf("private ptr: %p\n", memory->private);
+ /* use the values */
+
+ return 0; /* all is good */
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct progress data;
+
+ /* pass struct to callback */
+ curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &data);
+ curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_cb);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.32.0
+
+# RETURN VALUE
+
+Returns CURLE_OK
diff --git a/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3 b/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3
deleted file mode 100644
index f339eed81..000000000
--- a/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.3
+++ /dev/null
@@ -1,115 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_XFERINFOFUNCTION 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_XFERINFOFUNCTION \- progress meter callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-int progress_callback(void *clientp,
- curl_off_t dltotal,
- curl_off_t dlnow,
- curl_off_t ultotal,
- curl_off_t ulnow);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XFERINFOFUNCTION,
- progress_callback);
-.fi
-.SH DESCRIPTION
-Pass a pointer to your callback function, which should match the prototype
-shown above.
-
-This function gets called by libcurl instead of its internal equivalent with a
-frequent interval. While data is being transferred it gets called frequently,
-and during slow periods like when nothing is being transferred it can slow
-down to about one call per second.
-
-\fIclientp\fP is the pointer set with \fICURLOPT_XFERINFODATA(3)\fP, it is not
-used by libcurl but is only passed along from the application to the callback.
-
-The callback gets told how much data libcurl is about to transfer and has
-already transferred, in number of bytes. \fIdltotal\fP is the total number of
-bytes libcurl expects to download in this transfer. \fIdlnow\fP is the number
-of bytes downloaded so far. \fIultotal\fP is the total number of bytes libcurl
-expects to upload in this transfer. \fIulnow\fP is the number of bytes
-uploaded so far.
-
-Unknown/unused argument values passed to the callback are set to zero (like if
-you only download data, the upload size remains 0). Many times the callback is
-called one or more times first, before it knows the data sizes so a program
-must be made to handle that.
-
-If your callback function returns CURL_PROGRESSFUNC_CONTINUE it makes libcurl
-to continue executing the default progress function.
-
-Returning any other non-zero value from this callback makes libcurl abort the
-transfer and return \fICURLE_ABORTED_BY_CALLBACK\fP.
-
-If you transfer data with the multi interface, this function is not called
-during periods of idleness unless you call the appropriate libcurl function
-that performs transfers.
-
-\fICURLOPT_NOPROGRESS(3)\fP must be set to 0 to make this function actually
-get called.
-.SH DEFAULT
-By default, libcurl has an internal progress meter. That is rarely wanted by
-users.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- struct progress {
- char *private;
- size_t size;
- };
-
- static size_t progress_callback(void *clientp,
- curl_off_t dltotal,
- curl_off_t dlnow,
- curl_off_t ultotal,
- curl_off_t ulnow)
- {
- struct progress *memory = (struct progress *)clientp;
-
- /* use the values */
-
- return 0; /* all is good */
- }
-
- struct progress data;
-
- /* pass struct to callback */
- curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, &data);
-
- curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, progress_callback);
-.fi
-.SH AVAILABILITY
-Added in 7.32.0. This callback replaces \fICURLOPT_PROGRESSFUNCTION(3)\fP
-.SH RETURN VALUE
-Returns CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_NOPROGRESS (3),
-.BR CURLOPT_XFERINFODATA (3)
diff --git a/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.md b/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.md
new file mode 100644
index 000000000..b965db591
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_XFERINFOFUNCTION.md
@@ -0,0 +1,120 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_XFERINFOFUNCTION
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_NOPROGRESS (3)
+ - CURLOPT_XFERINFODATA (3)
+---
+
+# NAME
+
+CURLOPT_XFERINFOFUNCTION - progress meter callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+int progress_callback(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow);
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XFERINFOFUNCTION,
+ progress_callback);
+~~~
+
+# DESCRIPTION
+
+Pass a pointer to your callback function, which should match the prototype
+shown above.
+
+This function gets called by libcurl instead of its internal equivalent with a
+frequent interval. While data is being transferred it gets called frequently,
+and during slow periods like when nothing is being transferred it can slow
+down to about one call per second.
+
+*clientp* is the pointer set with CURLOPT_XFERINFODATA(3), it is not
+used by libcurl but is only passed along from the application to the callback.
+
+The callback gets told how much data libcurl is about to transfer and has
+already transferred, in number of bytes. *dltotal* is the total number of
+bytes libcurl expects to download in this transfer. *dlnow* is the number
+of bytes downloaded so far. *ultotal* is the total number of bytes libcurl
+expects to upload in this transfer. *ulnow* is the number of bytes
+uploaded so far.
+
+Unknown/unused argument values passed to the callback are set to zero (like if
+you only download data, the upload size remains 0). Many times the callback is
+called one or more times first, before it knows the data sizes so a program
+must be made to handle that.
+
+If your callback function returns CURL_PROGRESSFUNC_CONTINUE it makes libcurl
+to continue executing the default progress function.
+
+Returning any other non-zero value from this callback makes libcurl abort the
+transfer and return *CURLE_ABORTED_BY_CALLBACK*.
+
+If you transfer data with the multi interface, this function is not called
+during periods of idleness unless you call the appropriate libcurl function
+that performs transfers.
+
+CURLOPT_NOPROGRESS(3) must be set to 0 to make this function actually
+get called.
+
+# DEFAULT
+
+By default, libcurl has an internal progress meter. That is rarely wanted by
+users.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct progress {
+ char *private;
+ size_t size;
+};
+
+static size_t progress_callback(void *clientp,
+ curl_off_t dltotal,
+ curl_off_t dlnow,
+ curl_off_t ultotal,
+ curl_off_t ulnow)
+{
+ struct progress *memory = clientp;
+ printf("my ptr: %p\n", memory->private);
+
+ /* use the values */
+
+ return 0; /* all is good */
+}
+
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ struct progress data;
+
+ /* pass struct to callback */
+ curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &data);
+
+ curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.32.0. This callback replaces CURLOPT_PROGRESSFUNCTION(3)
+
+# RETURN VALUE
+
+Returns CURLE_OK.
diff --git a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3 b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3
deleted file mode 100644
index f495ac935..000000000
--- a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_XOAUTH2_BEARER 3 "19 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_XOAUTH2_BEARER \- OAuth 2.0 access token
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);
-.fi
-.SH DESCRIPTION
-Pass a char * as parameter, which should point to the null-terminated OAuth
-2.0 Bearer Access Token for use with HTTP, IMAP, LDAP, POP3 and SMTP servers
-that support the OAuth 2.0 Authorization Framework.
-
-Note: For IMAP, LDAP, POP3 and SMTP, the user name used to generate the
-Bearer Token should be supplied via the \fICURLOPT_USERNAME(3)\fP option.
-
-The application does not have to keep the string around after setting this
-option.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP, IMAP, LDAP, POP3 and SMTP
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "pop3://example.com/");
- curl_easy_setopt(curl, CURLOPT_XOAUTH2_BEARER, "1ab9cb22ba269a7");
- ret = curl_easy_perform(curl);
- curl_easy_cleanup(curl);
-}
-.fi
-.SH AVAILABILITY
-Added in 7.33.0. Support for OpenLDAP added in 7.82.0.
-.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_MAIL_AUTH (3),
-.BR CURLOPT_USERNAME (3)
-
diff --git a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md
new file mode 100644
index 000000000..af91ea03e
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md
@@ -0,0 +1,67 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLOPT_XOAUTH2_BEARER
+Section: 3
+Source: libcurl
+See-also:
+ - CURLOPT_MAIL_AUTH (3)
+ - CURLOPT_USERNAME (3)
+---
+
+# NAME
+
+CURLOPT_XOAUTH2_BEARER - OAuth 2.0 access token
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);
+~~~
+
+# DESCRIPTION
+
+Pass a char pointer as parameter, which should point to the null-terminated
+OAuth 2.0 Bearer Access Token for use with HTTP, IMAP, LDAP, POP3 and SMTP
+servers that support the OAuth 2.0 Authorization Framework.
+
+Note: For IMAP, LDAP, POP3 and SMTP, the user name used to generate the
+Bearer Token should be supplied via the CURLOPT_USERNAME(3) option.
+
+The application does not have to keep the string around after setting this
+option.
+
+# DEFAULT
+
+NULL
+
+# PROTOCOLS
+
+HTTP, IMAP, LDAP, POP3 and SMTP
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURL *curl = curl_easy_init();
+ if(curl) {
+ CURLcode res;
+ curl_easy_setopt(curl, CURLOPT_URL, "pop3://example.com/");
+ curl_easy_setopt(curl, CURLOPT_XOAUTH2_BEARER, "1ab9cb22ba269a7");
+ res = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+ }
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.33.0. Support for OpenLDAP added in 7.82.0.
+
+# 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.
diff --git a/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.3 b/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.3
deleted file mode 100644
index 8d146eb67..000000000
--- a/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH CURLSHOPT_LOCKFUNC 3 "8 Aug 2003" libcurl libcurl
-.SH NAME
-CURLSHOPT_LOCKFUNC - mutex lock callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void lockcb(CURL *handle, curl_lock_data data, curl_lock_access access,
- void *clientp);
-
-CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_LOCKFUNC, lockcb);
-.fi
-.SH DESCRIPTION
-Set a mutex lock callback for the share object, to allow it to get used by
-multiple threads concurrently. There is a corresponding
-\fICURLSHOPT_UNLOCKFUNC(3)\fP callback called when the mutex is again released.
-
-The \fIlockcb\fP argument must be a pointer to a function matching the
-prototype shown above. The arguments to the callback are:
-
-\fIhandle\fP is the currently active easy handle in use when the share object
-is intended to get used.
-
-The \fIdata\fP argument tells what kind of data libcurl wants to lock. Make
-sure that the callback uses a different lock for each kind of data.
-
-\fIaccess\fP defines what access type libcurl wants, shared or single.
-
-\fIclientp\fP is the private pointer you set with \fICURLSHOPT_USERDATA(3)\fP.
-This pointer is not used by libcurl itself.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, mutex_lock);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-CURLSHE_OK (zero) means that the option was set properly, non-zero means an
-error occurred. See \fIlibcurl-errors(3)\fP for the full list with
-descriptions.
-.SH "SEE ALSO"
-.BR curl_share_cleanup (3),
-.BR curl_share_init (3),
-.BR curl_share_setopt (3),
-.BR CURLSHOPT_UNLOCKFUNC (3)
diff --git a/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.md b/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.md
new file mode 100644
index 000000000..f41f86ebf
--- /dev/null
+++ b/docs/libcurl/opts/CURLSHOPT_LOCKFUNC.md
@@ -0,0 +1,77 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLSHOPT_LOCKFUNC
+Section: 3
+Source: libcurl
+See-also:
+ - CURLSHOPT_UNLOCKFUNC (3)
+ - curl_share_cleanup (3)
+ - curl_share_init (3)
+ - curl_share_setopt (3)
+---
+
+# NAME
+
+CURLSHOPT_LOCKFUNC - mutex lock callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void lockcb(CURL *handle, curl_lock_data data, curl_lock_access access,
+ void *clientp);
+
+CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_LOCKFUNC, lockcb);
+~~~
+
+# DESCRIPTION
+
+Set a mutex lock callback for the share object, to allow it to get used by
+multiple threads concurrently. There is a corresponding
+CURLSHOPT_UNLOCKFUNC(3) callback called when the mutex is again released.
+
+The *lockcb* argument must be a pointer to a function matching the
+prototype shown above. The arguments to the callback are:
+
+*handle* is the currently active easy handle in use when the share object
+is intended to get used.
+
+The *data* argument tells what kind of data libcurl wants to lock. Make
+sure that the callback uses a different lock for each kind of data.
+
+*access* defines what access type libcurl wants, shared or single.
+
+*clientp* is the private pointer you set with CURLSHOPT_USERDATA(3).
+This pointer is not used by libcurl itself.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+extern void mutex_lock(CURL *handle, curl_lock_data data,
+ curl_lock_access access, void *clientp);
+
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_LOCKFUNC, mutex_lock);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+CURLSHE_OK (zero) means that the option was set properly, non-zero means an
+error occurred. See libcurl-errors(3) for the full list with
+descriptions.
diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.3 b/docs/libcurl/opts/CURLSHOPT_SHARE.3
deleted file mode 100644
index d8f5dc87d..000000000
--- a/docs/libcurl/opts/CURLSHOPT_SHARE.3
+++ /dev/null
@@ -1,105 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH CURLSHOPT_SHARE 3 "8 Aug 2003" libcurl libcurl
-.SH NAME
-CURLSHOPT_SHARE - add data to share
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_SHARE, long type);
-.fi
-.SH DESCRIPTION
-The \fItype\fP parameter specifies what specific data that should be shared
-and kept in the share object that was created with \fIcurl_share_init(3)\fP.
-The given \fItype\fP must be be one of the values described below. You can set
-\fICURLSHOPT_SHARE(3)\fP multiple times with different data arguments to have
-the share object share multiple types of data. Unset a type again by setting
-\fICURLSHOPT_UNSHARE(3)\fP.
-.IP CURL_LOCK_DATA_COOKIE
-Cookie data is shared across the easy handles using this shared object. Note
-that this does not activate an easy handle's cookie handling. You can do that
-separately by using \fICURLOPT_COOKIEFILE(3)\fP for example.
-.IP CURL_LOCK_DATA_DNS
-Cached DNS hosts are shared across the easy handles using this shared
-object. Note that when you use the multi interface, all easy handles added to
-the same multi handle share DNS cache by default without using this option.
-.IP CURL_LOCK_DATA_SSL_SESSION
-SSL session IDs are shared across the easy handles using this shared
-object. This reduces the time spent in the SSL handshake when reconnecting to
-the same server. Note SSL session IDs are reused within the same easy handle
-by default. Note this symbol was added in 7.10.3 but was not implemented until
-7.23.0.
-.IP CURL_LOCK_DATA_CONNECT
-Put the connection cache in the share object and make all easy handles using
-this share object share the connection cache.
-
-It is not supported to share connections between multiple concurrent threads.
-
-Connections that are used for HTTP/1.1 Pipelining or HTTP/2 multiplexing only
-get additional transfers added to them if the existing connection is held by
-the same multi or easy handle. libcurl does not support doing HTTP/2 streams
-in different threads using a shared connection.
-
-Support for \fBCURL_LOCK_DATA_CONNECT\fP was added in 7.57.0, but the symbol
-existed before this.
-
-Note that when you use the multi interface, all easy handles added to the same
-multi handle shares connection cache by default without using this option.
-.IP CURL_LOCK_DATA_PSL
-The Public Suffix List stored in the share object is made available to all
-easy handle bound to the later. Since the Public Suffix List is periodically
-refreshed, this avoids updates in too many different contexts.
-
-Added in 7.61.0.
-
-Note that when you use the multi interface, all easy handles added to the same
-multi handle shares PSL cache by default without using this option.
-.IP CURL_LOCK_DATA_HSTS
-The in-memory HSTS cache.
-
-It is not supported to share the HSTS between multiple concurrent threads.
-
-Added in 7.88.0
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-CURLSHE_OK (zero) means that the option was set properly, non-zero means an
-error occurred. See \fIlibcurl-errors(3)\fP for the full list with
-descriptions.
-.SH "SEE ALSO"
-.BR curl_share_cleanup (3),
-.BR curl_share_init (3),
-.BR curl_share_setopt (3),
-.BR CURLSHOPT_UNSHARE (3)
diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.md b/docs/libcurl/opts/CURLSHOPT_SHARE.md
new file mode 100644
index 000000000..66ed27034
--- /dev/null
+++ b/docs/libcurl/opts/CURLSHOPT_SHARE.md
@@ -0,0 +1,117 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLSHOPT_SHARE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLSHOPT_UNSHARE (3)
+ - curl_share_cleanup (3)
+ - curl_share_init (3)
+ - curl_share_setopt (3)
+---
+
+# NAME
+
+CURLSHOPT_SHARE - add data to share
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_SHARE, long type);
+~~~
+
+# DESCRIPTION
+
+The *type* parameter specifies what specific data that should be shared
+and kept in the share object that was created with curl_share_init(3).
+The given *type* must be be one of the values described below. You can set
+CURLSHOPT_SHARE(3) multiple times with different data arguments to have
+the share object share multiple types of data. Unset a type again by setting
+CURLSHOPT_UNSHARE(3).
+
+## CURL_LOCK_DATA_COOKIE
+
+Cookie data is shared across the easy handles using this shared object. Note
+that this does not activate an easy handle's cookie handling. You can do that
+separately by using CURLOPT_COOKIEFILE(3) for example.
+
+## CURL_LOCK_DATA_DNS
+
+Cached DNS hosts are shared across the easy handles using this shared
+object. Note that when you use the multi interface, all easy handles added to
+the same multi handle share DNS cache by default without using this option.
+
+## CURL_LOCK_DATA_SSL_SESSION
+
+SSL session IDs are shared across the easy handles using this shared
+object. This reduces the time spent in the SSL handshake when reconnecting to
+the same server. Note SSL session IDs are reused within the same easy handle
+by default. Note this symbol was added in 7.10.3 but was not implemented until
+7.23.0.
+
+## CURL_LOCK_DATA_CONNECT
+
+Put the connection cache in the share object and make all easy handles using
+this share object share the connection cache.
+
+It is not supported to share connections between multiple concurrent threads.
+
+Connections that are used for HTTP/1.1 Pipelining or HTTP/2 multiplexing only
+get additional transfers added to them if the existing connection is held by
+the same multi or easy handle. libcurl does not support doing HTTP/2 streams
+in different threads using a shared connection.
+
+Support for **CURL_LOCK_DATA_CONNECT** was added in 7.57.0, but the symbol
+existed before this.
+
+Note that when you use the multi interface, all easy handles added to the same
+multi handle shares connection cache by default without using this option.
+
+## CURL_LOCK_DATA_PSL
+
+The Public Suffix List stored in the share object is made available to all
+easy handle bound to the later. Since the Public Suffix List is periodically
+refreshed, this avoids updates in too many different contexts.
+
+Added in 7.61.0.
+
+Note that when you use the multi interface, all easy handles added to the same
+multi handle shares PSL cache by default without using this option.
+
+## CURL_LOCK_DATA_HSTS
+
+The in-memory HSTS cache.
+
+It is not supported to share the HSTS between multiple concurrent threads.
+
+Added in 7.88.0
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+CURLSHE_OK (zero) means that the option was set properly, non-zero means an
+error occurred. See libcurl-errors(3) for the full list with
+descriptions.
diff --git a/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.3 b/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.3
deleted file mode 100644
index 4b52ef3cb..000000000
--- a/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH CURLSHOPT_UNLOCKFUNC 3 "8 Aug 2003" libcurl libcurl
-.SH NAME
-CURLSHOPT_UNLOCKFUNC - mutex unlock callback
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-void unlockcb(CURL *handle, curl_lock_data data, void *clientp);
-
-CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_UNLOCKFUNC, unlockcb);
-.fi
-.SH DESCRIPTION
-Set a mutex unlock callback for the share object. There is a corresponding
-\fICURLSHOPT_LOCKFUNC(3)\fP callback called when the mutex is first locked.
-
-The \fIunlockcb\fP argument must be a pointer to a function matching the
-prototype shown above. The arguments to the callback are:
-
-\fIhandle\fP is the currently active easy handle in use when the share object
-is released.
-
-The \fIdata\fP argument tells what kind of data libcurl wants to unlock. Make
-sure that the callback uses a different lock for each kind of data.
-
-\fIclientp\fP is the private pointer you set with \fICURLSHOPT_USERDATA(3)\fP.
-This pointer is not used by libcurl itself.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, mutex_unlock);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-CURLSHE_OK (zero) means that the option was set properly, non-zero means an
-error occurred. See \fIlibcurl-errors(3)\fP for the full list with
-descriptions.
-.SH "SEE ALSO"
-.BR curl_share_cleanup (3),
-.BR curl_share_init (3),
-.BR curl_share_setopt (3),
-.BR CURLSHOPT_LOCKFUNC (3)
diff --git a/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.md b/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.md
new file mode 100644
index 000000000..16f9a377e
--- /dev/null
+++ b/docs/libcurl/opts/CURLSHOPT_UNLOCKFUNC.md
@@ -0,0 +1,72 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLSHOPT_UNLOCKFUNC
+Section: 3
+Source: libcurl
+See-also:
+ - CURLSHOPT_LOCKFUNC (3)
+ - curl_share_cleanup (3)
+ - curl_share_init (3)
+ - curl_share_setopt (3)
+---
+
+# NAME
+
+CURLSHOPT_UNLOCKFUNC - mutex unlock callback
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+void unlockcb(CURL *handle, curl_lock_data data, void *clientp);
+
+CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_UNLOCKFUNC, unlockcb);
+~~~
+
+# DESCRIPTION
+
+Set a mutex unlock callback for the share object. There is a corresponding
+CURLSHOPT_LOCKFUNC(3) callback called when the mutex is first locked.
+
+The *unlockcb* argument must be a pointer to a function matching the
+prototype shown above. The arguments to the callback are:
+
+*handle* is the currently active easy handle in use when the share object
+is released.
+
+The *data* argument tells what kind of data libcurl wants to unlock. Make
+sure that the callback uses a different lock for each kind of data.
+
+*clientp* is the private pointer you set with CURLSHOPT_USERDATA(3).
+This pointer is not used by libcurl itself.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+extern void mutex_unlock(CURL *, curl_lock_data, void *);
+
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_UNLOCKFUNC, mutex_unlock);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+CURLSHE_OK (zero) means that the option was set properly, non-zero means an
+error occurred. See libcurl-errors(3) for the full list with
+descriptions.
diff --git a/docs/libcurl/opts/CURLSHOPT_UNSHARE.3 b/docs/libcurl/opts/CURLSHOPT_UNSHARE.3
deleted file mode 100644
index d469920e1..000000000
--- a/docs/libcurl/opts/CURLSHOPT_UNSHARE.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH CURLSHOPT_UNSHARE 3 "8 Aug 2003" libcurl libcurl
-.SH NAME
-CURLSHOPT_UNSHARE - remove data to share
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_UNSHARE, long type);
-.fi
-.SH DESCRIPTION
-The \fItype\fP parameter specifies what specific data that should no longer be
-shared and kept in the share object that was created with
-\fIcurl_share_init(3)\fP. In other words, stop sharing that data in this
-shared object. The given \fItype\fP must be be one of the values described
-below. You can set \fICURLSHOPT_UNSHARE(3)\fP multiple times with different
-data arguments to remove multiple types from the shared object. Add data to
-share again with \fICURLSHOPT_SHARE(3)\fP.
-.IP CURL_LOCK_DATA_COOKIE
-Cookie data is no longer shared across the easy handles using this shared
-object.
-.IP CURL_LOCK_DATA_DNS
-Cached DNS hosts are no longer shared across the easy handles using this
-shared object.
-.IP CURL_LOCK_DATA_SSL_SESSION
-SSL session IDs are no longer shared across the easy handles using this shared
-object.
-.IP CURL_LOCK_DATA_CONNECT
-The connection cache is no longer shared.
-.IP CURL_LOCK_DATA_PSL
-The Public Suffix List is no longer shared.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_UNSHARE, CURL_LOCK_DATA_COOKIE);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-CURLSHE_OK (zero) means that the option was set properly, non-zero means an
-error occurred. See \fIlibcurl-errors(3)\fP for the full list with
-descriptions.
-.SH "SEE ALSO"
-.BR curl_share_cleanup (3),
-.BR curl_share_init (3),
-.BR curl_share_setopt (3),
-.BR CURLSHOPT_SHARE (3)
diff --git a/docs/libcurl/opts/CURLSHOPT_UNSHARE.md b/docs/libcurl/opts/CURLSHOPT_UNSHARE.md
new file mode 100644
index 000000000..e3cf5988c
--- /dev/null
+++ b/docs/libcurl/opts/CURLSHOPT_UNSHARE.md
@@ -0,0 +1,84 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLSHOPT_UNSHARE
+Section: 3
+Source: libcurl
+See-also:
+ - CURLSHOPT_SHARE (3)
+ - curl_share_cleanup (3)
+ - curl_share_init (3)
+ - curl_share_setopt (3)
+---
+
+# NAME
+
+CURLSHOPT_UNSHARE - remove data to share
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_UNSHARE, long type);
+~~~
+
+# DESCRIPTION
+
+The *type* parameter specifies what specific data that should no longer be
+shared and kept in the share object that was created with
+curl_share_init(3). In other words, stop sharing that data in this
+shared object. The given *type* must be be one of the values described
+below. You can set CURLSHOPT_UNSHARE(3) multiple times with different
+data arguments to remove multiple types from the shared object. Add data to
+share again with CURLSHOPT_SHARE(3).
+
+## CURL_LOCK_DATA_COOKIE
+
+Cookie data is no longer shared across the easy handles using this shared
+object.
+
+## CURL_LOCK_DATA_DNS
+
+Cached DNS hosts are no longer shared across the easy handles using this
+shared object.
+
+## CURL_LOCK_DATA_SSL_SESSION
+
+SSL session IDs are no longer shared across the easy handles using this shared
+object.
+
+## CURL_LOCK_DATA_CONNECT
+
+The connection cache is no longer shared.
+
+## CURL_LOCK_DATA_PSL
+
+The Public Suffix List is no longer shared.
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+int main(void)
+{
+ CURLSHcode sh;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_UNSHARE, CURL_LOCK_DATA_COOKIE);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+CURLSHE_OK (zero) means that the option was set properly, non-zero means an
+error occurred. See libcurl-errors(3) for the full list with
+descriptions.
diff --git a/docs/libcurl/opts/CURLSHOPT_USERDATA.3 b/docs/libcurl/opts/CURLSHOPT_USERDATA.3
deleted file mode 100644
index 8684fc3fd..000000000
--- a/docs/libcurl/opts/CURLSHOPT_USERDATA.3
+++ /dev/null
@@ -1,58 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.TH CURLSHOPT_USERDATA 3 "8 Aug 2003" libcurl libcurl
-.SH NAME
-CURLSHOPT_USERDATA - pointer passed to the lock and unlock mutex callbacks
-.SH SYNOPSIS
-.nf
-#include <curl/curl.h>
-
-CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_USERDATA, void *clientp);
-.fi
-.SH DESCRIPTION
-The \fIclientp\fP parameter is held verbatim by libcurl and is passed on as
-the \fIclientp\fP argument to the callbacks set with
-\fICURLSHOPT_LOCKFUNC(3)\fP and \fICURLSHOPT_UNLOCKFUNC(3)\fP.
-.SH PROTOCOLS
-All
-.SH EXAMPLE
-.nf
- CURLSHcode sh;
- struct secrets private_stuff;
- share = curl_share_init();
- sh = curl_share_setopt(share, CURLSHOPT_USERDATA, &private_stuff);
- if(sh)
- printf("Error: %s\\n", curl_share_strerror(sh));
-.fi
-.SH AVAILABILITY
-Added in 7.10
-.SH RETURN VALUE
-CURLSHE_OK (zero) means that the option was set properly, non-zero means an
-error occurred. See \fIlibcurl-errors(3)\fP for the full list with
-descriptions.
-.SH "SEE ALSO"
-.BR curl_share_cleanup (3),
-.BR curl_share_init (3),
-.BR curl_share_setopt (3),
-.BR CURLSHOPT_LOCKFUNC (3)
diff --git a/docs/libcurl/opts/CURLSHOPT_USERDATA.md b/docs/libcurl/opts/CURLSHOPT_USERDATA.md
new file mode 100644
index 000000000..d0ec7772d
--- /dev/null
+++ b/docs/libcurl/opts/CURLSHOPT_USERDATA.md
@@ -0,0 +1,62 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: CURLSHOPT_USERDATA
+Section: 3
+Source: libcurl
+See-also:
+ - CURLSHOPT_LOCKFUNC (3)
+ - curl_share_cleanup (3)
+ - curl_share_init (3)
+ - curl_share_setopt (3)
+---
+
+# NAME
+
+CURLSHOPT_USERDATA - pointer passed to the lock and unlock mutex callbacks
+
+# SYNOPSIS
+
+~~~c
+#include <curl/curl.h>
+
+CURLSHcode curl_share_setopt(CURLSH *share, CURLSHOPT_USERDATA, void *clientp);
+~~~
+
+# DESCRIPTION
+
+The *clientp* parameter is held verbatim by libcurl and is passed on as
+the *clientp* argument to the callbacks set with
+CURLSHOPT_LOCKFUNC(3) and CURLSHOPT_UNLOCKFUNC(3).
+
+# PROTOCOLS
+
+All
+
+# EXAMPLE
+
+~~~c
+struct secrets {
+ void *custom;
+};
+
+int main(void)
+{
+ CURLSHcode sh;
+ struct secrets private_stuff;
+ CURLSH *share = curl_share_init();
+ sh = curl_share_setopt(share, CURLSHOPT_USERDATA, &private_stuff);
+ if(sh)
+ printf("Error: %s\n", curl_share_strerror(sh));
+}
+~~~
+
+# AVAILABILITY
+
+Added in 7.10
+
+# RETURN VALUE
+
+CURLSHE_OK (zero) means that the option was set properly, non-zero means an
+error occurred. See libcurl-errors(3) for the full list with
+descriptions.
diff --git a/docs/libcurl/opts/Makefile.am b/docs/libcurl/opts/Makefile.am
index 250937fd1..42f9db4c5 100644
--- a/docs/libcurl/opts/Makefile.am
+++ b/docs/libcurl/opts/Makefile.am
@@ -26,38 +26,19 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
include Makefile.inc
-man_DISTMANS = $(man_MANS:.3=.3.dist)
+CURLPAGES = $(man_MANS:.3=.md)
+CLEANFILES = $(man_MANS)
+nodist_MANS = $(man_MANS)
-HTMLPAGES = $(man_MANS:.3=.html)
+EXTRA_DIST = $(CURLPAGES) CMakeLists.txt
-PDFPAGES = $(man_MANS:.3=.pdf)
+CD2NROFF = $(top_srcdir)/scripts/cd2nroff $< >$@
+CD2 = $(CD2_$(V))
+CD2_0 = @echo " RENDER " $@;
+CD2_1 =
+CD2_ = $(CD2_0)
-CLEANFILES = $(HTMLPAGES) $(PDFPAGES) $(man_DISTMANS)
+SUFFIXES = .3 .md
-EXTRA_DIST = $(man_MANS) CMakeLists.txt
-MAN2HTML= roffit --mandir=. $< >$@
-
-SUFFIXES = .3 .html
-
-html: $(HTMLPAGES)
-
-.3.html:
- $(MAN2HTML)
-
-pdf: $(PDFPAGES)
-
-.3.pdf:
- @(foo=`echo $@ | sed -e 's/\.[0-9]$$//g'`; \
- groff -Tps -man $< >$$foo.ps; \
- ps2pdf $$foo.ps $@; \
- rm $$foo.ps; \
- echo "converted $< to $@")
-
-mancheck:
- @(cd $(top_srcdir)/docs/libcurl/opts && ls `awk -F, '!/OBSOLETE/ && /^ CINIT/ { a=substr($$1, 9); print "CURLOPT_" a ".3"}' $(top_srcdir)/include/curl/curl.h`)
- rm -f in_temp
- @(for a in $(man_MANS); do echo $$a >>in_temp; done)
- sort in_temp > in_makefile
- ls CURL*.3 > in_directory
- -diff -u in_makefile in_directory
- rm in_temp in_directory in_makefile
+.md.3:
+ $(CD2)$(CD2NROFF)
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index 9fe780677..be7035bf0 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -65,6 +65,7 @@ man_MANS = \
CURLINFO_PROXY_ERROR.3 \
CURLINFO_PROXY_SSL_VERIFYRESULT.3 \
CURLINFO_PROXYAUTH_AVAIL.3 \
+ CURLINFO_QUEUE_TIME_T.3 \
CURLINFO_REDIRECT_COUNT.3 \
CURLINFO_REDIRECT_TIME.3 \
CURLINFO_REDIRECT_TIME_T.3 \
@@ -332,6 +333,7 @@ man_MANS = \
CURLOPT_SEEKDATA.3 \
CURLOPT_SEEKFUNCTION.3 \
CURLOPT_SERVER_RESPONSE_TIMEOUT.3 \
+ CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.3 \
CURLOPT_SERVICE_NAME.3 \
CURLOPT_SHARE.3 \
CURLOPT_SOCKOPTDATA.3 \
diff --git a/docs/libcurl/opts/template.3 b/docs/libcurl/opts/template.3
deleted file mode 100644
index 495cb82e0..000000000
--- a/docs/libcurl/opts/template.3
+++ /dev/null
@@ -1,41 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH CURLOPT_TEMPLATE 3 "17 Jun 2014" libcurl libcurl
-.SH NAME
-CURLOPT_TEMPLATE \- [short description]
-.SH SYNOPSIS
-#include <curl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TEMPLATE, [argument]);
-.SH DESCRIPTION
-.SH DEFAULT
-.SH PROTOCOLS
-.SH EXAMPLE
-.SH AVAILABILITY
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
-.SH "SEE ALSO"
-.BR CURLOPT_STDERR (3),
-.BR CURLOPT_DEBUGFUNCTION (3)
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 24a954ece..c20008a73 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -190,7 +190,7 @@ CURL_VERSION_ZSTD 7.72.0
CURL_WAIT_POLLIN 7.28.0
CURL_WAIT_POLLOUT 7.28.0
CURL_WAIT_POLLPRI 7.28.0
-CURL_WIN32 7.69.0
+CURL_WIN32 7.69.0 - 8.5.0
CURL_WRITEFUNC_ERROR 7.87.0
CURL_WRITEFUNC_PAUSE 7.18.0
CURL_ZERO_TERMINATED 7.56.0
@@ -212,12 +212,12 @@ CURLAUTH_NONE 7.10.6
CURLAUTH_NTLM 7.10.6
CURLAUTH_NTLM_WB 7.22.0
CURLAUTH_ONLY 7.21.3
-CURLCLOSEPOLICY_CALLBACK 7.7
-CURLCLOSEPOLICY_LEAST_RECENTLY_USED 7.7
-CURLCLOSEPOLICY_LEAST_TRAFFIC 7.7
-CURLCLOSEPOLICY_NONE 7.7
-CURLCLOSEPOLICY_OLDEST 7.7
-CURLCLOSEPOLICY_SLOWEST 7.7
+CURLCLOSEPOLICY_CALLBACK 7.7 7.16.1
+CURLCLOSEPOLICY_LEAST_RECENTLY_USED 7.7 7.16.1
+CURLCLOSEPOLICY_LEAST_TRAFFIC 7.7 7.16.1
+CURLCLOSEPOLICY_NONE 7.7 7.16.1
+CURLCLOSEPOLICY_OLDEST 7.7 7.16.1
+CURLCLOSEPOLICY_SLOWEST 7.7 7.16.1
CURLE_ABORTED_BY_CALLBACK 7.1
CURLE_AGAIN 7.18.2
CURLE_ALREADY_COMPLETE 7.7.2 7.8
@@ -328,6 +328,7 @@ CURLE_TFTP_NOSUCHUSER 7.15.0
CURLE_TFTP_NOTFOUND 7.15.0
CURLE_TFTP_PERM 7.15.0
CURLE_TFTP_UNKNOWNID 7.15.0
+CURLE_TOO_LARGE 8.6.0
CURLE_TOO_MANY_REDIRECTS 7.5
CURLE_UNKNOWN_OPTION 7.21.5
CURLE_UNKNOWN_TELNET_OPTION 7.7 7.21.5
@@ -468,6 +469,7 @@ CURLINFO_PROXY_ERROR 7.73.0
CURLINFO_PROXY_SSL_VERIFYRESULT 7.52.0
CURLINFO_PROXYAUTH_AVAIL 7.10.8
CURLINFO_PTR 7.54.1
+CURLINFO_QUEUE_TIME_T 8.6.0
CURLINFO_REDIRECT_COUNT 7.9.7
CURLINFO_REDIRECT_TIME 7.9.7
CURLINFO_REDIRECT_TIME_T 7.61.0
@@ -800,6 +802,7 @@ CURLOPT_SASL_IR 7.31.0
CURLOPT_SEEKDATA 7.18.0
CURLOPT_SEEKFUNCTION 7.18.0
CURLOPT_SERVER_RESPONSE_TIMEOUT 7.20.0
+CURLOPT_SERVER_RESPONSE_TIMEOUT_MS 8.6.0
CURLOPT_SERVICE_NAME 7.43.0
CURLOPT_SHARE 7.10
CURLOPT_SOCKOPTDATA 7.16.0
@@ -1094,6 +1097,7 @@ CURLUE_NO_USER 7.62.0
CURLUE_NO_ZONEID 7.81.0
CURLUE_OK 7.62.0
CURLUE_OUT_OF_MEMORY 7.62.0
+CURLUE_TOO_LARGE 8.6.0
CURLUE_UNKNOWN_PART 7.62.0
CURLUE_UNSUPPORTED_SCHEME 7.62.0
CURLUE_URLDECODE 7.62.0
diff --git a/docs/mk-ca-bundle.1 b/docs/mk-ca-bundle.1
deleted file mode 100644
index e6db0504c..000000000
--- a/docs/mk-ca-bundle.1
+++ /dev/null
@@ -1,120 +0,0 @@
-.\" **************************************************************************
-.\" * _ _ ____ _
-.\" * Project ___| | | | _ \| |
-.\" * / __| | | | |_) | |
-.\" * | (__| |_| | _ <| |___
-.\" * \___|\___/|_| \_\_____|
-.\" *
-.\" * Copyright (C) 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.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.
-.\" *
-.\" * SPDX-License-Identifier: curl
-.\" *
-.\" **************************************************************************
-.\"
-.TH mk-ca-bundle 1 "24 Oct 2016" mk-ca-bundle mk-ca-bundle
-.SH NAME
-mk-ca-bundle \- convert Mozilla's certificate bundle to PEM format
-.SH SYNOPSIS
-mk-ca-bundle [options]
-.I [outputfile]
-.SH DESCRIPTION
-The mk-ca-bundle tool downloads the \fIcertdata.txt\fP file from Mozilla's
-source tree over HTTPS, then parses \fIcertdata.txt\fP and extracts
-certificates into PEM format. By default, only CA root certificates trusted to
-issue SSL server authentication certificates are extracted. These are then
-processed with the OpenSSL command line tool to produce the final ca-bundle
-file.
-
-The default \fIoutputfile\fP name is \fBca-bundle.crt\fP. By setting it to '-'
-(a single dash) you will get the output sent to STDOUT instead of a file.
-
-The PEM format this scripts uses for output makes the result readily available
-for use by just about all OpenSSL or GnuTLS powered applications, such as curl
-and others.
-.SH OPTIONS
-The following options are supported:
-.IP -b
-backup an existing version of \fIoutputfilename\fP
-.IP "-d [name]"
-specify which Mozilla tree to pull \fIcertdata.txt\fP from (or a custom
-URL). Valid names are: aurora, beta, central, Mozilla, nss, release
-(default). They are shortcuts for which source tree to get the certificates
-data from.
-.IP -f
-force rebuild even if \fIcertdata.txt\fP is current (Added in version 1.17)
-.IP -i
-print version info about used modules
-.IP -k
-Allow insecure data transfer. By default (since 1.27) this command will fail
-if the HTTPS transfer fails. This overrides that decision (and opens for
-man-in-the-middle attacks).
-.IP -l
-print license info about \fIcertdata.txt\fP
-.IP -m
-(Added in 1.26) Include meta data comments in the output. The meta data is
-specific information about each certificate that is stored in the original
-file as comments and using this option will make those comments get passed on
-to the output file. The meta data is not parsed in any way by mk-ca-bundle.
-.IP -n
-no download of \fIcertdata.txt\fP (to use existing)
-.IP "-p [purposes]:[levels]"
-list of Mozilla trust purposes and levels for certificates to include in
-output. Takes the form of a comma separated list of purposes, a colon, and a
-comma separated list of levels. The default is to include all certificates
-trusted to issue SSL Server certificates
-(\fISERVER_AUTH:TRUSTED_DELEGATOR\fP).
-
-(Added in version 1.21, Perl only)
-
-Valid purposes are:
-.RS
-\fIALL\fP, \fIDIGITAL_SIGNATURE\fP, \fINON_REPUDIATION\fP,
-\fIKEY_ENCIPHERMENT\fP, \fIDATA_ENCIPHERMENT\fP, \fIKEY_AGREEMENT\fP,
-\fIKEY_CERT_SIGN\fP, \fICRL_SIGN\fP, \fISERVER_AUTH\fP (default),
-\fICLIENT_AUTH\fP, \fICODE_SIGNING\fP, \fIEMAIL_PROTECTION\fP,
-\fIIPSEC_END_SYSTEM\fP, \fIIPSEC_TUNNEL\fP, \fIIPSEC_USER\fP,
-\fITIME_STAMPING\fP, \fISTEP_UP_APPROVED\fP
-.RE
-.IP
-Valid trust levels are:
-.RS
-\fIALL\fP, \fITRUSTED_DELEGATOR\fP (default), \fINOT_TRUSTED\fP, \fIMUST_VERIFY_TRUST\fP, \fITRUSTED\fP
-.RE
-.IP -q
-be really quiet (no progress output at all)
-.IP -t
-include plain text listing of certificates
-.IP "-s [algorithms]"
-comma separated list of signature algorithms with which to hash/fingerprint
-each certificate and output when run in plain text mode.
-
-(Added in version 1.21, Perl only)
-
-Valid algorithms are:
-.RS
-ALL, NONE, MD5 (default), SHA1, SHA256, SHA384, SHA512
-.RE
-.IP -u
-unlink (remove) \fIcertdata.txt\fP after processing
-.IP -v
-be verbose and print out processed certificate authorities
-.SH EXIT STATUS
-Returns 0 on success. Returns 1 if it fails to download data.
-.SH FILE FORMAT
-The file format used by Mozilla for this trust information is documented here:
-.nf
-https://p11-glue.freedesktop.org/doc/storing-trust-policy/storing-trust-existing.html
-.fi
-.SH SEE ALSO
-.BR curl (1)
diff --git a/docs/mk-ca-bundle.md b/docs/mk-ca-bundle.md
new file mode 100644
index 000000000..bacfce08b
--- /dev/null
+++ b/docs/mk-ca-bundle.md
@@ -0,0 +1,128 @@
+---
+c: Copyright (C) Daniel Stenberg, <daniel.se>, et al.
+SPDX-License-Identifier: curl
+Title: mk-ca-bundle
+Section: 1
+Source: mk-ca-bundle
+See-also:
+ - curl (1)
+---
+
+# NAME
+
+mk-ca-bundle - convert Mozilla's certificate bundle to PEM format
+
+# SYNOPSIS
+
+mk-ca-bundle [options]
+*[outputfile]*
+
+# DESCRIPTION
+
+The mk-ca-bundle tool downloads the *certdata.txt* file from Mozilla's source
+tree over HTTPS, then parses *certdata.txt* and extracts certificates into PEM
+format. By default, only CA root certificates trusted to issue SSL server
+authentication certificates are extracted. These are then processed with the
+OpenSSL command line tool to produce the final ca-bundle file.
+
+The default *outputfile* name is **ca-bundle.crt**. By setting it to '-' (a
+single dash) you will get the output sent to STDOUT instead of a file.
+
+The PEM format this scripts uses for output makes the result readily available
+for use by just about all OpenSSL or GnuTLS powered applications, such as curl
+and others.
+
+# OPTIONS
+
+The following options are supported:
+
+## -b
+
+backup an existing version of *outputfilename*
+
+## -d [name]
+
+specify which Mozilla tree to pull *certdata.txt* from (or a custom
+URL). Valid names are: aurora, beta, central, Mozilla, nss, release
+(default). They are shortcuts for which source tree to get the certificates
+data from.
+
+## -f
+
+force rebuild even if *certdata.txt* is current (Added in version 1.17)
+
+## -i
+
+print version info about used modules
+
+## -k
+
+Allow insecure data transfer. By default (since 1.27) this command will fail
+if the HTTPS transfer fails. This overrides that decision (and opens for
+man-in-the-middle attacks).
+
+## -l
+
+print license info about *certdata.txt*
+
+## -m
+
+(Added in 1.26) Include meta data comments in the output. The meta data is
+specific information about each certificate that is stored in the original
+file as comments and using this option will make those comments get passed on
+to the output file. The meta data is not parsed in any way by mk-ca-bundle.
+
+## -n
+
+no download of *certdata.txt* (to use existing)
+
+## -p [purposes]:[levels]
+
+list of Mozilla trust purposes and levels for certificates to include in
+output. Takes the form of a comma separated list of purposes, a colon, and a
+comma separated list of levels. The default is to include all certificates
+trusted to issue SSL Server certificates (*SERVER_AUTH:TRUSTED_DELEGATOR*).
+
+Valid purposes are: *ALL*, *DIGITAL_SIGNATURE*, *NON_REPUDIATION*,
+*KEY_ENCIPHERMENT*, *DATA_ENCIPHERMENT*, *KEY_AGREEMENT*, *KEY_CERT_SIGN*,
+*CRL_SIGN*, *SERVER_AUTH* (default), *CLIENT_AUTH*, *CODE_SIGNING*,
+*EMAIL_PROTECTION*, *IPSEC_END_SYSTEM*, *IPSEC_TUNNEL*, *IPSEC_USER*,
+*TIME_STAMPING*, *STEP_UP_APPROVED*
+
+Valid trust levels are: *ALL*, *TRUSTED_DELEGATOR* (default), *NOT_TRUSTED*,
+*MUST_VERIFY_TRUST*, *TRUSTED*
+
+## -q
+
+be really quiet (no progress output at all)
+
+## -t
+
+include plain text listing of certificates
+
+## -s [algorithms]
+
+comma separated list of signature algorithms with which to hash/fingerprint
+each certificate and output when run in plain text mode.
+
+Valid algorithms are:
+ALL, NONE, MD5 (default), SHA1, SHA256, SHA384, SHA512
+
+## -u
+
+unlink (remove) *certdata.txt* after processing
+
+## -v
+
+be verbose and print out processed certificate authorities
+
+# EXIT STATUS
+
+Returns 0 on success. Returns 1 if it fails to download data.
+
+# FILE FORMAT
+
+The file format used by Mozilla for this trust information is documented here:
+~~~c
+https://p11-glue.freedesktop.org/doc/storing-trust-policy/storing-trust-existing.html
+~~~
diff --git a/include/curl/curl.h b/include/curl/curl.h
index bf71d82fb..eb0602250 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -53,28 +53,19 @@
#include "curlver.h" /* libcurl version defines */
#include "system.h" /* determine things run-time */
-/*
- * Define CURL_WIN32 when build target is Win32 API
- */
-
-#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \
- !defined(__SYMBIAN32__)
-#define CURL_WIN32
-#endif
-
#include <stdio.h>
#include <limits.h>
-#if (defined(__FreeBSD__) && (__FreeBSD__ >= 2)) || defined(__MidnightBSD__)
+#if defined(__FreeBSD__) || defined(__MidnightBSD__)
/* Needed for __FreeBSD_version or __MidnightBSD_version symbol definition */
-#include <osreldate.h>
+#include <sys/param.h>
#endif
/* The include stuff here below is mainly for time_t! */
#include <sys/types.h>
#include <time.h>
-#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
/* The check above prevents the winsock2 inclusion if winsock.h already was
@@ -88,7 +79,7 @@
libc5-based Linux systems. Only include it on systems that are known to
require it! */
#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
- defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
+ defined(__minix) || defined(__INTEGRITY) || \
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
@@ -97,11 +88,11 @@
#include <sys/select.h>
#endif
-#if !defined(CURL_WIN32) && !defined(_WIN32_WCE)
+#if !defined(_WIN32) && !defined(_WIN32_WCE)
#include <sys/socket.h>
#endif
-#if !defined(CURL_WIN32)
+#if !defined(_WIN32)
#include <sys/time.h>
#endif
@@ -128,7 +119,7 @@ typedef void CURLSH;
#ifdef CURL_STATICLIB
# define CURL_EXTERN
-#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \
+#elif defined(_WIN32) || \
(__has_declspec_attribute(dllexport) && \
__has_declspec_attribute(dllimport))
# if defined(BUILDING_LIBCURL)
@@ -144,7 +135,7 @@ typedef void CURLSH;
#ifndef curl_socket_typedef
/* socket typedef */
-#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+#if defined(_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
typedef SOCKET curl_socket_t;
#define CURL_SOCKET_BAD INVALID_SOCKET
#else
@@ -640,6 +631,7 @@ typedef enum {
CURLE_PROXY, /* 97 - proxy handshake error */
CURLE_SSL_CLIENTCERT, /* 98 - client-side certificate required */
CURLE_UNRECOVERABLE_POLL, /* 99 - poll/select returned fatal error */
+ CURLE_TOO_LARGE, /* 100 - a value/data met its maximum */
CURL_LAST /* never use! */
} CURLcode;
@@ -1854,7 +1846,8 @@ typedef enum {
/* allow GSSAPI credential delegation */
CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_VALUES, 210),
- /* Set the name servers to use for DNS resolution */
+ /* Set the name servers to use for DNS resolution.
+ * Only supported by the c-ares DNS backend */
CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211),
/* Time-out accept operations (currently for FTP only) after this amount
@@ -2210,6 +2203,9 @@ typedef enum {
/* set a specific client IP for HAProxy PROXY protocol header? */
CURLOPT(CURLOPT_HAPROXY_CLIENT_IP, CURLOPTTYPE_STRINGPOINT, 323),
+ /* millisecond version */
+ CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2941,7 +2937,8 @@ typedef enum {
CURLINFO_CAPATH = CURLINFO_STRING + 62,
CURLINFO_XFER_ID = CURLINFO_OFF_T + 63,
CURLINFO_CONN_ID = CURLINFO_OFF_T + 64,
- CURLINFO_LASTONE = 64
+ CURLINFO_QUEUE_TIME_T = CURLINFO_OFF_T + 65,
+ CURLINFO_LASTONE = 65
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -3220,6 +3217,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#include "options.h"
#include "header.h"
#include "websockets.h"
+#include "mprintf.h"
/* the typechecker doesn't work in C++ (yet) */
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index 898816844..316f39c4e 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -32,12 +32,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "8.4.0-DEV"
+#define LIBCURL_VERSION "8.6.0-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
-#define LIBCURL_VERSION_MINOR 4
+#define LIBCURL_VERSION_MINOR 6
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -59,7 +59,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 0x080400
+#define LIBCURL_VERSION_NUM 0x080600
/*
* This is the date and time when the full source package was created. The
diff --git a/include/curl/mprintf.h b/include/curl/mprintf.h
index dc5664bc5..4f704548d 100644
--- a/include/curl/mprintf.h
+++ b/include/curl/mprintf.h
@@ -34,19 +34,27 @@ extern "C" {
#if (defined(__GNUC__) || defined(__clang__)) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
- !defined(__MINGW32__) && !defined(CURL_NO_FMT_CHECKS)
-#define CURL_TEMP_PRINTF(a,b) __attribute__ ((format(printf, a, b)))
+ !defined(CURL_NO_FMT_CHECKS)
+#if defined(__MINGW32__) && !defined(__clang__)
+#define CURL_TEMP_PRINTF(fmt, arg) \
+ __attribute__((format(gnu_printf, fmt, arg)))
#else
-#define CURL_TEMP_PRINTF(a,b)
+#define CURL_TEMP_PRINTF(fmt, arg) \
+ __attribute__((format(printf, fmt, arg)))
+#endif
+#else
+#define CURL_TEMP_PRINTF(fmt, arg)
#endif
-CURL_EXTERN int curl_mprintf(const char *format, ...) CURL_TEMP_PRINTF(1, 2);
+CURL_EXTERN int curl_mprintf(const char *format, ...)
+ CURL_TEMP_PRINTF(1, 2);
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...)
CURL_TEMP_PRINTF(2, 3);
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...)
CURL_TEMP_PRINTF(2, 3);
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
- const char *format, ...) CURL_TEMP_PRINTF(3, 4);
+ const char *format, ...)
+ CURL_TEMP_PRINTF(3, 4);
CURL_EXTERN int curl_mvprintf(const char *format, va_list args)
CURL_TEMP_PRINTF(1, 0);
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args)
diff --git a/include/curl/system.h b/include/curl/system.h
index 97e0d037a..81a1b817d 100644
--- a/include/curl/system.h
+++ b/include/curl/system.h
@@ -141,29 +141,6 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
-#elif defined(__SYMBIAN32__)
-# if defined(__EABI__) /* Treat all ARM compilers equally */
-# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# elif defined(__CW32__)
-# pragma longlong on
-# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# elif defined(__VC32__)
-# define CURL_TYPEOF_CURL_OFF_T __int64
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# endif
-# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-
#elif defined(macintosh)
# include <ConditionalMacros.h>
# if TYPE_LONGLONG
@@ -201,14 +178,14 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__MINGW32__)
+# include <inttypes.h>
# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "I64d"
-# define CURL_FORMAT_CURL_OFF_TU "I64u"
+# define CURL_FORMAT_CURL_OFF_T PRId64
+# define CURL_FORMAT_CURL_OFF_TU PRIu64
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
-# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_TYPEOF_CURL_SOCKLEN_T int
# define CURL_PULL_SYS_TYPES_H 1
-# define CURL_PULL_WS2TCPIP_H 1
#elif defined(__VMS)
# if defined(__VAX)
@@ -370,7 +347,14 @@
/* ===================================== */
#elif defined(_MSC_VER)
-# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
+# if (_MSC_VER >= 1800)
+# include <inttypes.h>
+# define CURL_TYPEOF_CURL_OFF_T __int64
+# define CURL_FORMAT_CURL_OFF_T PRId64
+# define CURL_FORMAT_CURL_OFF_TU PRIu64
+# define CURL_SUFFIX_CURL_OFF_T i64
+# define CURL_SUFFIX_CURL_OFF_TU ui64
+# elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
@@ -432,15 +416,6 @@
#define CURL_PULL_SYS_POLL_H
#endif
-
-/* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file */
-/* ws2tcpip.h is required here to properly make type definitions below. */
-#ifdef CURL_PULL_WS2TCPIP_H
-# include <winsock2.h>
-# include <windows.h>
-# include <ws2tcpip.h>
-#endif
-
/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
/* sys/types.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_TYPES_H
diff --git a/include/curl/urlapi.h b/include/curl/urlapi.h
index 88cdeb3bc..91f8c4548 100644
--- a/include/curl/urlapi.h
+++ b/include/curl/urlapi.h
@@ -63,6 +63,7 @@ typedef enum {
CURLUE_BAD_SLASHES, /* 28 */
CURLUE_BAD_USER, /* 29 */
CURLUE_LACKS_IDN, /* 30 */
+ CURLUE_TOO_LARGE, /* 31 */
CURLUE_LAST
} CURLUcode;
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 6f849199c..51d52578e 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -47,20 +47,25 @@ if(USE_ARES)
include_directories(${CARES_INCLUDE_DIR})
endif()
-add_library(
- curlu # special libcurlu library just for unittests
- STATIC
- EXCLUDE_FROM_ALL
- ${HHEADERS} ${CSOURCES}
-)
-target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
+if(BUILD_TESTING)
+ add_library(
+ curlu # special libcurlu library just for unittests
+ STATIC
+ EXCLUDE_FROM_ALL
+ ${HHEADERS} ${CSOURCES}
+ )
+ target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
+endif()
if(ENABLE_CURLDEBUG)
# We must compile these sources separately to avoid memdebug.h redefinitions
# applying to them.
set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
-target_link_libraries(curlu PRIVATE ${CURL_LIBS})
+
+if(BUILD_TESTING)
+ target_link_libraries(curlu PRIVATE ${CURL_LIBS})
+endif()
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 3c0a70912..1237c8e99 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -110,7 +110,7 @@ libcurl_la_CFLAGS_EXTRA += $(CFLAG_CURL_SYMBOL_HIDING)
endif
libcurl_la_CPPFLAGS = $(AM_CPPFLAGS) $(libcurl_la_CPPFLAGS_EXTRA)
-libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(LDFLAGS) $(LIBCURL_LIBS)
+libcurl_la_LDFLAGS = $(AM_LDFLAGS) $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_LIBS)
libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA)
libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index e568ef953..627148abe 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -78,15 +78,19 @@ LIB_VTLS_HFILES = \
LIB_VQUIC_CFILES = \
vquic/curl_msh3.c \
vquic/curl_ngtcp2.c \
+ vquic/curl_osslq.c \
vquic/curl_quiche.c \
- vquic/vquic.c
+ vquic/vquic.c \
+ vquic/vquic-tls.c
LIB_VQUIC_HFILES = \
vquic/curl_msh3.h \
vquic/curl_ngtcp2.h \
+ vquic/curl_osslq.h \
vquic/curl_quiche.h \
vquic/vquic.h \
- vquic/vquic_int.h
+ vquic/vquic_int.h \
+ vquic/vquic-tls.h
LIB_VSSH_CFILES = \
vssh/libssh.c \
diff --git a/lib/Makefile.mk b/lib/Makefile.mk
index 5071600b5..95f281b7d 100644
--- a/lib/Makefile.mk
+++ b/lib/Makefile.mk
@@ -24,8 +24,8 @@
# Makefile to build curl parts with GCC-like toolchains and optional features.
#
-# Usage: [mingw32-]make -f Makefile.mk CFG=-feat1[-feat2][-feat3][...]
-# Example: [mingw32-]make -f Makefile.mk CFG=-zlib-ssl-libssh2-ipv6
+# Usage: make -f Makefile.mk CFG=-feat1[-feat2][-feat3][...]
+# Example: make -f Makefile.mk CFG=-zlib-ssl-libssh2-ipv6
#
# Look for ' ?=' to find all accepted customization variables.
@@ -40,10 +40,7 @@ endif
CFLAGS ?=
CPPFLAGS ?=
-RCFLAGS ?=
LDFLAGS ?=
-CURL_LDFLAGS_BIN ?=
-CURL_LDFLAGS_LIB ?=
LIBS ?=
CROSSPREFIX ?=
@@ -53,46 +50,21 @@ ifeq ($(CC),cc)
endif
CC := $(CROSSPREFIX)$(CC)
AR := $(CROSSPREFIX)$(AR)
-RC ?= $(CROSSPREFIX)windres
-
-# For compatibility
-ARCH ?=
-ifeq ($(ARCH),w64)
- TRIPLET := x86_64-w64-mingw32
- CFLAGS += -m64
- LDFLAGS += -m64
- RCFLAGS += --target=pe-x86-64
-else ifdef ARCH
- TRIPLET := i686-w64-mingw32
- CFLAGS += -m32
- LDFLAGS += -m32
- RCFLAGS += --target=pe-i386
-else
- TRIPLET ?= $(shell $(CC) -dumpmachine)
-endif
-BIN_EXT := .exe
+TRIPLET ?= $(shell $(CC) -dumpmachine)
-ifneq ($(findstring -w,$(TRIPLET)),)
- WIN32 := 1
-else ifneq ($(findstring msdos,$(TRIPLET)),)
+BIN_EXT :=
+
+ifneq ($(findstring msdos,$(TRIPLET)),)
# Cross-tools: https://github.com/andrewwutw/build-djgpp
MSDOS := 1
+ BIN_EXT := .exe
else ifneq ($(findstring amigaos,$(TRIPLET)),)
# Cross-tools: https://github.com/bebbo/amiga-gcc
AMIGA := 1
endif
CPPFLAGS += -I. -I$(PROOT)/include
-RCFLAGS += -I$(PROOT)/include
-
-ifndef WIN32
- DYN :=
-endif
-
-ifdef AMIGA
- BIN_EXT :=
-endif
### Deprecated settings. For compatibility.
@@ -115,37 +87,26 @@ ifneq ($(findstring -map,$(CFG)),)
MAP := 1
endif
-ifdef WIN32
- ifneq ($(findstring -unicode,$(CFG)),)
- CPPFLAGS += -DUNICODE -D_UNICODE
- CURL_LDFLAGS_BIN += -municode
- endif
-endif
-
# CPPFLAGS below are only necessary when building libcurl via 'lib' (see
# comments below about exceptions). Always include them anyway to match
# behavior of other build systems.
-# Linker options to exclude for shared mode executables.
-_LDFLAGS :=
-_LIBS :=
-
ifneq ($(findstring -sync,$(CFG)),)
CPPFLAGS += -DUSE_SYNC_DNS
else ifneq ($(findstring -ares,$(CFG)),)
LIBCARES_PATH ?= $(PROOT)/../c-ares
CPPFLAGS += -DUSE_ARES
CPPFLAGS += -I"$(LIBCARES_PATH)/include"
- _LDFLAGS += -L"$(LIBCARES_PATH)/lib"
- _LIBS += -lcares
+ LDFLAGS += -L"$(LIBCARES_PATH)/lib"
+ LIBS += -lcares
endif
ifneq ($(findstring -rtmp,$(CFG)),)
LIBRTMP_PATH ?= $(PROOT)/../librtmp
CPPFLAGS += -DUSE_LIBRTMP
CPPFLAGS += -I"$(LIBRTMP_PATH)"
- _LDFLAGS += -L"$(LIBRTMP_PATH)/librtmp"
- _LIBS += -lrtmp -lwinmm
+ LDFLAGS += -L"$(LIBRTMP_PATH)/librtmp"
+ LIBS += -lrtmp
ZLIB := 1
endif
@@ -153,23 +114,20 @@ ifneq ($(findstring -ssh2,$(CFG)),)
LIBSSH2_PATH ?= $(PROOT)/../libssh2
CPPFLAGS += -DUSE_LIBSSH2
CPPFLAGS += -I"$(LIBSSH2_PATH)/include"
- _LDFLAGS += -L"$(LIBSSH2_PATH)/lib"
- ifdef WIN32
- _LDFLAGS += -L"$(LIBSSH2_PATH)/win32"
- endif
- _LIBS += -lssh2
+ LDFLAGS += -L"$(LIBSSH2_PATH)/lib"
+ LIBS += -lssh2
else ifneq ($(findstring -libssh,$(CFG)),)
LIBSSH_PATH ?= $(PROOT)/../libssh
CPPFLAGS += -DUSE_LIBSSH
CPPFLAGS += -I"$(LIBSSH_PATH)/include"
- _LDFLAGS += -L"$(LIBSSH_PATH)/lib"
- _LIBS += -lssh
+ LDFLAGS += -L"$(LIBSSH_PATH)/lib"
+ LIBS += -lssh
else ifneq ($(findstring -wolfssh,$(CFG)),)
WOLFSSH_PATH ?= $(PROOT)/../wolfssh
CPPFLAGS += -DUSE_WOLFSSH
CPPFLAGS += -I"$(WOLFSSH_PATH)/include"
- _LDFLAGS += -L"$(WOLFSSH_PATH)/lib"
- _LIBS += -lwolfssh
+ LDFLAGS += -L"$(WOLFSSH_PATH)/lib"
+ LIBS += -lwolfssh
endif
ifneq ($(findstring -ssl,$(CFG)),)
@@ -179,9 +137,9 @@ ifneq ($(findstring -ssl,$(CFG)),)
OPENSSL_INCLUDE ?= $(OPENSSL_PATH)/include
OPENSSL_LIBPATH ?= $(OPENSSL_PATH)/lib
CPPFLAGS += -I"$(OPENSSL_INCLUDE)"
- _LDFLAGS += -L"$(OPENSSL_LIBPATH)"
+ LDFLAGS += -L"$(OPENSSL_LIBPATH)"
OPENSSL_LIBS ?= -lssl -lcrypto
- _LIBS += $(OPENSSL_LIBS)
+ LIBS += $(OPENSSL_LIBS)
ifneq ($(findstring -srp,$(CFG)),)
ifneq ($(wildcard $(OPENSSL_INCLUDE)/openssl/srp.h),)
@@ -196,20 +154,16 @@ ifneq ($(findstring -wolfssl,$(CFG)),)
CPPFLAGS += -DUSE_WOLFSSL
CPPFLAGS += -DSIZEOF_LONG_LONG=8
CPPFLAGS += -I"$(WOLFSSL_PATH)/include"
- _LDFLAGS += -L"$(WOLFSSL_PATH)/lib"
- _LIBS += -lwolfssl
+ LDFLAGS += -L"$(WOLFSSL_PATH)/lib"
+ LIBS += -lwolfssl
SSLLIBS += 1
endif
ifneq ($(findstring -mbedtls,$(CFG)),)
MBEDTLS_PATH ?= $(PROOT)/../mbedtls
CPPFLAGS += -DUSE_MBEDTLS
CPPFLAGS += -I"$(MBEDTLS_PATH)/include"
- _LDFLAGS += -L"$(MBEDTLS_PATH)/lib"
- _LIBS += -lmbedtls -lmbedx509 -lmbedcrypto
- SSLLIBS += 1
-endif
-ifneq ($(findstring -schannel,$(CFG)),)
- CPPFLAGS += -DUSE_SCHANNEL
+ LDFLAGS += -L"$(MBEDTLS_PATH)/lib"
+ LIBS += -lmbedtls -lmbedx509 -lmbedcrypto
SSLLIBS += 1
endif
@@ -217,21 +171,21 @@ ifneq ($(findstring -nghttp2,$(CFG)),)
NGHTTP2_PATH ?= $(PROOT)/../nghttp2
CPPFLAGS += -DUSE_NGHTTP2
CPPFLAGS += -I"$(NGHTTP2_PATH)/include"
- _LDFLAGS += -L"$(NGHTTP2_PATH)/lib"
- _LIBS += -lnghttp2
+ LDFLAGS += -L"$(NGHTTP2_PATH)/lib"
+ LIBS += -lnghttp2
endif
ifeq ($(findstring -nghttp3,$(CFG))$(findstring -ngtcp2,$(CFG)),-nghttp3-ngtcp2)
NGHTTP3_PATH ?= $(PROOT)/../nghttp3
CPPFLAGS += -DUSE_NGHTTP3
CPPFLAGS += -I"$(NGHTTP3_PATH)/include"
- _LDFLAGS += -L"$(NGHTTP3_PATH)/lib"
- _LIBS += -lnghttp3
+ LDFLAGS += -L"$(NGHTTP3_PATH)/lib"
+ LIBS += -lnghttp3
NGTCP2_PATH ?= $(PROOT)/../ngtcp2
CPPFLAGS += -DUSE_NGTCP2
CPPFLAGS += -I"$(NGTCP2_PATH)/include"
- _LDFLAGS += -L"$(NGTCP2_PATH)/lib"
+ LDFLAGS += -L"$(NGTCP2_PATH)/lib"
NGTCP2_LIBS ?=
ifeq ($(NGTCP2_LIBS),)
@@ -246,7 +200,7 @@ ifeq ($(findstring -nghttp3,$(CFG))$(findstring -ngtcp2,$(CFG)),-nghttp3-ngtcp2)
endif
endif
- _LIBS += -lngtcp2 $(NGTCP2_LIBS)
+ LIBS += -lngtcp2 $(NGTCP2_LIBS)
endif
ifneq ($(findstring -zlib,$(CFG))$(ZLIB),)
@@ -254,59 +208,51 @@ ifneq ($(findstring -zlib,$(CFG))$(ZLIB),)
# These CPPFLAGS are also required when compiling the curl tool via 'src'.
CPPFLAGS += -DHAVE_LIBZ
CPPFLAGS += -I"$(ZLIB_PATH)/include"
- _LDFLAGS += -L"$(ZLIB_PATH)/lib"
+ LDFLAGS += -L"$(ZLIB_PATH)/lib"
ZLIB_LIBS ?= -lz
- _LIBS += $(ZLIB_LIBS)
+ LIBS += $(ZLIB_LIBS)
ZLIB := 1
endif
ifneq ($(findstring -zstd,$(CFG)),)
ZSTD_PATH ?= $(PROOT)/../zstd
CPPFLAGS += -DHAVE_ZSTD
CPPFLAGS += -I"$(ZSTD_PATH)/include"
- _LDFLAGS += -L"$(ZSTD_PATH)/lib"
+ LDFLAGS += -L"$(ZSTD_PATH)/lib"
ZSTD_LIBS ?= -lzstd
- _LIBS += $(ZSTD_LIBS)
+ LIBS += $(ZSTD_LIBS)
endif
ifneq ($(findstring -brotli,$(CFG)),)
BROTLI_PATH ?= $(PROOT)/../brotli
CPPFLAGS += -DHAVE_BROTLI
CPPFLAGS += -I"$(BROTLI_PATH)/include"
- _LDFLAGS += -L"$(BROTLI_PATH)/lib"
+ LDFLAGS += -L"$(BROTLI_PATH)/lib"
BROTLI_LIBS ?= -lbrotlidec -lbrotlicommon
- _LIBS += $(BROTLI_LIBS)
+ LIBS += $(BROTLI_LIBS)
endif
ifneq ($(findstring -gsasl,$(CFG)),)
LIBGSASL_PATH ?= $(PROOT)/../gsasl
CPPFLAGS += -DUSE_GSASL
CPPFLAGS += -I"$(LIBGSASL_PATH)/include"
- _LDFLAGS += -L"$(LIBGSASL_PATH)/lib"
- _LIBS += -lgsasl
+ LDFLAGS += -L"$(LIBGSASL_PATH)/lib"
+ LIBS += -lgsasl
endif
ifneq ($(findstring -idn2,$(CFG)),)
LIBIDN2_PATH ?= $(PROOT)/../libidn2
CPPFLAGS += -DUSE_LIBIDN2
CPPFLAGS += -I"$(LIBIDN2_PATH)/include"
- _LDFLAGS += -L"$(LIBIDN2_PATH)/lib"
- _LIBS += -lidn2
+ LDFLAGS += -L"$(LIBIDN2_PATH)/lib"
+ LIBS += -lidn2
ifneq ($(findstring -psl,$(CFG)),)
LIBPSL_PATH ?= $(PROOT)/../libpsl
CPPFLAGS += -DUSE_LIBPSL
CPPFLAGS += -I"$(LIBPSL_PATH)/include"
- _LDFLAGS += -L"$(LIBPSL_PATH)/lib"
- _LIBS += -lpsl
+ LDFLAGS += -L"$(LIBPSL_PATH)/lib"
+ LIBS += -lpsl
endif
-else ifneq ($(findstring -winidn,$(CFG)),)
- CPPFLAGS += -DUSE_WIN32_IDN
- _LIBS += -lnormaliz
endif
-ifneq ($(findstring -sspi,$(CFG)),)
- ifdef WIN32
- CPPFLAGS += -DUSE_WINDOWS_SSPI
- endif
-endif
ifneq ($(findstring -ipv6,$(CFG)),)
CPPFLAGS += -DENABLE_IPV6
endif
@@ -314,26 +260,14 @@ endif
ifneq ($(findstring -watt,$(CFG))$(MSDOS),)
WATT_PATH ?= $(PROOT)/../watt
CPPFLAGS += -I"$(WATT_PATH)/inc"
- _LDFLAGS += -L"$(WATT_PATH)/lib"
- _LIBS += -lwatt
-endif
-
-ifdef WIN32
- ifeq ($(findstring -lldap,$(LIBS)),)
- _LIBS += -lwldap32
- endif
- _LIBS += -lws2_32 -lcrypt32 -lbcrypt
+ LDFLAGS += -L"$(WATT_PATH)/lib"
+ LIBS += -lwatt
endif
ifneq ($(findstring 11,$(subst $(subst ,, ),,$(SSLLIBS))),)
CPPFLAGS += -DCURL_WITH_MULTI_SSL
endif
-ifndef DYN
- LDFLAGS += $(_LDFLAGS)
- LIBS += $(_LIBS)
-endif
-
### Common rules
OBJ_DIR := $(TRIPLET)
@@ -360,9 +294,6 @@ $(OBJ_DIR):
$(OBJ_DIR)/%.o: %.c
$(CC) -W -Wall $(CFLAGS) $(CPPFLAGS) -c $< -o $@
-$(OBJ_DIR)/%.res: %.rc
- $(RC) -O coff $(RCFLAGS) -i $< -o $@
-
clean:
@$(call DEL, $(TOCLEAN))
@$(RMDIR) $(OBJ_DIR)
@@ -375,42 +306,23 @@ distclean vclean: clean
ifdef LOCAL
CPPFLAGS += -DBUILDING_LIBCURL
-ifdef WIN32
-CPPFLAGS += -DCURL_STATICLIB
-endif
### Sources and targets
-# Provides CSOURCES, HHEADERS, LIB_RCFILES
+# Provides CSOURCES, HHEADERS
include Makefile.inc
vpath %.c vauth vquic vssh vtls
libcurl_a_LIBRARY := libcurl.a
-ifdef WIN32
-CURL_DLL_SUFFIX ?=
-libcurl_dll_LIBRARY := libcurl$(CURL_DLL_SUFFIX).dll
-libcurl_dll_a_LIBRARY := libcurl.dll.a
-ifeq ($(findstring -trackmem,$(CFG)),)
-CURL_LDFLAGS_LIB += $(PROOT)/libcurl.def
-endif
-ifdef MAP
-libcurl_map_LIBRARY := libcurl$(CURL_DLL_SUFFIX).map
-CURL_LDFLAGS_LIB += -Wl,-Map,$(libcurl_map_LIBRARY)
-endif
-endif
-TARGETS := $(libcurl_a_LIBRARY) $(libcurl_dll_LIBRARY)
+TARGETS := $(libcurl_a_LIBRARY)
libcurl_a_OBJECTS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(notdir $(strip $(CSOURCES))))
libcurl_a_DEPENDENCIES := $(strip $(CSOURCES) $(HHEADERS))
-ifdef WIN32
-libcurl_dll_OBJECTS := $(libcurl_a_OBJECTS)
-libcurl_dll_OBJECTS += $(patsubst %.rc,$(OBJ_DIR)/%.res,$(strip $(LIB_RCFILES)))
-endif
-TOCLEAN := $(libcurl_dll_OBJECTS)
-TOVCLEAN := $(libcurl_dll_LIBRARY:.dll=.def) $(libcurl_dll_a_LIBRARY) $(libcurl_map_LIBRARY)
+TOCLEAN :=
+TOVCLEAN :=
### Rules
@@ -418,9 +330,5 @@ $(libcurl_a_LIBRARY): $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
@$(call DEL, $@)
$(AR) rcs $@ $(libcurl_a_OBJECTS)
-$(libcurl_dll_LIBRARY): $(libcurl_dll_OBJECTS)
- $(CC) $(LDFLAGS) -shared $(CURL_LDFLAGS_LIB) -o $@ $(libcurl_dll_OBJECTS) $(LIBS) \
- -Wl,--output-def,$(@:.dll=.def),--out-implib,$(libcurl_dll_a_LIBRARY)
-
all: $(OBJ_DIR) $(TARGETS)
endif
diff --git a/lib/altsvc.c b/lib/altsvc.c
index 22b0b69c7..e9f62bf0e 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -97,7 +97,7 @@ static struct altsvc *altsvc_createid(const char *srchost,
unsigned int srcport,
unsigned int dstport)
{
- struct altsvc *as = calloc(sizeof(struct altsvc), 1);
+ struct altsvc *as = calloc(1, sizeof(struct altsvc));
size_t hlen;
size_t dlen;
if(!as)
@@ -106,9 +106,11 @@ static struct altsvc *altsvc_createid(const char *srchost,
dlen = strlen(dsthost);
DEBUGASSERT(hlen);
DEBUGASSERT(dlen);
- if(!hlen || !dlen)
+ if(!hlen || !dlen) {
/* bad input */
+ free(as);
return NULL;
+ }
if((hlen > 2) && srchost[0] == '[') {
/* IPv6 address, strip off brackets */
srchost++;
@@ -123,15 +125,13 @@ static struct altsvc *altsvc_createid(const char *srchost,
dlen -= 2;
}
- as->src.host = Curl_memdup(srchost, hlen + 1);
+ as->src.host = Curl_memdup0(srchost, hlen);
if(!as->src.host)
goto error;
- as->src.host[hlen] = 0;
- as->dst.host = Curl_memdup(dsthost, dlen + 1);
+ as->dst.host = Curl_memdup0(dsthost, dlen);
if(!as->dst.host)
goto error;
- as->dst.host[dlen] = 0;
as->src.alpnid = srcalpnid;
as->dst.alpnid = dstalpnid;
@@ -301,7 +301,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
*/
struct altsvcinfo *Curl_altsvc_init(void)
{
- struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1);
+ struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo));
if(!asi)
return NULL;
Curl_llist_init(&asi->list, NULL);
@@ -335,9 +335,6 @@ CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file)
CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
{
DEBUGASSERT(asi);
- if(!ctrl)
- /* unexpected */
- return CURLE_BAD_FUNCTION_ARGUMENT;
asi->flags = ctrl;
return CURLE_OK;
}
diff --git a/lib/arpa_telnet.h b/lib/arpa_telnet.h
index de1373800..228b4466e 100644
--- a/lib/arpa_telnet.h
+++ b/lib/arpa_telnet.h
@@ -56,12 +56,14 @@ static const char * const telnetoptions[]=
"TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC",
"OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON"
};
+#define CURL_TELOPT(x) telnetoptions[x]
+#else
+#define CURL_TELOPT(x) ""
#endif
#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON
#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM)
-#define CURL_TELOPT(x) telnetoptions[x]
#define CURL_NTELOPTS 40
@@ -103,7 +105,12 @@ static const char * const telnetcmds[]=
#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \
((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) )
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM]
+#else
+#define CURL_TELCMD(x) ""
+#endif
#endif /* CURL_DISABLE_TELNET */
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index e73e41dab..76efba78a 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -60,13 +60,13 @@
#include "progress.h"
#include "timediff.h"
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- defined(WIN32)
-# define CARES_STATICLIB
-# endif
-# include <ares.h>
-# include <ares_version.h> /* really old c-ares didn't include this by
- itself */
+#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ defined(_WIN32)
+# define CARES_STATICLIB
+#endif
+#include <ares.h>
+#include <ares_version.h> /* really old c-ares didn't include this by
+ itself */
#if ARES_VERSION >= 0x010500
/* c-ares 1.5.0 or later, the callback proto is modified */
@@ -173,10 +173,26 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
int status;
struct ares_options options;
int optmask = ARES_OPT_SOCK_STATE_CB;
+ static int ares_ver = 0;
options.sock_state_cb = sock_state_cb;
options.sock_state_cb_data = easy;
- options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
- optmask |= ARES_OPT_TIMEOUTMS;
+ if(ares_ver == 0)
+ ares_version(&ares_ver);
+
+ if(ares_ver < 0x011400) { /* c-ares included similar change since 1.20.0 */
+ options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
+ optmask |= ARES_OPT_TIMEOUTMS;
+ }
+
+ /*
+ if c ares < 1.20.0: curl set timeout to CARES_TIMEOUT_PER_ATTEMPT (2s)
+
+ if c-ares >= 1.20.0 it already has the timeout to 2s, curl does not need
+ to set the timeout value;
+
+ if c-ares >= 1.24.0, user can set the timeout via /etc/resolv.conf to
+ overwrite c-ares' timeout.
+ */
status = ares_init_options((ares_channel*)resolver, &options, optmask);
if(status != ARES_SUCCESS) {
@@ -755,7 +771,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
size_t namelen = strlen(hostname);
*waitp = 0; /* default to synchronous response */
- res = calloc(sizeof(struct thread_data) + namelen, 1);
+ res = calloc(1, sizeof(struct thread_data) + namelen);
if(res) {
strcpy(res->hostname, hostname);
data->state.async.hostname = res->hostname;
@@ -858,6 +874,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
case ARES_ENODATA:
case ARES_EBADSTR:
default:
+ DEBUGF(infof(data, "bad servers set"));
result = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
@@ -896,6 +913,7 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
}
else {
if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
+ DEBUGF(infof(data, "bad DNS IPv4 address"));
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
@@ -923,6 +941,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
}
else {
if(Curl_inet_pton(AF_INET6, local_ip6, a6) != 1) {
+ DEBUGF(infof(data, "bad DNS IPv6 address"));
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index a2e294f8f..d4d382add 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -54,6 +54,7 @@
# define RESOLVER_ENOMEM ENOMEM
#endif
+#include "system_win32.h"
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -144,9 +145,22 @@ static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints);
+#ifdef _WIN32
+/* Thread sync data used by GetAddrInfoExW for win8+ */
+struct thread_sync_data_w8
+{
+ OVERLAPPED overlapped;
+ ADDRINFOEXW_ *res;
+ HANDLE cancel_ev;
+ ADDRINFOEXW_ hints;
+};
+#endif
/* Data for synchronization between resolver thread and its parent */
struct thread_sync_data {
+#ifdef _WIN32
+ struct thread_sync_data_w8 w8;
+#endif
curl_mutex_t *mtx;
int done;
int port;
@@ -165,6 +179,9 @@ struct thread_sync_data {
};
struct thread_data {
+#ifdef _WIN32
+ HANDLE complete_ev;
+#endif
curl_thread_t thread_hnd;
unsigned int poll_interval;
timediff_t interval_end;
@@ -196,7 +213,7 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd)
* the other end (for reading) is always closed in the parent thread.
*/
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
- sclose(tsd->sock_pair[1]);
+ wakeup_close(tsd->sock_pair[1]);
}
#endif
memset(tsd, 0, sizeof(*tsd));
@@ -233,8 +250,8 @@ int init_thread_sync_data(struct thread_data *td,
Curl_mutex_init(tsd->mtx);
#ifndef CURL_DISABLE_SOCKETPAIR
- /* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
- if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
+ /* create socket pair or pipe */
+ if(wakeup_create(&tsd->sock_pair[0]) < 0) {
tsd->sock_pair[0] = CURL_SOCKET_BAD;
tsd->sock_pair[1] = CURL_SOCKET_BAD;
goto err_exit;
@@ -254,7 +271,7 @@ int init_thread_sync_data(struct thread_data *td,
err_exit:
#ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
- sclose(tsd->sock_pair[0]);
+ wakeup_close(tsd->sock_pair[0]);
tsd->sock_pair[0] = CURL_SOCKET_BAD;
}
#endif
@@ -276,6 +293,151 @@ static CURLcode getaddrinfo_complete(struct Curl_easy *data)
return result;
}
+#ifdef _WIN32
+static VOID WINAPI
+query_complete(DWORD err, DWORD bytes, LPWSAOVERLAPPED overlapped)
+{
+ size_t ss_size;
+ const ADDRINFOEXW_ *ai;
+ struct Curl_addrinfo *ca;
+ struct Curl_addrinfo *cafirst = NULL;
+ struct Curl_addrinfo *calast = NULL;
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wcast-align"
+#endif
+ struct thread_sync_data *tsd =
+ CONTAINING_RECORD(overlapped, struct thread_sync_data, w8.overlapped);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ struct thread_data *td = tsd->td;
+ const ADDRINFOEXW_ *res = tsd->w8.res;
+ int error = (int)err;
+ (void)bytes;
+
+ if(error == ERROR_SUCCESS) {
+ /* traverse the addrinfo list */
+
+ for(ai = res; ai != NULL; ai = ai->ai_next) {
+ size_t namelen = ai->ai_canonname ? wcslen(ai->ai_canonname) + 1 : 0;
+ /* ignore elements with unsupported address family, */
+ /* settle family-specific sockaddr structure size. */
+ if(ai->ai_family == AF_INET)
+ ss_size = sizeof(struct sockaddr_in);
+#ifdef ENABLE_IPV6
+ else if(ai->ai_family == AF_INET6)
+ ss_size = sizeof(struct sockaddr_in6);
+#endif
+ else
+ continue;
+
+ /* ignore elements without required address info */
+ if(!ai->ai_addr || !(ai->ai_addrlen > 0))
+ continue;
+
+ /* ignore elements with bogus address size */
+ if((size_t)ai->ai_addrlen < ss_size)
+ continue;
+
+ ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
+ if(!ca) {
+ error = EAI_MEMORY;
+ break;
+ }
+
+ /* copy each structure member individually, member ordering, */
+ /* size, or padding might be different for each platform. */
+ ca->ai_flags = ai->ai_flags;
+ ca->ai_family = ai->ai_family;
+ ca->ai_socktype = ai->ai_socktype;
+ ca->ai_protocol = ai->ai_protocol;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
+ ca->ai_addr = NULL;
+ ca->ai_canonname = NULL;
+ ca->ai_next = NULL;
+
+ ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
+ memcpy(ca->ai_addr, ai->ai_addr, ss_size);
+
+ if(namelen) {
+ size_t i;
+ ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
+ for(i = 0; i < namelen; ++i) /* convert wide string to ascii */
+ ca->ai_canonname[i] = (char)ai->ai_canonname[i];
+ ca->ai_canonname[namelen] = '\0';
+ }
+
+ /* if the return list is empty, this becomes the first element */
+ if(!cafirst)
+ cafirst = ca;
+
+ /* add this element last in the return list */
+ if(calast)
+ calast->ai_next = ca;
+ calast = ca;
+ }
+
+ /* if we failed, also destroy the Curl_addrinfo list */
+ if(error) {
+ Curl_freeaddrinfo(cafirst);
+ cafirst = NULL;
+ }
+ else if(!cafirst) {
+#ifdef EAI_NONAME
+ /* rfc3493 conformant */
+ error = EAI_NONAME;
+#else
+ /* rfc3493 obsoleted */
+ error = EAI_NODATA;
+#endif
+#ifdef USE_WINSOCK
+ SET_SOCKERRNO(error);
+#endif
+ }
+ tsd->res = cafirst;
+ }
+
+ if(tsd->w8.res) {
+ Curl_FreeAddrInfoExW(tsd->w8.res);
+ tsd->w8.res = NULL;
+ }
+
+ if(error) {
+ tsd->sock_error = SOCKERRNO?SOCKERRNO:error;
+ if(tsd->sock_error == 0)
+ tsd->sock_error = RESOLVER_ENOMEM;
+ }
+ else {
+ Curl_addrinfo_set_port(tsd->res, tsd->port);
+ }
+
+ Curl_mutex_acquire(tsd->mtx);
+ if(tsd->done) {
+ /* too late, gotta clean up the mess */
+ Curl_mutex_release(tsd->mtx);
+ destroy_thread_sync_data(tsd);
+ free(td);
+ }
+ else {
+#ifndef CURL_DISABLE_SOCKETPAIR
+ char buf[1];
+ if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
+ /* DNS has been resolved, signal client task */
+ buf[0] = 1;
+ if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
+ /* update sock_erro to errno */
+ tsd->sock_error = SOCKERRNO;
+ }
+ }
+#endif
+ tsd->done = 1;
+ Curl_mutex_release(tsd->mtx);
+ if(td->complete_ev)
+ SetEvent(td->complete_ev); /* Notify caller that the query completed */
+ }
+}
+#endif
#ifdef HAVE_GETADDRINFO
@@ -320,7 +482,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
/* DNS has been resolved, signal client task */
buf[0] = 1;
- if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
+ if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
/* update sock_erro to errno */
tsd->sock_error = SOCKERRNO;
}
@@ -391,9 +553,21 @@ static void destroy_async_data(struct Curl_async *async)
Curl_mutex_release(td->tsd.mtx);
if(!done) {
+#ifdef _WIN32
+ if(td->complete_ev)
+ CloseHandle(td->complete_ev);
+ else
+#endif
Curl_thread_destroy(td->thread_hnd);
}
else {
+#ifdef _WIN32
+ if(td->complete_ev) {
+ Curl_GetAddrInfoExCancel(&td->tsd.w8.cancel_ev);
+ WaitForSingleObject(td->complete_ev, INFINITE);
+ CloseHandle(td->complete_ev);
+ }
+#endif
if(td->thread_hnd != curl_thread_t_null)
Curl_thread_join(&td->thread_hnd);
@@ -439,6 +613,9 @@ static bool init_resolve_thread(struct Curl_easy *data,
asp->status = 0;
asp->dns = NULL;
td->thread_hnd = curl_thread_t_null;
+#ifdef _WIN32
+ td->complete_ev = NULL;
+#endif
if(!init_thread_sync_data(td, hostname, port, hints)) {
asp->tdata = NULL;
@@ -454,6 +631,41 @@ static bool init_resolve_thread(struct Curl_easy *data,
/* The thread will set this to 1 when complete. */
td->tsd.done = 0;
+#ifdef _WIN32
+ if(Curl_isWindows8OrGreater && Curl_FreeAddrInfoExW &&
+ Curl_GetAddrInfoExCancel && Curl_GetAddrInfoExW) {
+#define MAX_NAME_LEN 256 /* max domain name is 253 chars */
+#define MAX_PORT_LEN 8
+ WCHAR namebuf[MAX_NAME_LEN];
+ WCHAR portbuf[MAX_PORT_LEN];
+ /* calculate required length */
+ int w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, hostname,
+ -1, NULL, 0);
+ if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
+ /* do utf8 conversion */
+ w_len = MultiByteToWideChar(CP_UTF8, 0, hostname, -1, namebuf, w_len);
+ if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
+ swprintf(portbuf, MAX_PORT_LEN, L"%d", port);
+ td->tsd.w8.hints.ai_family = hints->ai_family;
+ td->tsd.w8.hints.ai_socktype = hints->ai_socktype;
+ td->complete_ev = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if(!td->complete_ev) {
+ /* failed to start, mark it as done here for proper cleanup. */
+ td->tsd.done = 1;
+ goto err_exit;
+ }
+ err = Curl_GetAddrInfoExW(namebuf, portbuf, NS_DNS,
+ NULL, &td->tsd.w8.hints, &td->tsd.w8.res,
+ NULL, &td->tsd.w8.overlapped,
+ &query_complete, &td->tsd.w8.cancel_ev);
+ if(err != WSA_IO_PENDING)
+ query_complete(err, 0, &td->tsd.w8.overlapped);
+ return TRUE;
+ }
+ }
+ }
+#endif
+
#ifdef HAVE_GETADDRINFO
td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
#else
@@ -490,9 +702,22 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
DEBUGASSERT(data);
td = data->state.async.tdata;
DEBUGASSERT(td);
+#ifdef _WIN32
+ DEBUGASSERT(td->complete_ev || td->thread_hnd != curl_thread_t_null);
+#else
DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
+#endif
/* wait for the thread to resolve the name */
+#ifdef _WIN32
+ if(td->complete_ev) {
+ WaitForSingleObject(td->complete_ev, INFINITE);
+ CloseHandle(td->complete_ev);
+ if(entry)
+ result = getaddrinfo_complete(data);
+ }
+ else
+#endif
if(Curl_thread_join(&td->thread_hnd)) {
if(entry)
result = getaddrinfo_complete(data);
diff --git a/lib/base64.c b/lib/base64.c
index 2a49b5acd..919eb6235 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -31,6 +31,7 @@
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
!defined(CURL_DISABLE_IMAP) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL)
#include "curl/curl.h"
#include "warnless.h"
diff --git a/lib/bufref.c b/lib/bufref.c
index ce686b6f3..f0a0e2a7d 100644
--- a/lib/bufref.c
+++ b/lib/bufref.c
@@ -25,6 +25,7 @@
#include "curl_setup.h"
#include "urldata.h"
#include "bufref.h"
+#include "strdup.h"
#include "curl_memory.h"
#include "memdebug.h"
@@ -116,12 +117,9 @@ CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len)
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
if(ptr) {
- cpy = malloc(len + 1);
+ cpy = Curl_memdup0(ptr, len);
if(!cpy)
return CURLE_OUT_OF_MEMORY;
- if(len)
- memcpy(cpy, ptr, len);
- cpy[len] = '\0';
}
Curl_bufref_set(br, cpy, len, curl_free);
diff --git a/lib/c-hyper.c b/lib/c-hyper.c
index 5726ff1cc..d02ecd73a 100644
--- a/lib/c-hyper.c
+++ b/lib/c-hyper.c
@@ -22,6 +22,10 @@
*
***************************************************************************/
+/* Curl's integration with Hyper. This replaces certain functions in http.c,
+ * based on configuration #defines. This implementation supports HTTP/1.1 but
+ * not HTTP/2.
+ */
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
@@ -144,7 +148,7 @@ static int hyper_each_header(void *userdata,
if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) {
failf(data, "Too long response header");
- data->state.hresult = CURLE_OUT_OF_MEMORY;
+ data->state.hresult = CURLE_TOO_LARGE;
return HYPER_ITER_BREAK;
}
@@ -172,17 +176,15 @@ static int hyper_each_header(void *userdata,
Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
- if(!data->state.hconnect || !data->set.suppress_connect_headers) {
- writetype = CLIENTWRITE_HEADER;
- if(data->state.hconnect)
- writetype |= CLIENTWRITE_CONNECT;
- if(data->req.httpcode/100 == 1)
- writetype |= CLIENTWRITE_1XX;
- result = Curl_client_write(data, writetype, headp, len);
- if(result) {
- data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
- return HYPER_ITER_BREAK;
- }
+ writetype = CLIENTWRITE_HEADER;
+ if(data->state.hconnect)
+ writetype |= CLIENTWRITE_CONNECT;
+ if(data->req.httpcode/100 == 1)
+ writetype |= CLIENTWRITE_1XX;
+ result = Curl_client_write(data, writetype, headp, len);
+ if(result) {
+ data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
+ return HYPER_ITER_BREAK;
}
result = Curl_bump_headersize(data, len, FALSE);
@@ -201,7 +203,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
struct SingleRequest *k = &data->req;
CURLcode result = CURLE_OK;
- if(0 == k->bodywrites++) {
+ if(0 == k->bodywrites) {
bool done = FALSE;
#if defined(USE_NTLM)
struct connectdata *conn = data->conn;
@@ -241,11 +243,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
return HYPER_ITER_BREAK;
}
}
- if(k->ignorebody)
- return HYPER_ITER_CONTINUE;
- if(0 == len)
- return HYPER_ITER_CONTINUE;
- Curl_debug(data, CURLINFO_DATA_IN, buf, len);
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
if(result) {
@@ -253,12 +250,6 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
return HYPER_ITER_BREAK;
}
- data->req.bytecount += len;
- result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
- if(result) {
- data->state.hresult = result;
- return HYPER_ITER_BREAK;
- }
return HYPER_ITER_CONTINUE;
}
@@ -310,13 +301,14 @@ static CURLcode status_line(struct Curl_easy *data,
Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
len);
- if(!data->state.hconnect || !data->set.suppress_connect_headers) {
- writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
- result = Curl_client_write(data, writetype,
- Curl_dyn_ptr(&data->state.headerb), len);
- if(result)
- return result;
- }
+ writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
+ if(data->state.hconnect)
+ writetype |= CLIENTWRITE_CONNECT;
+ result = Curl_client_write(data, writetype,
+ Curl_dyn_ptr(&data->state.headerb), len);
+ if(result)
+ return result;
+
result = Curl_bump_headersize(data, len, FALSE);
return result;
}
@@ -333,6 +325,9 @@ static CURLcode empty_header(struct Curl_easy *data)
CURLE_WRITE_ERROR : CURLE_OK;
if(result)
failf(data, "hyperstream: couldn't pass blank header");
+ /* Hyper does chunked decoding itself. If it was added during
+ * response header processing, remove it again. */
+ Curl_cwriter_remove_by_name(data, "chunked");
}
return result;
}
@@ -551,11 +546,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
static CURLcode debug_request(struct Curl_easy *data,
const char *method,
- const char *path,
- bool h2)
+ const char *path)
{
- char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
- h2?"2":"1.1");
+ char *req = aprintf("%s %s HTTP/1.1\r\n", method, path);
if(!req)
return CURLE_OUT_OF_MEMORY;
Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
@@ -637,7 +630,6 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
static CURLcode request_target(struct Curl_easy *data,
struct connectdata *conn,
const char *method,
- bool h2,
hyper_request *req)
{
CURLcode result;
@@ -649,26 +641,13 @@ static CURLcode request_target(struct Curl_easy *data,
if(result)
return result;
- if(h2 && hyper_request_set_uri_parts(req,
- /* scheme */
- (uint8_t *)data->state.up.scheme,
- strlen(data->state.up.scheme),
- /* authority */
- (uint8_t *)conn->host.name,
- strlen(conn->host.name),
- /* path_and_query */
- (uint8_t *)Curl_dyn_uptr(&r),
- Curl_dyn_len(&r))) {
- failf(data, "error setting uri parts to hyper");
- result = CURLE_OUT_OF_MEMORY;
- }
- else if(!h2 && hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
+ if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
Curl_dyn_len(&r))) {
failf(data, "error setting uri to hyper");
result = CURLE_OUT_OF_MEMORY;
}
else
- result = debug_request(data, method, Curl_dyn_ptr(&r), h2);
+ result = debug_request(data, method, Curl_dyn_ptr(&r));
Curl_dyn_free(&r);
@@ -899,7 +878,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
const char *p_accept; /* Accept: string */
const char *method;
Curl_HttpReq httpreq;
- bool h2 = FALSE;
const char *te = NULL; /* transfer-encoding */
hyper_code rc;
@@ -907,6 +885,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
may be parts of the request that is not yet sent, since we can deal with
the rest of the request in the PERFORM phase. */
*done = TRUE;
+ Curl_client_cleanup(data);
infof(data, "Time for the Hyper dance");
memset(h, 0, sizeof(struct hyptransfer));
@@ -917,6 +896,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
Curl_http_method(data, conn, &method, &httpreq);
+ DEBUGASSERT(data->req.bytecount == 0);
+
/* setup the authentication headers */
{
char *pq = NULL;
@@ -972,8 +953,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
if(conn->alpn == CURL_HTTP_VERSION_2) {
- hyper_clientconn_options_http2(options, 1);
- h2 = TRUE;
+ failf(data, "ALPN protocol h2 not supported with Hyper");
+ result = CURLE_UNSUPPORTED_PROTOCOL;
+ goto error;
}
hyper_clientconn_options_set_preserve_header_case(options, 1);
hyper_clientconn_options_set_preserve_header_order(options, 1);
@@ -1024,7 +1006,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
}
else {
- if(!h2 && !data->state.disableexpect) {
+ if(!data->state.disableexpect) {
data->state.expect100header = TRUE;
}
}
@@ -1035,7 +1017,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
- result = request_target(data, conn, method, h2, req);
+ result = request_target(data, conn, method, req);
if(result)
goto error;
@@ -1056,19 +1038,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result)
goto error;
- if(!h2) {
- if(data->state.aptr.host) {
- result = Curl_hyper_header(data, headers, data->state.aptr.host);
- if(result)
- goto error;
- }
- }
- else {
- /* For HTTP/2, we show the Host: header as if we sent it, to make it look
- like for HTTP/1 but it isn't actually sent since :authority is then
- used. */
- Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
- strlen(data->state.aptr.host));
+ if(data->state.aptr.host) {
+ result = Curl_hyper_header(data, headers, data->state.aptr.host);
+ if(result)
+ goto error;
}
if(data->state.aptr.proxyuserpwd) {
diff --git a/lib/cf-h1-proxy.c b/lib/cf-h1-proxy.c
index 674802114..167e5315a 100644
--- a/lib/cf-h1-proxy.c
+++ b/lib/cf-h1-proxy.c
@@ -70,6 +70,7 @@ struct h1_tunnel_state {
struct dynbuf request_data;
size_t nsent;
size_t headerlines;
+ struct Curl_chunker ch;
enum keeponval {
KEEPON_DONE,
KEEPON_CONNECT,
@@ -133,6 +134,7 @@ static CURLcode tunnel_init(struct Curl_cfilter *cf,
Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
Curl_dyn_init(&ts->request_data, DYN_HTTP_REQUEST);
+ Curl_httpchunk_init(data, &ts->ch, TRUE);
*pts = ts;
connkeep(cf->conn, "HTTP proxy CONNECT");
@@ -146,14 +148,6 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
{
if(ts->tunnel_state == new_state)
return;
- /* leaving this one */
- switch(ts->tunnel_state) {
- case H1_TUNNEL_CONNECT:
- data->req.ignorebody = FALSE;
- break;
- default:
- break;
- }
/* entering this one */
switch(new_state) {
case H1_TUNNEL_INIT:
@@ -183,7 +177,7 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
infof(data, "CONNECT phase completed");
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case H1_TUNNEL_FAILED:
if(new_state == H1_TUNNEL_FAILED)
CURL_TRC_CF(data, cf, "new tunnel state 'failed'");
@@ -212,6 +206,7 @@ static void tunnel_free(struct Curl_cfilter *cf,
h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
Curl_dyn_free(&ts->rcvbuf);
Curl_dyn_free(&ts->request_data);
+ Curl_httpchunk_free(data, &ts->ch);
free(ts);
cf->ctx = NULL;
}
@@ -344,8 +339,8 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
STRCONST("chunked"))) {
infof(data, "CONNECT responded chunked");
ts->chunked_encoding = TRUE;
- /* init our chunky engine */
- Curl_httpchunk_init(data);
+ /* reset our chunky engine */
+ Curl_httpchunk_reset(data, &ts->ch, TRUE);
}
}
else if(Curl_compareheader(header,
@@ -373,8 +368,8 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
struct SingleRequest *k = &data->req;
curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
char *linep;
- size_t perline;
- int error;
+ size_t line_len;
+ int error, writetype;
#define SELECT_OK 0
#define SELECT_ERROR 1
@@ -386,12 +381,12 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
return CURLE_OK;
while(ts->keepon) {
- ssize_t gotbytes;
+ ssize_t nread;
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(data, tunnelsocket, &byte, 1, &gotbytes);
+ result = Curl_read(data, tunnelsocket, &byte, 1, &nread);
if(result == CURLE_AGAIN)
/* socket buffer drained, return */
return CURLE_OK;
@@ -404,7 +399,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
break;
}
- if(gotbytes <= 0) {
+ if(nread <= 0) {
if(data->set.proxyauth && data->state.authproxy.avail &&
data->state.aptr.proxyuserpwd) {
/* proxy auth was requested and there was proxy auth available,
@@ -432,17 +427,17 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
break;
}
}
- else {
+ else if(ts->chunked_encoding) {
/* chunked-encoded body, so we need to do the chunked dance
properly to know when the end of the body is reached */
- CHUNKcode r;
- CURLcode extra;
- ssize_t tookcareof = 0;
+ size_t consumed = 0;
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
- r = Curl_httpchunk_read(data, &byte, 1, &tookcareof, &extra);
- if(r == CHUNKE_STOP) {
+ result = Curl_httpchunk_read(data, &ts->ch, &byte, 1, &consumed);
+ if(result)
+ return result;
+ if(Curl_httpchunk_is_done(data, &ts->ch)) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE");
ts->keepon = KEEPON_DONE;
@@ -462,22 +457,19 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
ts->headerlines++;
linep = Curl_dyn_ptr(&ts->rcvbuf);
- perline = Curl_dyn_len(&ts->rcvbuf); /* amount of bytes in this line */
+ line_len = Curl_dyn_len(&ts->rcvbuf); /* amount of bytes in this line */
/* output debug if that is requested */
- Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
+ Curl_debug(data, CURLINFO_HEADER_IN, linep, line_len);
- if(!data->set.suppress_connect_headers) {
- /* send the header to the callback */
- int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
- (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
-
- result = Curl_client_write(data, writetype, linep, perline);
- if(result)
- return result;
- }
+ /* send the header to the callback */
+ writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
+ (ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
+ result = Curl_client_write(data, writetype, linep, line_len);
+ if(result)
+ return result;
- result = Curl_bump_headersize(data, perline, TRUE);
+ result = Curl_bump_headersize(data, line_len, TRUE);
if(result)
return result;
@@ -500,29 +492,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
" bytes of response-body", ts->cl);
}
else if(ts->chunked_encoding) {
- CHUNKcode r;
- CURLcode extra;
-
infof(data, "Ignore chunked response-body");
-
- /* 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(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(data, linep + 1, 1, &gotbytes,
- &extra);
- if(r == CHUNKE_STOP) {
- /* we're done reading chunks! */
- infof(data, "chunk reading DONE");
- ts->keepon = KEEPON_DONE;
- }
}
else {
/* without content-length or chunked encoding, we
@@ -755,7 +725,7 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
}
if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent")) &&
- data->set.str[STRING_USERAGENT]) {
+ data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) {
struct dynbuf ua;
Curl_dyn_init(&ua, DYN_HTTP_REQUEST);
result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n",
@@ -915,7 +885,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
if(result)
goto out;
h1_tunnel_go_state(cf, ts, H1_TUNNEL_CONNECT, data);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case H1_TUNNEL_CONNECT:
/* see that the request is completely sent */
@@ -924,7 +894,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
if(result || !done)
goto out;
h1_tunnel_go_state(cf, ts, H1_TUNNEL_RECEIVE, data);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case H1_TUNNEL_RECEIVE:
/* read what is there */
@@ -939,7 +909,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
goto out;
/* got it */
h1_tunnel_go_state(cf, ts, H1_TUNNEL_RESPONSE, data);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case H1_TUNNEL_RESPONSE:
CURL_TRC_CF(data, cf, "CONNECT response");
@@ -1033,36 +1003,42 @@ out:
*done = (result == CURLE_OK) && tunnel_is_established(cf->ctx);
if(*done) {
cf->connected = TRUE;
+ /* Restore `data->req` fields that may habe been touched */
+ data->req.header = TRUE; /* assume header */
+ data->req.bytecount = 0;
+ data->req.ignorebody = FALSE;
+ Curl_client_cleanup(data);
+ Curl_pgrsSetUploadCounter(data, 0);
+ Curl_pgrsSetDownloadCounter(data, 0);
+
tunnel_free(cf, data);
}
return result;
}
-static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
+static void cf_h1_proxy_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct h1_tunnel_state *ts = cf->ctx;
- int fds;
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- if(!fds && cf->next->connected && !cf->connected) {
+ if(!cf->connected) {
/* If we are not connected, but the filter "below" is
* and not waiting on something, we are tunneling. */
- socks[0] = Curl_conn_cf_get_socket(cf, data);
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
if(ts) {
/* when we've sent a CONNECT to a proxy, we should rather either
wait for the socket to become readable to be able to get the
response headers or if we're still sending the request, wait
for write. */
- if(ts->CONNECT.sending == HTTPSEND_REQUEST) {
- return GETSOCK_WRITESOCK(0);
- }
- return GETSOCK_READSOCK(0);
+ if(ts->CONNECT.sending == HTTPSEND_REQUEST)
+ Curl_pollset_set_out_only(data, ps, sock);
+ else
+ Curl_pollset_set_in_only(data, ps, sock);
}
- return GETSOCK_WRITESOCK(0);
+ else
+ Curl_pollset_set_out_only(data, ps, sock);
}
- return fds;
}
static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
@@ -1093,7 +1069,7 @@ struct Curl_cftype Curl_cft_h1_proxy = {
cf_h1_proxy_connect,
cf_h1_proxy_close,
Curl_cf_http_proxy_get_host,
- cf_h1_proxy_get_select_socks,
+ cf_h1_proxy_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
diff --git a/lib/cf-h2-proxy.c b/lib/cf-h2-proxy.c
index dbc895d26..f8f2f3c41 100644
--- a/lib/cf-h2-proxy.c
+++ b/lib/cf-h2-proxy.c
@@ -155,7 +155,7 @@ static void h2_tunnel_go_state(struct Curl_cfilter *cf,
infof(data, "CONNECT phase completed");
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case H2_TUNNEL_FAILED:
if(new_state == H2_TUNNEL_FAILED)
CURL_TRC_CF(data, cf, "[%d] new tunnel state 'failed'", ts->stream_id);
@@ -221,10 +221,10 @@ static void drain_tunnel(struct Curl_cfilter *cf,
bits = CURL_CSELECT_IN;
if(!tunnel->closed && !tunnel->reset && tunnel->upload_blocked_len)
bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
+ if(data->state.select_bits != bits) {
+ CURL_TRC_CF(data, cf, "[%d] DRAIN select_bits=%x",
tunnel->stream_id, bits);
- data->state.dselect_bits = bits;
+ data->state.select_bits = bits;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
@@ -688,12 +688,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
* window and *assume* that we treat this like a WINDOW_UPDATE. Some
* servers send an explicit WINDOW_UPDATE, but not all seem to do that.
* To be safe, we UNHOLD a stream in order not to stall. */
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
+ if(CURL_WANT_SEND(data)) {
drain_tunnel(cf, data, &ctx->tunnel);
- CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
- stream_id);
}
break;
case NGHTTP2_GOAWAY:
@@ -727,12 +723,8 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
}
break;
case NGHTTP2_WINDOW_UPDATE:
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
- CURL_TRC_CF(data, cf, "[%d] unpausing after win update",
- stream_id);
+ if(CURL_WANT_SEND(data)) {
+ drain_tunnel(cf, data, &ctx->tunnel);
}
break;
default:
@@ -909,7 +901,6 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
{
struct dynhds h2_headers;
nghttp2_nv *nva = NULL;
- unsigned int i;
int32_t stream_id = -1;
size_t nheader;
CURLcode result;
@@ -920,22 +911,12 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id,
if(result)
goto out;
- nheader = Curl_dynhds_count(&h2_headers);
- nva = malloc(sizeof(nghttp2_nv) * nheader);
+ nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
if(!nva) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- for(i = 0; i < nheader; ++i) {
- struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
- nva[i].name = (unsigned char *)e->name;
- nva[i].namelen = e->namelen;
- nva[i].value = (unsigned char *)e->value;
- nva[i].valuelen = e->valuelen;
- nva[i].flags = NGHTTP2_NV_FLAG_NONE;
- }
-
if(read_callback) {
nghttp2_data_provider data_prd;
@@ -1052,7 +1033,7 @@ static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
if(result)
goto out;
h2_tunnel_go_state(cf, ts, H2_TUNNEL_CONNECT, data);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case H2_TUNNEL_CONNECT:
/* see that the request is completely sent */
@@ -1071,7 +1052,7 @@ static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
result = CURLE_OK;
goto out;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case H2_TUNNEL_RESPONSE:
DEBUGASSERT(ts->has_final_response);
@@ -1187,25 +1168,31 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
}
-static int cf_h2_proxy_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *sock)
+static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
- int bitmap = GETSOCK_BLANK;
- struct cf_call_data save;
-
- CF_DATA_SAVE(save, cf, data);
- sock[0] = Curl_conn_cf_get_socket(cf, data);
- bitmap |= GETSOCK_READSOCK(0);
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
+ bool want_recv, want_send;
- /* HTTP/2 layer wants to send data) AND there's a window to send data in */
- if(nghttp2_session_want_write(ctx->h2) &&
- nghttp2_session_get_remote_window_size(ctx->h2))
- bitmap |= GETSOCK_WRITESOCK(0);
+ Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
+ if(ctx->h2 && (want_recv || want_send)) {
+ struct cf_call_data save;
+ bool c_exhaust, s_exhaust;
- CF_DATA_RESTORE(cf, save);
- return bitmap;
+ CF_DATA_SAVE(save, cf, data);
+ c_exhaust = !nghttp2_session_get_remote_window_size(ctx->h2);
+ s_exhaust = ctx->tunnel.stream_id >= 0 &&
+ !nghttp2_session_get_stream_remote_window_size(
+ ctx->h2, ctx->tunnel.stream_id);
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ (!c_exhaust && nghttp2_session_want_write(ctx->h2));
+
+ Curl_pollset_set(data, ps, sock, want_recv, want_send);
+ CF_DATA_RESTORE(cf, save);
+ }
}
static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
@@ -1542,7 +1529,7 @@ struct Curl_cftype Curl_cft_h2_proxy = {
cf_h2_proxy_connect,
cf_h2_proxy_close,
Curl_cf_http_proxy_get_host,
- cf_h2_proxy_get_select_socks,
+ cf_h2_proxy_adjust_pollset,
cf_h2_proxy_data_pending,
cf_h2_proxy_send,
cf_h2_proxy_recv,
@@ -1560,7 +1547,7 @@ CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
CURLcode result = CURLE_OUT_OF_MEMORY;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
diff --git a/lib/cf-haproxy.c b/lib/cf-haproxy.c
index 39ac41571..c062887bf 100644
--- a/lib/cf-haproxy.c
+++ b/lib/cf-haproxy.c
@@ -125,7 +125,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
if(result)
goto out;
ctx->state = HAPROXY_SEND;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case HAPROXY_SEND:
len = Curl_dyn_len(&ctx->data_out);
if(len > 0) {
@@ -141,7 +141,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
}
}
ctx->state = HAPROXY_DONE;
- /* FALLTHROUGH */
+ FALLTHROUGH();
default:
Curl_dyn_free(&ctx->data_out);
break;
@@ -171,23 +171,17 @@ static void cf_haproxy_close(struct Curl_cfilter *cf,
cf->next->cft->do_close(cf->next, data);
}
-static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- int fds;
-
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- if(!fds && cf->next->connected && !cf->connected) {
+ if(cf->next->connected && !cf->connected) {
/* If we are not connected, but the filter "below" is
* and not waiting on something, we are sending. */
- socks[0] = Curl_conn_cf_get_socket(cf, data);
- return GETSOCK_WRITESOCK(0);
+ Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data));
}
- return fds;
}
-
struct Curl_cftype Curl_cft_haproxy = {
"HAPROXY",
0,
@@ -196,7 +190,7 @@ struct Curl_cftype Curl_cft_haproxy = {
cf_haproxy_connect,
cf_haproxy_close,
Curl_cf_def_get_host,
- cf_haproxy_get_select_socks,
+ cf_haproxy_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -214,7 +208,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
CURLcode result;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/cf-https-connect.c b/lib/cf-https-connect.c
index be54aec74..b23fa056f 100644
--- a/lib/cf-https-connect.c
+++ b/lib/cf-https-connect.c
@@ -188,9 +188,6 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
#endif
infof(data, "using HTTP/2");
break;
- case CURL_HTTP_VERSION_1_1:
- infof(data, "using HTTP/1.1");
- break;
default:
infof(data, "using HTTP/1.x");
break;
@@ -269,7 +266,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
cf->conn->transport);
ctx->state = CF_HC_CONNECT;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CF_HC_CONNECT:
if(cf_hc_baller_is_active(&ctx->h3_baller)) {
@@ -325,42 +322,25 @@ out:
return result;
}
-static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
+static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
- struct cf_hc_ctx *ctx = cf->ctx;
- size_t i, j, s;
- int brc, rc = GETSOCK_BLANK;
- curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE];
- struct cf_hc_baller *ballers[2];
-
- if(cf->connected)
- return cf->next->cft->get_select_socks(cf->next, data, socks);
-
- ballers[0] = &ctx->h3_baller;
- ballers[1] = &ctx->h21_baller;
- for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
- struct cf_hc_baller *b = ballers[i];
- if(!cf_hc_baller_is_active(b))
- continue;
- brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
- CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc);
- if(!brc)
- continue;
- for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
- if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) {
- socks[s] = bsocks[j];
- if(brc & GETSOCK_WRITESOCK(j))
- rc |= GETSOCK_WRITESOCK(s);
- if(brc & GETSOCK_READSOCK(j))
- rc |= GETSOCK_READSOCK(s);
- s++;
- }
+ if(!cf->connected) {
+ struct cf_hc_ctx *ctx = cf->ctx;
+ struct cf_hc_baller *ballers[2];
+ size_t i;
+
+ ballers[0] = &ctx->h3_baller;
+ ballers[1] = &ctx->h21_baller;
+ for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
+ struct cf_hc_baller *b = ballers[i];
+ if(!cf_hc_baller_is_active(b))
+ continue;
+ Curl_conn_cf_adjust_pollset(b->cf, data, ps);
}
+ CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
- CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc);
- return rc;
}
static bool cf_hc_data_pending(struct Curl_cfilter *cf,
@@ -455,7 +435,7 @@ struct Curl_cftype Curl_cft_http_connect = {
cf_hc_connect,
cf_hc_close,
Curl_cf_def_get_host,
- cf_hc_get_select_socks,
+ cf_hc_adjust_pollset,
cf_hc_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -475,7 +455,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OK;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/cf-socket.c b/lib/cf-socket.c
index ce3f9e943..742902f1b 100644
--- a/lib/cf-socket.c
+++ b/lib/cf-socket.c
@@ -81,7 +81,7 @@
#include "memdebug.h"
-#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(WIN32)
+#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) && defined(_WIN32)
/* It makes support for IPv4-mapped IPv6 addresses.
* Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
* Windows Vista and later: default is on;
@@ -102,11 +102,7 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
#if defined(TCP_NODELAY)
curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
char buffer[STRERROR_LEN];
-#else
- (void) data;
-#endif
if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
sizeof(onoff)) < 0)
@@ -127,6 +123,7 @@ static void nosigpipe(struct Curl_easy *data,
curl_socket_t sockfd)
{
int onoff = 1;
+ (void)data;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0) {
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -140,14 +137,14 @@ static void nosigpipe(struct Curl_easy *data,
#define nosigpipe(x,y) Curl_nop_stmt
#endif
-#if defined(__DragonFly__) || defined(HAVE_WINSOCK2_H)
+#if defined(__DragonFly__) || defined(USE_WINSOCK)
/* DragonFlyBSD and Windows use millisecond units */
#define KEEPALIVE_FACTOR(x) (x *= 1000)
#else
#define KEEPALIVE_FACTOR(x)
#endif
-#if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
+#if defined(USE_WINSOCK) && !defined(SIO_KEEPALIVE_VALS)
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
struct tcp_keepalive {
@@ -166,7 +163,9 @@ tcpkeepalive(struct Curl_easy *data,
/* only set IDLE and INTVL if setting KEEPALIVE is successful */
if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set SO_KEEPALIVE on fd %d", sockfd);
+ infof(data, "Failed to set SO_KEEPALIVE on fd "
+ "%" CURL_FORMAT_SOCKET_T ": errno %d",
+ sockfd, SOCKERRNO);
}
else {
#if defined(SIO_KEEPALIVE_VALS)
@@ -181,8 +180,9 @@ tcpkeepalive(struct Curl_easy *data,
vals.keepaliveinterval = optval;
if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
NULL, 0, &dummy, NULL, NULL) != 0) {
- infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d",
- (int)sockfd, WSAGetLastError());
+ infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd "
+ "%" CURL_FORMAT_SOCKET_T ": errno %d",
+ sockfd, SOCKERRNO);
}
#else
#ifdef TCP_KEEPIDLE
@@ -190,7 +190,9 @@ tcpkeepalive(struct Curl_easy *data,
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPIDLE on fd %d", sockfd);
+ infof(data, "Failed to set TCP_KEEPIDLE on fd "
+ "%" CURL_FORMAT_SOCKET_T ": errno %d",
+ sockfd, SOCKERRNO);
}
#elif defined(TCP_KEEPALIVE)
/* Mac OS X style */
@@ -198,7 +200,9 @@ tcpkeepalive(struct Curl_easy *data,
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPALIVE on fd %d", sockfd);
+ infof(data, "Failed to set TCP_KEEPALIVE on fd "
+ "%" CURL_FORMAT_SOCKET_T ": errno %d",
+ sockfd, SOCKERRNO);
}
#endif
#ifdef TCP_KEEPINTVL
@@ -206,7 +210,9 @@ tcpkeepalive(struct Curl_easy *data,
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
(void *)&optval, sizeof(optval)) < 0) {
- infof(data, "Failed to set TCP_KEEPINTVL on fd %d", sockfd);
+ infof(data, "Failed to set TCP_KEEPINTVL on fd "
+ "%" CURL_FORMAT_SOCKET_T ": errno %d",
+ sockfd, SOCKERRNO);
}
#endif
#endif
@@ -662,7 +668,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
int err = 0;
curl_socklen_t errSize = sizeof(err);
-#ifdef WIN32
+#ifdef _WIN32
/*
* In October 2003 we effectively nullified this function on Windows due to
* problems with it using all CPU in multi-threaded cases.
@@ -786,6 +792,7 @@ struct cf_socket_ctx {
#endif
BIT(got_first_byte); /* if first byte was received */
BIT(accepted); /* socket was accepted, not connected */
+ BIT(sock_connected); /* socket is "connected", e.g. in UDP */
BIT(active);
BIT(buffer_recv);
};
@@ -883,34 +890,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_socket_ctx *ctx = cf->ctx;
if(ctx && CURL_SOCKET_BAD != ctx->sock) {
- if(ctx->active) {
- /* We share our socket at cf->conn->sock[cf->sockindex] when active.
- * If it is no longer there, someone has stolen (and hopefully
- * closed it) and we just forget about it.
- */
- if(ctx->sock == cf->conn->sock[cf->sockindex]) {
- CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ", active)", ctx->sock);
- socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
- cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
- }
- else {
- CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ") no longer at conn->sock[], discarding", ctx->sock);
- /* TODO: we do not want this to happen. Need to check which
- * code is messing with conn->sock[cf->sockindex] */
- }
- ctx->sock = CURL_SOCKET_BAD;
- if(cf->sockindex == FIRSTSOCKET)
- cf->conn->remote_addr = NULL;
- }
- else {
- /* this is our local socket, we did never publish it */
- CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
- ", not active)", ctx->sock);
- socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
- ctx->sock = CURL_SOCKET_BAD;
- }
+ CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
+ ")", ctx->sock);
+ if(ctx->sock == cf->conn->sock[cf->sockindex])
+ cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
+ socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
+ ctx->sock = CURL_SOCKET_BAD;
+ if(ctx->active && cf->sockindex == FIRSTSOCKET)
+ cf->conn->remote_addr = NULL;
Curl_bufq_reset(&ctx->recvbuf);
ctx->active = FALSE;
ctx->buffer_recv = FALSE;
@@ -1006,20 +993,14 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
if(result)
goto out;
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- {
- const char *ipmsg;
#ifdef ENABLE_IPV6
- if(ctx->addr.family == AF_INET6) {
- set_ipv6_v6only(ctx->sock, 0);
- ipmsg = " Trying [%s]:%d...";
- }
- else
-#endif
- ipmsg = " Trying %s:%d...";
- infof(data, ipmsg, ctx->r_ip, ctx->r_port);
+ if(ctx->addr.family == AF_INET6) {
+ set_ipv6_v6only(ctx->sock, 0);
+ infof(data, " Trying [%s]:%d...", ctx->r_ip, ctx->r_port);
}
+ else
#endif
+ infof(data, " Trying %s:%d...", ctx->r_ip, ctx->r_port);
#ifdef ENABLE_IPV6
is_tcp = (ctx->addr.family == AF_INET
@@ -1077,7 +1058,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
/* set socket non-blocking */
(void)curlx_nonblock(ctx->sock, TRUE);
-
+ ctx->sock_connected = (ctx->addr.socktype != SOCK_DGRAM);
out:
if(result) {
if(ctx->sock != CURL_SOCKET_BAD) {
@@ -1169,6 +1150,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
*done = FALSE; /* a very negative world view is best */
if(ctx->sock == CURL_SOCKET_BAD) {
+ int error;
result = cf_socket_open(cf, data);
if(result)
@@ -1181,8 +1163,12 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
/* Connect TCP socket */
rc = do_connect(cf, data, cf->conn->bits.tcp_fastopen);
+ error = SOCKERRNO;
+ set_local_ip(cf, data);
+ CURL_TRC_CF(data, cf, "local address %s port %d...",
+ ctx->l_ip, ctx->l_port);
if(-1 == rc) {
- result = socket_connect_result(data, ctx->r_ip, SOCKERRNO);
+ result = socket_connect_result(data, ctx->r_ip, error);
goto out;
}
}
@@ -1220,13 +1206,14 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
out:
if(result) {
if(ctx->error) {
+ set_local_ip(cf, data);
data->state.os_errno = ctx->error;
SET_SOCKERRNO(ctx->error);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
{
char buffer[STRERROR_LEN];
- infof(data, "connect to %s port %u failed: %s",
- ctx->r_ip, ctx->r_port,
+ infof(data, "connect to %s port %u from %s port %d failed: %s",
+ ctx->r_ip, ctx->r_port, ctx->l_ip, ctx->l_port,
Curl_strerror(ctx->error, buffer, sizeof(buffer)));
}
#endif
@@ -1252,20 +1239,22 @@ static void cf_socket_get_host(struct Curl_cfilter *cf,
*pport = cf->conn->port;
}
-static int cf_socket_get_select_socks(struct Curl_cfilter *cf,
+static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_socket_ctx *ctx = cf->ctx;
- int rc = GETSOCK_BLANK;
- (void)data;
- if(!cf->connected && ctx->sock != CURL_SOCKET_BAD) {
- socks[0] = ctx->sock;
- rc |= GETSOCK_WRITESOCK(0);
+ if(ctx->sock != CURL_SOCKET_BAD) {
+ if(!cf->connected) {
+ Curl_pollset_set_out_only(data, ps, ctx->sock);
+ CURL_TRC_CF(data, cf, "adjust_pollset(!connected) -> %d socks", ps->num);
+ }
+ else if(!ctx->active) {
+ Curl_pollset_add_in(data, ps, ctx->sock);
+ CURL_TRC_CF(data, cf, "adjust_pollset(!active) -> %d socks", ps->num);
+ }
}
-
- return rc;
}
static bool cf_socket_data_pending(struct Curl_cfilter *cf,
@@ -1447,36 +1436,11 @@ out:
static void conn_set_primary_ip(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
-#ifdef HAVE_GETPEERNAME
struct cf_socket_ctx *ctx = cf->ctx;
- if(!(data->conn->handler->protocol & CURLPROTO_TFTP)) {
- /* TFTP does not connect the endpoint: getpeername() failed with errno
- 107: Transport endpoint is not connected */
-
- char buffer[STRERROR_LEN];
- struct Curl_sockaddr_storage ssrem;
- curl_socklen_t plen;
- int port;
- plen = sizeof(ssrem);
- memset(&ssrem, 0, plen);
- if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
- int error = SOCKERRNO;
- failf(data, "getpeername() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
- if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
- cf->conn->primary_ip, &port)) {
- failf(data, "ssrem inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
- }
- }
-#else
- cf->conn->primary_ip[0] = 0;
(void)data;
-#endif
+ DEBUGASSERT(sizeof(ctx->r_ip) == sizeof(cf->conn->primary_ip));
+ memcpy(cf->conn->primary_ip, ctx->r_ip, sizeof(cf->conn->primary_ip));
}
static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -1518,6 +1482,9 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
case CF_CTRL_DATA_SETUP:
Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
break;
+ case CF_CTRL_FORGET_SOCKET:
+ ctx->sock = CURL_SOCKET_BAD;
+ break;
}
return CURLE_OK;
}
@@ -1589,7 +1556,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
*when = ctx->first_byte_at;
break;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
default:
*when = ctx->connected_at;
break;
@@ -1612,7 +1579,7 @@ struct Curl_cftype Curl_cft_tcp = {
cf_tcp_connect,
cf_socket_close,
cf_socket_get_host,
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1635,7 +1602,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_TCP);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1663,10 +1630,17 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
/* QUIC needs a connected socket, nonblocking */
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
+#if defined(__APPLE__) && defined(USE_OPENSSL_QUIC)
+ (void)rc;
+ /* On macOS OpenSSL QUIC fails on connected sockets.
+ * see: <https://github.com/openssl/openssl/issues/23251> */
+#else
rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
if(-1 == rc) {
return socket_connect_result(data, ctx->r_ip, SOCKERRNO);
}
+ ctx->sock_connected = TRUE;
+#endif
set_local_ip(cf, data);
CURL_TRC_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
" connected: [%s:%d] -> [%s:%d]",
@@ -1742,7 +1716,7 @@ struct Curl_cftype Curl_cft_udp = {
cf_udp_connect,
cf_socket_close,
cf_socket_get_host,
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1765,7 +1739,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1793,7 +1767,7 @@ struct Curl_cftype Curl_cft_unix = {
cf_tcp_connect,
cf_socket_close,
cf_socket_get_host,
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1816,7 +1790,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
DEBUGASSERT(transport == TRNSPRT_UNIX);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1857,7 +1831,7 @@ struct Curl_cftype Curl_cft_tcp_accept = {
cf_tcp_accept_connect,
cf_socket_close,
cf_socket_get_host, /* TODO: not accurate */
- cf_socket_get_select_socks,
+ cf_socket_adjust_pollset,
cf_socket_data_pending,
cf_socket_send,
cf_socket_recv,
@@ -1879,7 +1853,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
Curl_conn_cf_discard_all(data, conn, sockindex);
DEBUGASSERT(conn->sock[sockindex] == CURL_SOCKET_BAD);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/cf-socket.h b/lib/cf-socket.h
index 1d40df737..87e0f30a2 100644
--- a/lib/cf-socket.h
+++ b/lib/cf-socket.h
@@ -34,23 +34,6 @@ struct Curl_easy;
struct connectdata;
struct Curl_sockaddr_ex;
-#ifndef SIZEOF_CURL_SOCKET_T
-/* configure and cmake check and set the define */
-# ifdef _WIN64
-# define SIZEOF_CURL_SOCKET_T 8
-# else
-/* default guess */
-# define SIZEOF_CURL_SOCKET_T 4
-# endif
-#endif
-
-#if SIZEOF_CURL_SOCKET_T < 8
-# define CURL_FORMAT_SOCKET_T "d"
-#else
-# define CURL_FORMAT_SOCKET_T "qd"
-#endif
-
-
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
diff --git a/lib/cfilters.c b/lib/cfilters.c
index f74eb4003..823e90c3f 100644
--- a/lib/cfilters.c
+++ b/lib/cfilters.c
@@ -33,6 +33,7 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "progress.h"
+#include "select.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
@@ -70,12 +71,14 @@ void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
}
}
-int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
+void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
- return cf->next?
- cf->next->cft->get_select_socks(cf->next, data, socks) : 0;
+ /* NOP */
+ (void)cf;
+ (void)data;
+ (void)ps;
}
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
@@ -212,7 +215,7 @@ CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(cft);
- cf = calloc(sizeof(*cf), 1);
+ cf = calloc(1, sizeof(*cf));
if(!cf)
goto out;
@@ -303,15 +306,6 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
cf->cft->do_close(cf, data);
}
-int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
-{
- if(cf)
- return cf->cft->get_select_socks(cf, data, socks);
- return 0;
-}
-
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
@@ -433,22 +427,31 @@ bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
return FALSE;
}
-int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
- curl_socket_t *socks)
+void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct Curl_cfilter *cf;
+ /* Get the lowest not-connected filter, if there are any */
+ while(cf && !cf->connected && cf->next && !cf->next->connected)
+ cf = cf->next;
+ /* From there on, give all filters a chance to adjust the pollset.
+ * Lower filters are called later, so they may override */
+ while(cf) {
+ cf->cft->adjust_pollset(cf, data, ps);
+ cf = cf->next;
+ }
+}
+
+void Curl_conn_adjust_pollset(struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ int i;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
- cf = data->conn->cfilter[sockindex];
-
- /* if the next one is not yet connected, that's the one we want */
- while(cf && cf->next && !cf->next->connected)
- cf = cf->next;
- if(cf) {
- return cf->cft->get_select_socks(cf, data, socks);
+ for(i = 0; i < 2; ++i) {
+ Curl_conn_cf_adjust_pollset(data->conn->cfilter[i], data, ps);
}
- return GETSOCK_BLANK;
}
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
@@ -524,6 +527,18 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
}
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
+{
+ if(data->conn) {
+ struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
+ if(cf)
+ (void)Curl_conn_cf_cntrl(cf, data, TRUE,
+ CF_CTRL_FORGET_SOCKET, 0, NULL);
+ fake_sclose(data->conn->sock[sockindex]);
+ data->conn->sock[sockindex] = CURL_SOCKET_BAD;
+ }
+}
+
static CURLcode cf_cntrl_all(struct connectdata *conn,
struct Curl_easy *data,
bool ignore_result,
@@ -646,3 +661,128 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
&n, NULL) : CURLE_UNKNOWN_OPTION;
return (result || n <= 0)? 1 : (size_t)n;
}
+
+
+void Curl_pollset_reset(struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ size_t i;
+ (void)data;
+ memset(ps, 0, sizeof(*ps));
+ for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
+ ps->sockets[i] = CURL_SOCKET_BAD;
+}
+
+/**
+ *
+ */
+void Curl_pollset_change(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ int add_flags, int remove_flags)
+{
+ unsigned int i;
+
+ (void)data;
+ DEBUGASSERT(VALID_SOCK(sock));
+ if(!VALID_SOCK(sock))
+ return;
+
+ DEBUGASSERT(add_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+ DEBUGASSERT(remove_flags <= (CURL_POLL_IN|CURL_POLL_OUT));
+ DEBUGASSERT((add_flags&remove_flags) == 0); /* no overlap */
+ for(i = 0; i < ps->num; ++i) {
+ if(ps->sockets[i] == sock) {
+ ps->actions[i] &= (unsigned char)(~remove_flags);
+ ps->actions[i] |= (unsigned char)add_flags;
+ /* all gone? remove socket */
+ if(!ps->actions[i]) {
+ if((i + 1) < ps->num) {
+ memmove(&ps->sockets[i], &ps->sockets[i + 1],
+ (ps->num - (i + 1)) * sizeof(ps->sockets[0]));
+ memmove(&ps->actions[i], &ps->actions[i + 1],
+ (ps->num - (i + 1)) * sizeof(ps->actions[0]));
+ }
+ --ps->num;
+ }
+ return;
+ }
+ }
+ /* not present */
+ if(add_flags) {
+ /* Having more SOCKETS per easy handle than what is defined
+ * is a programming error. This indicates that we need
+ * to raise this limit, making easy_pollset larger.
+ * Since we use this in tight loops, we do not want to make
+ * the pollset dynamic unnecessarily.
+ * The current maximum in practise is HTTP/3 eyeballing where
+ * we have up to 4 sockets involved in connection setup.
+ */
+ DEBUGASSERT(i < MAX_SOCKSPEREASYHANDLE);
+ if(i < MAX_SOCKSPEREASYHANDLE) {
+ ps->sockets[i] = sock;
+ ps->actions[i] = (unsigned char)add_flags;
+ ps->num = i + 1;
+ }
+ }
+}
+
+void Curl_pollset_set(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool do_in, bool do_out)
+{
+ Curl_pollset_change(data, ps, sock,
+ (do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0),
+ (!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0));
+}
+
+static void ps_add(struct Curl_easy *data, struct easy_pollset *ps,
+ int bitmap, curl_socket_t *socks)
+{
+ if(bitmap) {
+ int i;
+ for(i = 0; i < MAX_SOCKSPEREASYHANDLE; ++i) {
+ if(!(bitmap & GETSOCK_MASK_RW(i)) || !VALID_SOCK((socks[i]))) {
+ break;
+ }
+ if(bitmap & GETSOCK_READSOCK(i)) {
+ if(bitmap & GETSOCK_WRITESOCK(i))
+ Curl_pollset_add_inout(data, ps, socks[i]);
+ else
+ /* is READ, since we checked MASK_RW above */
+ Curl_pollset_add_in(data, ps, socks[i]);
+ }
+ else
+ Curl_pollset_add_out(data, ps, socks[i]);
+ }
+ }
+}
+
+void Curl_pollset_add_socks(struct Curl_easy *data,
+ struct easy_pollset *ps,
+ int (*get_socks_cb)(struct Curl_easy *data,
+ curl_socket_t *socks))
+{
+ curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
+ int bitmap;
+
+ bitmap = get_socks_cb(data, socks);
+ ps_add(data, ps, bitmap, socks);
+}
+
+void Curl_pollset_check(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool *pwant_read, bool *pwant_write)
+{
+ unsigned int i;
+
+ (void)data;
+ DEBUGASSERT(VALID_SOCK(sock));
+ for(i = 0; i < ps->num; ++i) {
+ if(ps->sockets[i] == sock) {
+ *pwant_read = !!(ps->actions[i] & CURL_POLL_IN);
+ *pwant_write = !!(ps->actions[i] & CURL_POLL_OUT);
+ return;
+ }
+ }
+ *pwant_read = *pwant_write = FALSE;
+}
diff --git a/lib/cfilters.h b/lib/cfilters.h
index 2c65264d9..f83842920 100644
--- a/lib/cfilters.h
+++ b/lib/cfilters.h
@@ -60,14 +60,34 @@ typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
const char **pdisplay_host,
int *pport);
-/* Filters may return sockets and fdset flags they are waiting for.
- * The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
- * @return read/write fdset for index in socks
- * or GETSOCK_BLANK when nothing to wait on
+struct easy_pollset;
+
+/* Passing in an easy_pollset for monitoring of sockets, let
+ * filters add or remove sockets actions (CURL_POLL_OUT, CURL_POLL_IN).
+ * This may add a socket or, in case no actions remain, remove
+ * a socket from the set.
+ *
+ * Filter implementations need to call filters "below" *after* they have
+ * made their adjustments. This allows lower filters to override "upper"
+ * actions. If a "lower" filter is unable to write, it needs to be able
+ * to disallow POLL_OUT.
+ *
+ * A filter without own restrictions/preferences should not modify
+ * the pollset. Filters, whose filter "below" is not connected, should
+ * also do no adjustments.
+ *
+ * Examples: a TLS handshake, while ongoing, might remove POLL_IN
+ * when it needs to write, or vice versa. A HTTP/2 filter might remove
+ * POLL_OUT when a stream window is exhausted and a WINDOW_UPDATE needs
+ * to be received first and add instead POLL_IN.
+ *
+ * @param cf the filter to ask
+ * @param data the easy handle the pollset is about
+ * @param ps the pollset (inout) for the easy handle
*/
-typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks);
+typedef void Curl_cft_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps);
typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
@@ -110,6 +130,7 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
#define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */
/* update conn info at connection and data */
#define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */
+#define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */
/**
* Handle event/control for the filter.
@@ -171,7 +192,7 @@ struct Curl_cftype {
Curl_cft_connect *do_connect; /* establish connection */
Curl_cft_close *do_close; /* close conn */
Curl_cft_get_host *get_host; /* host filter talks to */
- Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
+ Curl_cft_adjust_pollset *adjust_pollset; /* adjust transfer poll set */
Curl_cft_data_pending *has_data_pending;/* conn has data pending */
Curl_cft_send *do_send; /* send data */
Curl_cft_recv *do_recv; /* receive data */
@@ -200,9 +221,9 @@ void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport);
-int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks);
+void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps);
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -279,9 +300,6 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
-int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks);
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -364,11 +382,22 @@ bool Curl_conn_data_pending(struct Curl_easy *data,
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
/**
- * Get any select fd flags and the socket filters at chain `sockindex`
- * at connection `conn` might be waiting for.
+ * Tell filters to forget about the socket at sockindex.
*/
-int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
- curl_socket_t *socks);
+void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex);
+
+/**
+ * Adjust the pollset for the filter chain startgin at `cf`.
+ */
+void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps);
+
+/**
+ * Adjust pollset from filters installed at transfer's connection.
+ */
+void Curl_conn_adjust_pollset(struct Curl_easy *data,
+ struct easy_pollset *ps);
/**
* Receive data through the filter chain at `sockindex` for connection
@@ -468,6 +497,49 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
int sockindex);
+void Curl_pollset_reset(struct Curl_easy *data,
+ struct easy_pollset *ps);
+
+/* Change the poll flags (CURL_POLL_IN/CURL_POLL_OUT) to the poll set for
+ * socket `sock`. If the socket is not already part of the poll set, it
+ * will be added.
+ * If the socket is present and all poll flags are cleared, it will be removed.
+ */
+void Curl_pollset_change(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ int add_flags, int remove_flags);
+
+void Curl_pollset_set(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool do_in, bool do_out);
+
+#define Curl_pollset_add_in(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0)
+#define Curl_pollset_add_out(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0)
+#define Curl_pollset_add_inout(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), \
+ CURL_POLL_IN|CURL_POLL_OUT, 0)
+#define Curl_pollset_set_in_only(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), \
+ CURL_POLL_IN, CURL_POLL_OUT)
+#define Curl_pollset_set_out_only(data, ps, sock) \
+ Curl_pollset_change((data), (ps), (sock), \
+ CURL_POLL_OUT, CURL_POLL_IN)
+
+void Curl_pollset_add_socks(struct Curl_easy *data,
+ struct easy_pollset *ps,
+ int (*get_socks_cb)(struct Curl_easy *data,
+ curl_socket_t *socks));
+
+/**
+ * Check if the pollset, as is, wants to read and/or write regarding
+ * the given socket.
+ */
+void Curl_pollset_check(struct Curl_easy *data,
+ struct easy_pollset *ps, curl_socket_t sock,
+ bool *pwant_read, bool *pwant_write);
+
/**
* Types and macros used to keep the current easy handle in filter calls,
* allowing for nested invocations. See #10336.
diff --git a/lib/config-amigaos.h b/lib/config-amigaos.h
index 8f4d3e6c3..d168b446b 100644
--- a/lib/config-amigaos.h
+++ b/lib/config-amigaos.h
@@ -32,7 +32,6 @@
#define HAVE_ARPA_INET_H 1
#define HAVE_CLOSESOCKET_CAMEL 1
-#define HAVE_INTTYPES_H 1
#define HAVE_IOCTLSOCKET_CAMEL 1
#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1
#define HAVE_LONGLONG 1
diff --git a/lib/config-dos.h b/lib/config-dos.h
index 550c410a1..c6fbba796 100644
--- a/lib/config-dos.h
+++ b/lib/config-dos.h
@@ -122,7 +122,6 @@
#define HAVE_SIGSETJMP 1
#define HAVE_SYS_TIME_H 1
#define HAVE_TERMIOS_H 1
- #define HAVE_VARIADIC_MACROS_GCC 1
#elif defined(__HIGHC__)
#define HAVE_SYS_TIME_H 1
diff --git a/lib/config-os400.h b/lib/config-os400.h
index e9a628863..32852bb37 100644
--- a/lib/config-os400.h
+++ b/lib/config-os400.h
@@ -104,9 +104,6 @@
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
-/* Define if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H
-
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
@@ -119,12 +116,6 @@
/* Define if you have the GNU gssapi libraries */
#undef HAVE_GSSGNU
-/* Define if you have the Heimdal gssapi libraries */
-#define HAVE_GSSHEIMDAL
-
-/* Define if you have the MIT gssapi libraries */
-#undef HAVE_GSSMIT
-
/* Define if you need the malloc.h header file even with stdlib.h */
/* #define NEED_MALLOC_H 1 */
@@ -152,9 +143,6 @@
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
-/* Define if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
/* The following define is needed on OS400 to enable strcmpi(), stricmp() and
strdup(). */
diff --git a/lib/config-plan9.h b/lib/config-plan9.h
index fa4be8e6d..aa9623f92 100644
--- a/lib/config-plan9.h
+++ b/lib/config-plan9.h
@@ -91,7 +91,6 @@
#define HAVE_GMTIME_R 1
#define HAVE_INET_NTOP 1
#define HAVE_INET_PTON 1
-#define HAVE_INTTYPES_H 1
#define HAVE_LIBGEN_H 1
#define HAVE_LIBZ 1
#define HAVE_LOCALE_H 1
@@ -117,7 +116,6 @@
#define HAVE_SOCKET 1
#define HAVE_SSL_GET_SHUTDOWN 1
#define HAVE_STDBOOL_H 1
-#define HAVE_STDINT_H 1
#define HAVE_STRCASECMP 1
#define HAVE_STRDUP 1
#define HAVE_STRTOK_R 1
diff --git a/lib/config-riscos.h b/lib/config-riscos.h
index 52c279f5b..f3a8e6832 100644
--- a/lib/config-riscos.h
+++ b/lib/config-riscos.h
@@ -108,9 +108,6 @@
/* Define if you have the `timeval' struct. */
#define HAVE_STRUCT_TIMEVAL
-/* Define if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H
-
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
@@ -144,9 +141,6 @@
/* Define if you have the `socket' function. */
#define HAVE_SOCKET
-/* Define if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
/* Define if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
diff --git a/lib/config-win32.h b/lib/config-win32.h
index e55ef2fd2..89ed1a0f1 100644
--- a/lib/config-win32.h
+++ b/lib/config-win32.h
@@ -38,17 +38,6 @@
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
-/* Define to 1 if you have the <inttypes.h> header file. */
-#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
-#define HAVE_INTTYPES_H 1
-#endif
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#if (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(__MINGW32__) || \
- (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0582)) || defined(__POCC__)
-#define HAVE_STDINT_H 1
-#endif
-
/* Define if you have the <io.h> header file. */
#define HAVE_IO_H 1
@@ -56,9 +45,7 @@
#define HAVE_LOCALE_H 1
/* Define if you need <malloc.h> header even with <stdlib.h> header file. */
-#if !defined(__SALFORDC__) && !defined(__POCC__)
#define NEED_MALLOC_H 1
-#endif
/* Define if you have the <netdb.h> header file. */
/* #define HAVE_NETDB_H 1 */
@@ -72,7 +59,9 @@
#endif
/* Define if you have the <sys/param.h> header file. */
-/* #define HAVE_SYS_PARAM_H 1 */
+#if defined(__MINGW32__)
+#define HAVE_SYS_PARAM_H 1
+#endif
/* Define if you have the <sys/select.h> header file. */
/* #define HAVE_SYS_SELECT_H 1 */
@@ -87,15 +76,15 @@
#define HAVE_SYS_STAT_H 1
/* Define if you have the <sys/time.h> header file. */
-/* #define HAVE_SYS_TIME_H 1 */
+#if defined(__MINGW32__)
+#define HAVE_SYS_TIME_H 1
+#endif
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define if you have the <sys/utime.h> header file. */
-#ifndef __BORLANDC__
#define HAVE_SYS_UTIME_H 1
-#endif
/* Define if you have the <termio.h> header file. */
/* #define HAVE_TERMIO_H 1 */
@@ -104,23 +93,10 @@
/* #define HAVE_TERMIOS_H 1 */
/* Define if you have the <unistd.h> header file. */
-#if defined(__MINGW32__) || defined(__LCC__) || defined(__POCC__)
+#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#endif
-/* Define if you have the <windows.h> header file. */
-#define HAVE_WINDOWS_H 1
-
-/* Define if you have the <winsock2.h> header file. */
-#ifndef __SALFORDC__
-#define HAVE_WINSOCK2_H 1
-#endif
-
-/* Define if you have the <ws2tcpip.h> header file. */
-#ifndef __SALFORDC__
-#define HAVE_WS2TCPIP_H 1
-#endif
-
/* Define to 1 if you have the <libgen.h> header file. */
#if defined(__MINGW32__)
#define HAVE_LIBGEN_H 1
@@ -160,7 +136,9 @@
#define HAVE_GETHOSTNAME 1
/* Define if you have the gettimeofday function. */
-/* #define HAVE_GETTIMEOFDAY 1 */
+#if defined(__MINGW32__)
+#define HAVE_GETTIMEOFDAY 1
+#endif
/* Define if you have the ioctlsocket function. */
#define HAVE_IOCTLSOCKET 1
@@ -192,15 +170,12 @@
#define HAVE_STRICMP 1
/* Define if you have the strtoll function. */
-#if defined(__MINGW32__) || defined(__POCC__) || \
- (defined(_MSC_VER) && (_MSC_VER >= 1800))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__)
#define HAVE_STRTOLL 1
#endif
/* Define if you have the utime function. */
-#ifndef __BORLANDC__
#define HAVE_UTIME 1
-#endif
/* Define if you have the recv function. */
#define HAVE_RECV 1
@@ -242,7 +217,7 @@
#define SEND_TYPE_RETV int
/* Define to 1 if you have the snprintf function. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1900)
+#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || defined(__MINGW32__)
#define HAVE_SNPRINTF 1
#endif
@@ -275,7 +250,7 @@
/* Define if ssize_t is not an available 'typedefed' type. */
#ifndef _SSIZE_T_DEFINED
-# if defined(__POCC__) || defined(__MINGW32__)
+# if defined(__MINGW32__)
# elif defined(_WIN64)
# define _SSIZE_T_DEFINED
# define ssize_t __int64
@@ -309,56 +284,6 @@
#define SIZEOF_CURL_OFF_T 8
/* ---------------------------------------------------------------- */
-/* BSD-style lwIP TCP/IP stack SPECIFIC */
-/* ---------------------------------------------------------------- */
-
-/* Define to use BSD-style lwIP TCP/IP stack. */
-/* #define USE_LWIPSOCK 1 */
-
-#ifdef USE_LWIPSOCK
-# undef USE_WINSOCK
-# undef HAVE_WINSOCK2_H
-# undef HAVE_WS2TCPIP_H
-# undef HAVE_GETHOSTNAME
-# undef LWIP_POSIX_SOCKETS_IO_NAMES
-# undef RECV_TYPE_ARG1
-# undef RECV_TYPE_ARG3
-# undef SEND_TYPE_ARG1
-# undef SEND_TYPE_ARG3
-# define HAVE_FREEADDRINFO
-# define HAVE_GETADDRINFO
-# define HAVE_GETHOSTBYNAME_R
-# define HAVE_GETHOSTBYNAME_R_6
-# define LWIP_POSIX_SOCKETS_IO_NAMES 0
-# define RECV_TYPE_ARG1 int
-# define RECV_TYPE_ARG3 size_t
-# define SEND_TYPE_ARG1 int
-# define SEND_TYPE_ARG3 size_t
-#endif
-
-/* ---------------------------------------------------------------- */
-/* Watt-32 tcp/ip SPECIFIC */
-/* ---------------------------------------------------------------- */
-
-#ifdef USE_WATT32
- #include <tcp.h>
- #undef byte
- #undef word
- #undef USE_WINSOCK
- #undef HAVE_WINSOCK2_H
- #undef HAVE_WS2TCPIP_H
- #define HAVE_GETADDRINFO
- #define HAVE_SYS_IOCTL_H
- #define HAVE_SYS_SOCKET_H
- #define HAVE_NETINET_IN_H
- #define HAVE_NETDB_H
- #define HAVE_ARPA_INET_H
- #define HAVE_FREEADDRINFO
- #define SOCKET int
-#endif
-
-
-/* ---------------------------------------------------------------- */
/* COMPILER SPECIFIC */
/* ---------------------------------------------------------------- */
@@ -371,15 +296,8 @@
/* Windows should not have HAVE_GMTIME_R defined */
/* #undef HAVE_GMTIME_R */
-/* Define if the compiler supports C99 variadic macro style. */
-#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-#define HAVE_VARIADIC_MACROS_C99 1
-#endif
-
/* Define if the compiler supports the 'long long' data type. */
-#if defined(__MINGW32__) || \
- (defined(_MSC_VER) && (_MSC_VER >= 1310)) || \
- (defined(__BORLANDC__) && (__BORLANDC__ >= 0x561))
+#if (defined(_MSC_VER) && (_MSC_VER >= 1310)) || defined(__MINGW32__)
#define HAVE_LONGLONG 1
#endif
@@ -461,53 +379,17 @@ Vista
# endif
#endif
-/* When no build target is specified Pelles C 5.00 and later default build
- target is Windows Vista. We override default target to be Windows 2000. */
-#if defined(__POCC__) && (__POCC__ >= 500)
-# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0500
-# endif
-# ifndef WINVER
-# define WINVER 0x0500
-# endif
-#endif
-
-/* Availability of freeaddrinfo, getaddrinfo, and if_nametoindex
- functions is quite convoluted, compiler dependent and even build target
- dependent. */
-#if defined(HAVE_WS2TCPIP_H)
-# if defined(__POCC__)
-# define HAVE_FREEADDRINFO 1
-# define HAVE_GETADDRINFO 1
-# define HAVE_GETADDRINFO_THREADSAFE 1
-# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)
-# define HAVE_FREEADDRINFO 1
-# define HAVE_GETADDRINFO 1
-# define HAVE_GETADDRINFO_THREADSAFE 1
-# elif defined(_MSC_VER) && (_MSC_VER >= 1200)
-# define HAVE_FREEADDRINFO 1
-# define HAVE_GETADDRINFO 1
-# define HAVE_GETADDRINFO_THREADSAFE 1
-# endif
-#endif
-
-#if defined(__POCC__)
-# ifndef _MSC_VER
-# error Microsoft extensions /Ze compiler option is required
-# endif
-# ifndef __POCC__OLDNAMES
-# error Compatibility names /Go compiler option is required
-# endif
-#endif
+/* Windows XP is required for freeaddrinfo, getaddrinfo */
+#define HAVE_FREEADDRINFO 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETADDRINFO_THREADSAFE 1
/* ---------------------------------------------------------------- */
/* STRUCT RELATED */
/* ---------------------------------------------------------------- */
/* Define if you have struct sockaddr_storage. */
-#if !defined(__SALFORDC__) && !defined(__BORLANDC__)
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
-#endif
/* Define if you have struct timeval. */
#define HAVE_STRUCT_TIMEVAL 1
@@ -531,10 +413,6 @@ Vista
# define USE_WIN32_LARGE_FILES
#endif
-#if defined(__POCC__)
-# undef USE_WIN32_LARGE_FILES
-#endif
-
#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES)
# define USE_WIN32_SMALL_FILES
#endif
@@ -596,10 +474,6 @@ Vista
#define USE_WIN32_LDAP 1
#endif
-#if defined(__POCC__) && defined(USE_WIN32_LDAP)
-# define CURL_DISABLE_LDAP 1
-#endif
-
/* Define to use the Windows crypto library. */
#if !defined(CURL_WINDOWS_APP)
#define USE_WIN32_CRYPTO
@@ -635,7 +509,7 @@ Vista
/* If you want to build curl with the built-in manual */
#define USE_MANUAL 1
-#if defined(__POCC__) || defined(USE_IPV6)
+#if defined(USE_IPV6)
# define ENABLE_IPV6 1
#endif
diff --git a/lib/config-win32ce.h b/lib/config-win32ce.h
index cc3833d01..ae3ca290c 100644
--- a/lib/config-win32ce.h
+++ b/lib/config-win32ce.h
@@ -81,19 +81,10 @@
/* #define HAVE_TERMIOS_H 1 */
/* Define if you have the <unistd.h> header file. */
-#if defined(__MINGW32__) || defined(__LCC__)
+#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#endif
-/* Define if you have the <windows.h> header file. */
-#define HAVE_WINDOWS_H 1
-
-/* Define if you have the <winsock2.h> header file. */
-#define HAVE_WINSOCK2_H 1
-
-/* Define if you have the <ws2tcpip.h> header file. */
-#define HAVE_WS2TCPIP_H 1
-
/* ---------------------------------------------------------------- */
/* OTHER HEADER INFO */
/* ---------------------------------------------------------------- */
@@ -190,8 +181,7 @@
#define in_addr_t unsigned long
/* Define ssize_t if it is not an available 'typedefed' type */
-#if defined(__POCC__)
-#elif defined(_WIN64)
+#if defined(_WIN64)
#define ssize_t __int64
#else
#define ssize_t int
diff --git a/lib/conncache.c b/lib/conncache.c
index 93d87686c..66f18ecb8 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -107,7 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size)
connc->closure_handle = curl_easy_init();
if(!connc->closure_handle)
return 1; /* bad */
- connc->closure_handle->internal = true;
+ connc->closure_handle->state.internal = true;
Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry);
@@ -243,7 +243,7 @@ CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
conn->connection_id = connc->next_connection_id++;
connc->num_conn++;
- DEBUGF(infof(data, "Added connection %ld. "
+ DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". "
"The cache now contains %zu members",
conn->connection_id, connc->num_conn));
@@ -379,21 +379,26 @@ conncache_find_first_connection(struct conncache *connc)
bool Curl_conncache_return_conn(struct Curl_easy *data,
struct connectdata *conn)
{
- /* data->multi->maxconnects can be negative, deal with it. */
- size_t maxconnects =
- (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
- data->multi->maxconnects;
+ unsigned int maxconnects = !data->multi->maxconnects ?
+ data->multi->num_easy * 4: data->multi->maxconnects;
struct connectdata *conn_candidate = NULL;
conn->lastused = Curl_now(); /* it was used up until now */
- if(maxconnects > 0 &&
- Curl_conncache_size(data) > maxconnects) {
+ if(maxconnects && Curl_conncache_size(data) > maxconnects) {
infof(data, "Connection cache is full, closing the oldest one");
conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate) {
- /* the winner gets the honour of being disconnected */
- Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
+ /* Use the closure handle for this disconnect so that anything that
+ happens during the disconnect is not stored and associated with the
+ 'data' handle which already just finished a transfer and it is
+ important that details from this (unrelated) disconnect does not
+ taint meta-data in the data handle. */
+ struct conncache *connc = data->state.conn_cache;
+ connc->closure_handle->state.buffer = data->state.buffer;
+ connc->closure_handle->set.buffer_size = data->set.buffer_size;
+ Curl_disconnect(connc->closure_handle, conn_candidate,
+ /* dead_connection */ FALSE);
}
}
diff --git a/lib/connect.c b/lib/connect.c
index c7ba3e20e..45743e98b 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -84,31 +84,26 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
/*
* Curl_timeleft() returns the amount of milliseconds left allowed for the
* transfer/connection. If the value is 0, there's no timeout (ie there's
* infinite time left). If the value is negative, the timeout time has already
* elapsed.
- *
- * If 'nowp' is non-NULL, it points to the current time.
- * 'duringconnect' is FALSE if not during a connect, as then of course the
- * connect timeout is not taken into account!
- *
+ * @param data the transfer to check on
+ * @param nowp timestamp to use for calculdation, NULL to use Curl_now()
+ * @param duringconnect TRUE iff connect timeout is also taken into account.
* @unittest: 1303
*/
-
-#define TIMEOUT_CONNECT 1
-#define TIMEOUT_MAXTIME 2
-
timediff_t Curl_timeleft(struct Curl_easy *data,
struct curltime *nowp,
bool duringconnect)
{
- unsigned int timeout_set = 0;
- timediff_t connect_timeout_ms = 0;
- timediff_t maxtime_timeout_ms = 0;
- timediff_t timeout_ms = 0;
+ timediff_t timeleft_ms = 0;
+ timediff_t ctimeleft_ms = 0;
struct curltime now;
/* The duration of a connect and the total transfer are calculated from two
@@ -116,43 +111,35 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
before the connect timeout expires and we must acknowledge whichever
timeout that is reached first. The total timeout is set per entire
operation, while the connect timeout is set per connect. */
-
- if(data->set.timeout > 0) {
- timeout_set = TIMEOUT_MAXTIME;
- maxtime_timeout_ms = data->set.timeout;
- }
- if(duringconnect) {
- timeout_set |= TIMEOUT_CONNECT;
- connect_timeout_ms = (data->set.connecttimeout > 0) ?
- data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
- }
- if(!timeout_set)
- /* no timeout */
- return 0;
+ if(data->set.timeout <= 0 && !duringconnect)
+ return 0; /* no timeout in place or checked, return "no limit" */
if(!nowp) {
now = Curl_now();
nowp = &now;
}
- if(timeout_set & TIMEOUT_MAXTIME) {
- maxtime_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startop);
- timeout_ms = maxtime_timeout_ms;
+ if(data->set.timeout > 0) {
+ timeleft_ms = data->set.timeout -
+ Curl_timediff(*nowp, data->progress.t_startop);
+ if(!timeleft_ms)
+ timeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
+ if(!duringconnect)
+ return timeleft_ms; /* no connect check, this is it */
}
- if(timeout_set & TIMEOUT_CONNECT) {
- connect_timeout_ms -= Curl_timediff(*nowp, data->progress.t_startsingle);
-
- if(!(timeout_set & TIMEOUT_MAXTIME) ||
- (connect_timeout_ms < maxtime_timeout_ms))
- timeout_ms = connect_timeout_ms;
+ if(duringconnect) {
+ timediff_t ctimeout_ms = (data->set.connecttimeout > 0) ?
+ data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
+ ctimeleft_ms = ctimeout_ms -
+ Curl_timediff(*nowp, data->progress.t_startsingle);
+ if(!ctimeleft_ms)
+ ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
+ if(!timeleft_ms)
+ return ctimeleft_ms; /* no general timeout, this is it */
}
-
- if(!timeout_ms)
- /* avoid returning 0 as that means no timeout! */
- return -1;
-
- return timeout_ms;
+ /* return minimal time left or max amount already expired */
+ return (ctimeleft_ms < timeleft_ms)? ctimeleft_ms : timeleft_ms;
}
/* Copies connection info into the transfer handle to make it available when
@@ -348,6 +335,7 @@ void Curl_conncontrol(struct connectdata *conn,
*/
struct eyeballer {
const char *name;
+ const struct Curl_addrinfo *first; /* complete address list, not owned */
const struct Curl_addrinfo *addr; /* List of addresses to try, not owned */
int ai_family; /* matching address family only */
cf_ip_connect_create *cf_create; /* for creating cf */
@@ -359,9 +347,12 @@ struct eyeballer {
expire_id timeout_id; /* ID for Curl_expire() */
CURLcode result;
int error;
+ BIT(rewinded); /* if we rewinded the addr list */
BIT(has_started); /* attempts have started */
BIT(is_done); /* out of addresses/time */
BIT(connected); /* cf has connected */
+ BIT(inconclusive); /* connect was not a hard failure, we
+ * might talk to a restarting server */
};
@@ -398,7 +389,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
struct eyeballer *baller;
*pballer = NULL;
- baller = calloc(1, sizeof(*baller) + 1000);
+ baller = calloc(1, sizeof(*baller));
if(!baller)
return CURLE_OUT_OF_MEMORY;
@@ -408,7 +399,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
#endif
"ip"));
baller->cf_create = cf_create;
- baller->addr = addr;
+ baller->first = baller->addr = addr;
baller->ai_family = ai_family;
baller->primary = primary;
baller->delay_ms = delay_ms;
@@ -438,6 +429,13 @@ static void baller_free(struct eyeballer *baller,
}
}
+static void baller_rewind(struct eyeballer *baller)
+{
+ baller->rewinded = TRUE;
+ baller->addr = baller->first;
+ baller->inconclusive = FALSE;
+}
+
static void baller_next_addr(struct eyeballer *baller)
{
baller->addr = addr_next_match(baller->addr, baller->ai_family);
@@ -528,6 +526,10 @@ static CURLcode baller_start_next(struct Curl_cfilter *cf,
{
if(cf->sockindex == FIRSTSOCKET) {
baller_next_addr(baller);
+ /* If we get inconclusive answers from the server(s), we make
+ * a second iteration over the address list */
+ if(!baller->addr && baller->inconclusive && !baller->rewinded)
+ baller_rewind(baller);
baller_start(cf, data, baller, timeoutms);
}
else {
@@ -566,6 +568,8 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
baller->result = CURLE_OPERATION_TIMEDOUT;
}
}
+ else if(baller->result == CURLE_WEIRD_SERVER_REPLY)
+ baller->inconclusive = TRUE;
}
return baller->result;
}
@@ -595,7 +599,7 @@ evaluate:
*connected = FALSE; /* a very negative world view is best */
now = Curl_now();
ongoing = not_started = 0;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->is_done)
@@ -656,7 +660,7 @@ evaluate:
if(not_started > 0) {
int added = 0;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || baller->has_started)
@@ -691,13 +695,13 @@ evaluate:
/* all ballers have failed to connect. */
CURL_TRC_CF(data, cf, "all eyeballers failed");
result = CURLE_COULDNT_CONNECT;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
+ if(!baller)
+ continue;
CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d",
- baller?baller->name:NULL,
- baller?baller->has_started:0,
- baller?baller->result:0);
- if(baller && baller->has_started && baller->result) {
+ baller->name, baller->has_started, baller->result);
+ if(baller->has_started && baller->result) {
result = baller->result;
break;
}
@@ -838,7 +842,7 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGASSERT(ctx);
DEBUGASSERT(data);
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
baller_free(ctx->baller[i], data);
ctx->baller[i] = NULL;
}
@@ -846,35 +850,22 @@ static void cf_he_ctx_clear(struct Curl_cfilter *cf, struct Curl_easy *data)
ctx->winner = NULL;
}
-static int cf_he_get_select_socks(struct Curl_cfilter *cf,
+static void cf_he_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_he_ctx *ctx = cf->ctx;
- size_t i, s;
- int wrc, rc = GETSOCK_BLANK;
- curl_socket_t wsocks[MAX_SOCKSPEREASYHANDLE];
-
- if(cf->connected)
- return cf->next->cft->get_select_socks(cf->next, data, socks);
-
- for(i = s = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
- struct eyeballer *baller = ctx->baller[i];
- if(!baller || !baller->cf)
- continue;
+ size_t i;
- wrc = Curl_conn_cf_get_select_socks(baller->cf, data, wsocks);
- if(wrc) {
- /* TODO: we assume we get at most one socket back */
- socks[s] = wsocks[0];
- if(wrc & GETSOCK_WRITESOCK(0))
- rc |= GETSOCK_WRITESOCK(s);
- if(wrc & GETSOCK_READSOCK(0))
- rc |= GETSOCK_READSOCK(s);
- s++;
+ if(!cf->connected) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
+ struct eyeballer *baller = ctx->baller[i];
+ if(!baller || !baller->cf)
+ continue;
+ Curl_conn_cf_adjust_pollset(baller->cf, data, ps);
}
+ CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
}
- return rc;
}
static CURLcode cf_he_connect(struct Curl_cfilter *cf,
@@ -901,7 +892,7 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
if(result)
return result;
ctx->state = SCFST_WAITING;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SCFST_WAITING:
result = is_connected(cf, data, done);
if(!result && *done) {
@@ -956,7 +947,7 @@ static bool cf_he_data_pending(struct Curl_cfilter *cf,
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
if(!baller || !baller->cf)
continue;
@@ -975,7 +966,7 @@ static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
size_t i;
memset(&tmax, 0, sizeof(tmax));
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
memset(&t, 0, sizeof(t));
@@ -1000,7 +991,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
int reply_ms = -1;
size_t i;
- for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
+ for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
struct eyeballer *baller = ctx->baller[i];
int breply_ms;
@@ -1055,7 +1046,7 @@ struct Curl_cftype Curl_cft_happy_eyeballs = {
cf_he_connect,
cf_he_close,
Curl_cf_def_get_host,
- cf_he_get_select_socks,
+ cf_he_adjust_pollset,
cf_he_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -1089,7 +1080,7 @@ cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
*pcf = NULL;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@@ -1122,13 +1113,13 @@ struct transport_provider transport_providers[] = {
#ifdef ENABLE_QUIC
{ TRNSPRT_QUIC, Curl_cf_quic_create },
#endif
+#ifndef CURL_DISABLE_TFTP
{ TRNSPRT_UDP, Curl_cf_udp_create },
+#endif
+#ifdef USE_UNIX_SOCKETS
{ TRNSPRT_UNIX, Curl_cf_unix_create },
-};
-
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
+};
static cf_ip_connect_create *get_cf_create(int transport)
{
@@ -1319,7 +1310,7 @@ struct Curl_cftype Curl_cft_setup = {
cf_setup_connect,
cf_setup_close,
Curl_cf_def_get_host,
- Curl_cf_def_get_select_socks,
+ Curl_cf_def_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -1340,7 +1331,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OK;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index be7c075e9..c1abf24e8 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -63,6 +63,9 @@
#ifndef CURL_DISABLE_HTTP
+/* allow no more than 5 "chained" compression steps */
+#define MAX_ENCODE_STACK 5
+
#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
@@ -95,7 +98,7 @@ typedef enum {
/* Deflate and gzip writer. */
struct zlib_writer {
- struct contenc_writer super;
+ struct Curl_cwriter super;
zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
@@ -171,7 +174,7 @@ static CURLcode process_trailer(struct Curl_easy *data,
}
static CURLcode inflate_stream(struct Curl_easy *data,
- struct contenc_writer *writer,
+ struct Curl_cwriter *writer, int type,
zlibInitState started)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
@@ -196,7 +199,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
/* because the buffer size is fixed, iteratively decompress and transfer to
- the client via downstream_write function. */
+ the client via next_write function. */
while(!done) {
int status; /* zlib status */
done = TRUE;
@@ -217,7 +220,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
if(z->avail_out != DSIZ) {
if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */
- result = Curl_unencode_write(data, writer->downstream, decomp,
+ result = Curl_cwriter_write(data, writer->next, type, decomp,
DSIZ - z->avail_out);
if(result) {
exit_zlib(data, z, &zp->zlib_init, result);
@@ -274,8 +277,8 @@ static CURLcode inflate_stream(struct Curl_easy *data,
/* Deflate handler. */
-static CURLcode deflate_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode deflate_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -290,13 +293,16 @@ static CURLcode deflate_init_writer(struct Curl_easy *data,
return CURLE_OK;
}
-static CURLcode deflate_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode deflate_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
/* Set the compressed input when this function is called */
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
@@ -305,11 +311,11 @@ static CURLcode deflate_unencode_write(struct Curl_easy *data,
return process_trailer(data, zp);
/* Now uncompress the data */
- return inflate_stream(data, writer, ZLIB_INFLATING);
+ return inflate_stream(data, writer, type, ZLIB_INFLATING);
}
-static void deflate_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void deflate_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -317,19 +323,19 @@ static void deflate_close_writer(struct Curl_easy *data,
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
-static const struct content_encoding deflate_encoding = {
+static const struct Curl_cwtype deflate_encoding = {
"deflate",
NULL,
- deflate_init_writer,
- deflate_unencode_write,
- deflate_close_writer,
+ deflate_do_init,
+ deflate_do_write,
+ deflate_do_close,
sizeof(struct zlib_writer)
};
/* Gzip handler. */
-static CURLcode gzip_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode gzip_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -359,11 +365,14 @@ static CURLcode gzip_init_writer(struct Curl_easy *data,
#ifdef OLD_ZLIB_SUPPORT
/* Skip over the gzip header */
-static enum {
+typedef enum {
GZIP_OK,
GZIP_BAD,
GZIP_UNDERFLOW
-} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
+} gzip_status;
+
+static gzip_status check_gzip_header(unsigned char const *data, ssize_t len,
+ ssize_t *headerlen)
{
int method, flags;
const ssize_t totallen = len;
@@ -441,19 +450,22 @@ static enum {
}
#endif
-static CURLcode gzip_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode gzip_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
if(zp->zlib_init == ZLIB_INIT_GZIP) {
/* Let zlib handle the gzip decompression entirely */
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
/* Now uncompress the data */
- return inflate_stream(data, writer, ZLIB_INIT_GZIP);
+ return inflate_stream(data, writer, type, ZLIB_INIT_GZIP);
}
#ifndef OLD_ZLIB_SUPPORT
@@ -565,12 +577,12 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
}
/* We've parsed the header, now uncompress the data */
- return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
+ return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING);
#endif
}
-static void gzip_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void gzip_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -578,12 +590,12 @@ static void gzip_close_writer(struct Curl_easy *data,
exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
}
-static const struct content_encoding gzip_encoding = {
+static const struct Curl_cwtype gzip_encoding = {
"gzip",
"x-gzip",
- gzip_init_writer,
- gzip_unencode_write,
- gzip_close_writer,
+ gzip_do_init,
+ gzip_do_write,
+ gzip_do_close,
sizeof(struct zlib_writer)
};
@@ -593,7 +605,7 @@ static const struct content_encoding gzip_encoding = {
#ifdef HAVE_BROTLI
/* Brotli writer. */
struct brotli_writer {
- struct contenc_writer super;
+ struct Curl_cwriter super;
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -635,8 +647,8 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
return CURLE_WRITE_ERROR;
}
-static CURLcode brotli_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode brotli_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
@@ -645,8 +657,8 @@ static CURLcode brotli_init_writer(struct Curl_easy *data,
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
}
-static CURLcode brotli_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode brotli_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
@@ -657,6 +669,9 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
CURLcode result = CURLE_OK;
BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
if(!bp->br)
return CURLE_WRITE_ERROR; /* Stream already ended. */
@@ -670,7 +685,7 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
dstleft = DSIZ;
r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL);
- result = Curl_unencode_write(data, writer->downstream,
+ result = Curl_cwriter_write(data, writer->next, type,
decomp, DSIZ - dstleft);
if(result)
break;
@@ -693,8 +708,8 @@ static CURLcode brotli_unencode_write(struct Curl_easy *data,
return result;
}
-static void brotli_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void brotli_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
@@ -706,12 +721,12 @@ static void brotli_close_writer(struct Curl_easy *data,
}
}
-static const struct content_encoding brotli_encoding = {
+static const struct Curl_cwtype brotli_encoding = {
"br",
NULL,
- brotli_init_writer,
- brotli_unencode_write,
- brotli_close_writer,
+ brotli_do_init,
+ brotli_do_write,
+ brotli_do_close,
sizeof(struct brotli_writer)
};
#endif
@@ -720,13 +735,13 @@ static const struct content_encoding brotli_encoding = {
#ifdef HAVE_ZSTD
/* Zstd writer. */
struct zstd_writer {
- struct contenc_writer super;
+ struct Curl_cwriter super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
};
-static CURLcode zstd_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode zstd_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -737,8 +752,8 @@ static CURLcode zstd_init_writer(struct Curl_easy *data,
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
-static CURLcode zstd_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode zstd_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
@@ -747,6 +762,9 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
ZSTD_outBuffer out;
size_t errorCode;
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
if(!zp->decomp) {
zp->decomp = malloc(DSIZ);
if(!zp->decomp)
@@ -766,7 +784,7 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
return CURLE_BAD_CONTENT_ENCODING;
}
if(out.pos > 0) {
- result = Curl_unencode_write(data, writer->downstream,
+ result = Curl_cwriter_write(data, writer->next, type,
zp->decomp, out.pos);
if(result)
break;
@@ -778,8 +796,8 @@ static CURLcode zstd_unencode_write(struct Curl_easy *data,
return result;
}
-static void zstd_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void zstd_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -795,52 +813,30 @@ static void zstd_close_writer(struct Curl_easy *data,
}
}
-static const struct content_encoding zstd_encoding = {
+static const struct Curl_cwtype zstd_encoding = {
"zstd",
NULL,
- zstd_init_writer,
- zstd_unencode_write,
- zstd_close_writer,
+ zstd_do_init,
+ zstd_do_write,
+ zstd_do_close,
sizeof(struct zstd_writer)
};
#endif
/* Identity handler. */
-static CURLcode identity_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
-{
- (void)data;
- (void)writer;
- return CURLE_OK;
-}
-
-static CURLcode identity_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
-{
- return Curl_unencode_write(data, writer->downstream, buf, nbytes);
-}
-
-static void identity_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
-{
- (void) data;
- (void) writer;
-}
-
-static const struct content_encoding identity_encoding = {
+static const struct Curl_cwtype identity_encoding = {
"identity",
"none",
- identity_init_writer,
- identity_unencode_write,
- identity_close_writer,
- sizeof(struct contenc_writer)
+ Curl_cwriter_def_init,
+ Curl_cwriter_def_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
};
-/* supported content encodings table. */
-static const struct content_encoding * const encodings[] = {
+/* supported general content decoders. */
+static const struct Curl_cwtype * const general_unencoders[] = {
&identity_encoding,
#ifdef HAVE_LIBZ
&deflate_encoding,
@@ -855,28 +851,39 @@ static const struct content_encoding * const encodings[] = {
NULL
};
+/* supported content decoders only for transfer encodings */
+static const struct Curl_cwtype * const transfer_unencoders[] = {
+#ifndef CURL_DISABLE_HTTP
+ &Curl_httpchunk_unencoder,
+#endif
+ NULL
+};
-/* Return a list of comma-separated names of supported encodings. */
-char *Curl_all_content_encodings(void)
+/* Provide a list of comma-separated names of supported encodings.
+*/
+void Curl_all_content_encodings(char *buf, size_t blen)
{
size_t len = 0;
- const struct content_encoding * const *cep;
- const struct content_encoding *ce;
- char *ace;
+ const struct Curl_cwtype * const *cep;
+ const struct Curl_cwtype *ce;
+
+ DEBUGASSERT(buf);
+ DEBUGASSERT(blen);
+ buf[0] = 0;
- for(cep = encodings; *cep; cep++) {
+ for(cep = general_unencoders; *cep; cep++) {
ce = *cep;
if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT))
len += strlen(ce->name) + 2;
}
- if(!len)
- return strdup(CONTENT_ENCODING_DEFAULT);
-
- ace = malloc(len);
- if(ace) {
- char *p = ace;
- for(cep = encodings; *cep; cep++) {
+ if(!len) {
+ if(blen >= sizeof(CONTENT_ENCODING_DEFAULT))
+ strcpy(buf, CONTENT_ENCODING_DEFAULT);
+ }
+ else if(blen > len) {
+ char *p = buf;
+ for(cep = general_unencoders; *cep; cep++) {
ce = *cep;
if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
strcpy(p, ce->name);
@@ -887,75 +894,71 @@ char *Curl_all_content_encodings(void)
}
p[-2] = '\0';
}
-
- return ace;
}
-
/* Deferred error dummy writer. */
-static CURLcode error_init_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static CURLcode error_do_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
(void)data;
(void)writer;
return CURLE_OK;
}
-static CURLcode error_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
+static CURLcode error_do_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
- char *all = Curl_all_content_encodings();
+ char all[256];
+ (void)Curl_all_content_encodings(all, sizeof(all));
(void) writer;
(void) buf;
(void) nbytes;
- if(!all)
- return CURLE_OUT_OF_MEMORY;
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
failf(data, "Unrecognized content encoding type. "
"libcurl understands %s content encodings.", all);
- free(all);
return CURLE_BAD_CONTENT_ENCODING;
}
-static void error_close_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+static void error_do_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
(void) data;
(void) writer;
}
-static const struct content_encoding error_encoding = {
- NULL,
+static const struct Curl_cwtype error_writer = {
+ "ce-error",
NULL,
- error_init_writer,
- error_unencode_write,
- error_close_writer,
- sizeof(struct contenc_writer)
+ error_do_init,
+ error_do_write,
+ error_do_close,
+ sizeof(struct Curl_cwriter)
};
-/* Write data using an unencoding writer stack. "nbytes" is not
- allowed to be 0. */
-CURLcode Curl_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
-{
- if(!nbytes)
- return CURLE_OK;
- if(!writer)
- return CURLE_WRITE_ERROR;
- return writer->handler->unencode_write(data, writer, buf, nbytes);
-}
-
/* Find the content encoding by name. */
-static const struct content_encoding *find_encoding(const char *name,
- size_t len)
+static const struct Curl_cwtype *find_unencode_writer(const char *name,
+ size_t len,
+ Curl_cwriter_phase phase)
{
- const struct content_encoding * const *cep;
-
- for(cep = encodings; *cep; cep++) {
- const struct content_encoding *ce = *cep;
+ const struct Curl_cwtype * const *cep;
+
+ if(phase == CURL_CW_TRANSFER_DECODE) {
+ for(cep = transfer_unencoders; *cep; cep++) {
+ const struct Curl_cwtype *ce = *cep;
+ if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
+ (ce->alias && strncasecompare(name, ce->alias, len)
+ && !ce->alias[len]))
+ return ce;
+ }
+ }
+ /* look among the general decoders */
+ for(cep = general_unencoders; *cep; cep++) {
+ const struct Curl_cwtype *ce = *cep;
if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
(ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
return ce;
@@ -968,8 +971,8 @@ static const struct content_encoding *find_encoding(const char *name,
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer)
{
- struct SingleRequest *k = &data->req;
- unsigned int order = is_transfer? 2: 1;
+ Curl_cwriter_phase phase = is_transfer?
+ CURL_CW_TRANSFER_DECODE:CURL_CW_CONTENT_DECODE;
CURLcode result;
do {
@@ -986,29 +989,36 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
if(!ISSPACE(*enclist))
namelen = enclist - name + 1;
- /* Special case: chunked encoding is handled at the reader level. */
- if(is_transfer && namelen == 7 && strncasecompare(name, "chunked", 7)) {
- k->chunk = TRUE; /* chunks coming our way. */
- Curl_httpchunk_init(data); /* init our chunky engine. */
- }
- else if(namelen) {
- const struct content_encoding *encoding;
- struct contenc_writer *writer;
- if(is_transfer && !data->set.http_transfer_encoding)
+ if(namelen) {
+ const struct Curl_cwtype *cwt;
+ struct Curl_cwriter *writer;
+
+ /* if we skip the decoding in this phase, do not look further.
+ * Exception is "chunked" transfer-encoding which always must happen */
+ if((is_transfer && !data->set.http_transfer_encoding &&
+ (namelen != 7 || !strncasecompare(name, "chunked", 7))) ||
+ (!is_transfer && data->set.http_ce_skip)) {
/* not requested, ignore */
return CURLE_OK;
+ }
- encoding = find_encoding(name, namelen);
- if(!encoding)
- encoding = &error_encoding; /* Defer error at stack use. */
+ if(Curl_cwriter_count(data, phase) + 1 >= MAX_ENCODE_STACK) {
+ failf(data, "Reject response due to more than %u content encodings",
+ MAX_ENCODE_STACK);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
- result = Curl_client_create_writer(&writer, data, encoding, order);
+ cwt = find_unencode_writer(name, namelen, phase);
+ if(!cwt)
+ cwt = &error_writer; /* Defer error at use. */
+
+ result = Curl_cwriter_create(&writer, data, cwt, phase);
if(result)
return result;
- result = Curl_client_add_writer(data, writer);
+ result = Curl_cwriter_add(data, writer);
if(result) {
- Curl_client_free_writer(data, writer);
+ Curl_cwriter_free(data, writer);
return result;
}
}
@@ -1028,20 +1038,15 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
return CURLE_NOT_BUILT_IN;
}
-CURLcode Curl_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
+void Curl_all_content_encodings(char *buf, size_t blen)
{
- (void) data;
- (void) writer;
- (void) buf;
- (void) nbytes;
- return CURLE_NOT_BUILT_IN;
+ DEBUGASSERT(buf);
+ DEBUGASSERT(blen);
+ if(blen < sizeof(CONTENT_ENCODING_DEFAULT))
+ buf[0] = 0;
+ else
+ strcpy(buf, CONTENT_ENCODING_DEFAULT);
}
-char *Curl_all_content_encodings(void)
-{
- return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */
-}
#endif /* CURL_DISABLE_HTTP */
diff --git a/lib/content_encoding.h b/lib/content_encoding.h
index ef7930cb3..1addf230b 100644
--- a/lib/content_encoding.h
+++ b/lib/content_encoding.h
@@ -25,15 +25,10 @@
***************************************************************************/
#include "curl_setup.h"
-struct contenc_writer;
+struct Curl_cwriter;
-char *Curl_all_content_encodings(void);
+void Curl_all_content_encodings(char *buf, size_t blen);
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int is_transfer);
-CURLcode Curl_unencode_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes);
-void Curl_unencode_cleanup(struct Curl_easy *data);
-
#endif /* HEADER_CURL_CONTENT_ENCODING_H */
diff --git a/lib/cookie.c b/lib/cookie.c
index af01203a9..dc319b611 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -330,7 +330,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
*/
void Curl_cookie_loadfiles(struct Curl_easy *data)
{
- struct curl_slist *list = data->set.cookielist;
+ struct curl_slist *list = data->state.cookielist;
if(list) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
while(list) {
@@ -365,9 +365,7 @@ static void strstore(char **str, const char *newstr, size_t len)
DEBUGASSERT(newstr);
DEBUGASSERT(str);
free(*str);
- *str = Curl_memdup(newstr, len + 1);
- if(*str)
- (*str)[len] = 0;
+ *str = Curl_memdup0(newstr, len);
}
/*
@@ -823,10 +821,8 @@ Curl_cookie_add(struct Curl_easy *data,
endslash = memrchr(path, '/', (queryp - path));
if(endslash) {
size_t pathlen = (endslash-path + 1); /* include end slash */
- co->path = malloc(pathlen + 1); /* one extra for the zero byte */
+ co->path = Curl_memdup0(path, pathlen);
if(co->path) {
- memcpy(co->path, path, pathlen);
- co->path[pathlen] = 0; /* null-terminate */
co->spath = sanitize_cookie_path(co->path);
if(!co->spath)
badcookie = TRUE; /* out of memory bad */
@@ -929,7 +925,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(!co->spath)
badcookie = TRUE;
fields++; /* add a field and fall down to secure */
- /* FALLTHROUGH */
+ FALLTHROUGH();
case 3:
co->secure = FALSE;
if(strcasecompare(ptr, "TRUE")) {
@@ -1029,15 +1025,23 @@ Curl_cookie_add(struct Curl_easy *data,
* dereference it.
*/
if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) {
- const psl_ctx_t *psl = Curl_psl_use(data);
- int acceptable;
-
- if(psl) {
- acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
- Curl_psl_release(data);
+ bool acceptable = FALSE;
+ char lcase[256];
+ char lcookie[256];
+ size_t dlen = strlen(domain);
+ size_t clen = strlen(co->domain);
+ if((dlen < sizeof(lcase)) && (clen < sizeof(lcookie))) {
+ const psl_ctx_t *psl = Curl_psl_use(data);
+ if(psl) {
+ /* the PSL check requires lowercase domain name and pattern */
+ Curl_strntolower(lcase, domain, dlen + 1);
+ Curl_strntolower(lcookie, co->domain, clen + 1);
+ acceptable = psl_is_cookie_domain_acceptable(psl, lcase, lcookie);
+ Curl_psl_release(data);
+ }
+ else
+ acceptable = !bad_domain(domain, strlen(domain));
}
- else
- acceptable = !bad_domain(domain, strlen(domain));
if(!acceptable) {
infof(data, "cookie '%s' dropped, domain '%s' must not "
@@ -1223,7 +1227,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
if(data) {
FILE *fp = NULL;
- if(file) {
+ if(file && *file) {
if(!strcmp(file, "-"))
fp = stdin;
else {
@@ -1347,7 +1351,7 @@ static int cookie_sort_ct(const void *p1, const void *p2)
static struct Cookie *dup_cookie(struct Cookie *src)
{
- struct Cookie *d = calloc(sizeof(struct Cookie), 1);
+ struct Cookie *d = calloc(1, sizeof(struct Cookie));
if(d) {
CLONE(domain);
CLONE(path);
diff --git a/lib/curl_config.h b/lib/curl_config.h
index a5becc9a1..a4951d728 100644
--- a/lib/curl_config.h
+++ b/lib/curl_config.h
@@ -184,6 +184,9 @@
/* Define to 1 if you have the <crypto.h> header file. */
/* #undef HAVE_CRYPTO_H */
+/* Define to 1 if you have the fseeko declaration */
+#define HAVE_DECL_FSEEKO 1
+
/* Define to 1 if you have the declaration of `getpwuid_r', and to 0 if you
don't. */
#define HAVE_DECL_GETPWUID_R 1
@@ -197,9 +200,6 @@
/* Define to 1 if you have the <err.h> header file. */
/* #undef HAVE_ERR_H */
-/* Define to 1 if you have the `fchmod' function. */
-#define HAVE_FCHMOD 1
-
/* Define to 1 if you have the fcntl function. */
#define HAVE_FCNTL 1
@@ -308,12 +308,6 @@
/* if you have GNU GSS */
/* #undef HAVE_GSSGNU */
-/* if you have Heimdal */
-/* #undef HAVE_GSSHEIMDAL */
-
-/* if you have MIT Kerberos */
-/* #undef HAVE_GSSMIT */
-
/* Define to 1 if you have the <hyper.h> header file. */
/* #undef HAVE_HYPER_H */
@@ -707,18 +701,6 @@
/* Define to 1 if you have the <utime.h> header file. */
#define HAVE_UTIME_H 1
-/* Define to 1 if compiler supports C99 variadic macro style. */
-#define HAVE_VARIADIC_MACROS_C99 1
-
-/* Define to 1 if compiler supports old gcc variadic macro style. */
-#define HAVE_VARIADIC_MACROS_GCC 1
-
-/* Define to 1 if you have the windows.h header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the winsock2.h header file. */
-/* #undef HAVE_WINSOCK2_H */
-
/* Define to 1 if you have the <wolfssh/ssh.h> header file. */
/* #undef HAVE_WOLFSSH_SSH_H */
@@ -737,9 +719,6 @@
/* Define this symbol if your OS supports changing the contents of argv */
#define HAVE_WRITABLE_ARGV 1
-/* Define to 1 if you have the ws2tcpip.h header file. */
-/* #undef HAVE_WS2TCPIP_H */
-
/* Define to 1 if you have the <x509.h> header file. */
/* #undef HAVE_X509_H */
@@ -874,6 +853,9 @@
/* if ngtcp2 is in use */
/* #undef USE_NGTCP2 */
+/* if ngtcp2_crypto_boringssl is in use */
+/* #undef USE_NGTCP2_CRYPTO_BORINGSSL */
+
/* if ngtcp2_crypto_gnutls is in use */
/* #undef USE_NGTCP2_CRYPTO_GNUTLS */
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 0bfb45796..937b93edb 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -74,9 +74,15 @@
/* disables FTP */
#cmakedefine CURL_DISABLE_FTP 1
+/* disables curl_easy_options API for existing options to curl_easy_setopt */
+#cmakedefine CURL_DISABLE_GETOPTIONS 1
+
/* disables GOPHER */
#cmakedefine CURL_DISABLE_GOPHER 1
+/* disables headers-api support */
+#cmakedefine CURL_DISABLE_HEADERS_API 1
+
/* disables HSTS support */
#cmakedefine CURL_DISABLE_HSTS 1
@@ -98,6 +104,9 @@
/* disables MIME support */
#cmakedefine CURL_DISABLE_MIME 1
+/* disables local binding support */
+#cmakedefine CURL_DISABLE_BINDLOCAL 1
+
/* disables MQTT */
#cmakedefine CURL_DISABLE_MQTT 1
@@ -168,9 +177,6 @@
/* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ATOMIC 1
-/* Define to 1 if you have the `fchmod' function. */
-#cmakedefine HAVE_FCHMOD 1
-
/* Define to 1 if you have the `fnmatch' function. */
#cmakedefine HAVE_FNMATCH 1
@@ -208,6 +214,9 @@
/* Define to 1 if you have the fseeko function. */
#cmakedefine HAVE_FSEEKO 1
+/* Define to 1 if you have the fseeko declaration. */
+#cmakedefine HAVE_DECL_FSEEKO 1
+
/* Define to 1 if you have the _fseeki64 function. */
#cmakedefine HAVE__FSEEKI64 1
@@ -289,12 +298,6 @@
/* if you have the GNU gssapi libraries */
#cmakedefine HAVE_GSSGNU 1
-/* if you have the Heimdal gssapi libraries */
-#cmakedefine HAVE_GSSHEIMDAL 1
-
-/* if you have the MIT gssapi libraries */
-#cmakedefine HAVE_GSSMIT 1
-
/* Define to 1 if you have the `idna_strerror' function. */
#cmakedefine HAVE_IDNA_STRERROR 1
@@ -313,9 +316,6 @@
/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
#cmakedefine HAVE_ADDRESS_FAMILY 1
-/* Define to 1 if you have the <inttypes.h> header file. */
-#cmakedefine HAVE_INTTYPES_H 1
-
/* Define to 1 if you have the ioctlsocket function. */
#cmakedefine HAVE_IOCTLSOCKET 1
@@ -497,9 +497,6 @@
/* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine HAVE_STDBOOL_H 1
-/* Define to 1 if you have the <stdint.h> header file. */
-#cmakedefine HAVE_STDINT_H 1
-
/* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1
@@ -596,24 +593,9 @@
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H 1
-/* Define to 1 if compiler supports C99 variadic macro style. */
-#cmakedefine HAVE_VARIADIC_MACROS_C99 1
-
-/* Define to 1 if compiler supports old gcc variadic macro style. */
-#cmakedefine HAVE_VARIADIC_MACROS_GCC 1
-
-/* Define to 1 if you have the windows.h header file. */
-#cmakedefine HAVE_WINDOWS_H 1
-
-/* Define to 1 if you have the winsock2.h header file. */
-#cmakedefine HAVE_WINSOCK2_H 1
-
/* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV 1
-/* Define to 1 if you have the ws2tcpip.h header file. */
-#cmakedefine HAVE_WS2TCPIP_H 1
-
/* Define to 1 if you need the lber.h header file even with ldap.h */
#cmakedefine NEED_LBER_H 1
@@ -716,9 +698,6 @@ ${SIZEOF_TIME_T_CODE}
/* if libPSL is in use */
#cmakedefine USE_LIBPSL 1
-/* If you want to build curl with the built-in manual */
-#cmakedefine USE_MANUAL 1
-
/* if you want to use OpenLDAP code instead of legacy ldap implementation */
#cmakedefine USE_OPENLDAP 1
diff --git a/lib/curl_config.h.in b/lib/curl_config.h.in
index 4037b3aae..617724ef6 100644
--- a/lib/curl_config.h.in
+++ b/lib/curl_config.h.in
@@ -199,6 +199,9 @@
/* Define to 1 if you have the <crypto.h> header file. */
#undef HAVE_CRYPTO_H
+/* Define to 1 if you have the fseeko declaration */
+#undef HAVE_DECL_FSEEKO
+
/* Define to 1 if you have the declaration of `getpwuid_r', and to 0 if you
don't. */
#undef HAVE_DECL_GETPWUID_R
@@ -212,9 +215,6 @@
/* Define to 1 if you have the <err.h> header file. */
#undef HAVE_ERR_H
-/* Define to 1 if you have the `fchmod' function. */
-#undef HAVE_FCHMOD
-
/* Define to 1 if you have the fcntl function. */
#undef HAVE_FCNTL
@@ -323,12 +323,6 @@
/* if you have GNU GSS */
#undef HAVE_GSSGNU
-/* if you have Heimdal */
-#undef HAVE_GSSHEIMDAL
-
-/* if you have MIT Kerberos */
-#undef HAVE_GSSMIT
-
/* Define to 1 if you have the <hyper.h> header file. */
#undef HAVE_HYPER_H
@@ -493,6 +487,9 @@
/* Define to 1 if you have the <openssl/pem.h> header file. */
#undef HAVE_OPENSSL_PEM_H
+/* if you have the functions OSSL_QUIC_client_method */
+#undef HAVE_OPENSSL_QUIC
+
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#undef HAVE_OPENSSL_RSA_H
@@ -602,6 +599,10 @@
/* Define to 1 if you have the `SSL_set0_wbio' function. */
#undef HAVE_SSL_SET0_WBIO
+/* Define to 1 if you have the `SSL_set_quic_use_legacy_codepoint' function.
+ */
+#undef HAVE_SSL_SET_QUIC_USE_LEGACY_CODEPOINT
+
/* Define to 1 if you have the <stdatomic.h> header file. */
#undef HAVE_STDATOMIC_H
@@ -722,18 +723,6 @@
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
-/* Define to 1 if compiler supports C99 variadic macro style. */
-#undef HAVE_VARIADIC_MACROS_C99
-
-/* Define to 1 if compiler supports old gcc variadic macro style. */
-#undef HAVE_VARIADIC_MACROS_GCC
-
-/* Define to 1 if you have the windows.h header file. */
-#undef HAVE_WINDOWS_H
-
-/* Define to 1 if you have the winsock2.h header file. */
-#undef HAVE_WINSOCK2_H
-
/* Define to 1 if you have the <wolfssh/ssh.h> header file. */
#undef HAVE_WOLFSSH_SSH_H
@@ -752,9 +741,6 @@
/* Define this symbol if your OS supports changing the contents of argv */
#undef HAVE_WRITABLE_ARGV
-/* Define to 1 if you have the ws2tcpip.h header file. */
-#undef HAVE_WS2TCPIP_H
-
/* Define to 1 if you have the <x509.h> header file. */
#undef HAVE_X509_H
@@ -892,6 +878,9 @@
/* if ngtcp2 is in use */
#undef USE_NGTCP2
+/* if ngtcp2_crypto_boringssl is in use */
+#undef USE_NGTCP2_CRYPTO_BORINGSSL
+
/* if ngtcp2_crypto_gnutls is in use */
#undef USE_NGTCP2_CRYPTO_GNUTLS
@@ -901,12 +890,21 @@
/* if ngtcp2_crypto_wolfssl is in use */
#undef USE_NGTCP2_CRYPTO_WOLFSSL
+/* if ngtcp2 + nghttp3 is in use */
+#undef USE_NGTCP2_H3
+
/* Use OpenLDAP-specific code */
#undef USE_OPENLDAP
/* if OpenSSL is in use */
#undef USE_OPENSSL
+/* if openssl quic + nghttp3 is in use */
+#undef USE_OPENSSL_H3
+
+/* if openssl QUIC is in use */
+#undef USE_OPENSSL_QUIC
+
/* if quiche is in use */
#undef USE_QUICHE
diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h
index 2ea03dd26..7a5387a94 100644
--- a/lib/curl_hmac.h
+++ b/lib/curl_hmac.h
@@ -25,7 +25,8 @@
***************************************************************************/
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
- || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
+ || !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
+ || defined(USE_LIBSSH2)
#include <curl/curl.h>
diff --git a/lib/curl_memory.h b/lib/curl_memory.h
index b8c46d793..714ad71c9 100644
--- a/lib/curl_memory.h
+++ b/lib/curl_memory.h
@@ -68,7 +68,7 @@
#undef send
#undef recv
-#ifdef WIN32
+#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# undef _wcsdup
@@ -134,7 +134,7 @@ extern curl_free_callback Curl_cfree;
extern curl_realloc_callback Curl_crealloc;
extern curl_strdup_callback Curl_cstrdup;
extern curl_calloc_callback Curl_ccalloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
extern curl_wcsdup_callback Curl_cwcsdup;
#endif
@@ -160,7 +160,7 @@ extern curl_wcsdup_callback Curl_cwcsdup;
#undef free
#define free(ptr) Curl_cfree(ptr)
-#ifdef WIN32
+#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# define wcsdup(ptr) Curl_cwcsdup(ptr)
diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c
index 522ea34e8..ff2109856 100644
--- a/lib/curl_multibyte.c
+++ b/lib/curl_multibyte.c
@@ -32,7 +32,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
#include "curl_multibyte.h"
@@ -84,7 +84,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
return str_utf8;
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
diff --git a/lib/curl_multibyte.h b/lib/curl_multibyte.h
index ddac1f638..8b9ac719e 100644
--- a/lib/curl_multibyte.h
+++ b/lib/curl_multibyte.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
/*
* MultiByte conversions using Windows kernel32 library.
@@ -33,7 +33,7 @@
wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
-#endif /* WIN32 */
+#endif /* _WIN32 */
/*
* Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
@@ -54,7 +54,7 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
* ensure that the curl memdebug override macros do not replace them.
*/
-#if defined(UNICODE) && defined(WIN32)
+#if defined(UNICODE) && defined(_WIN32)
#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))
@@ -78,7 +78,7 @@ typedef union {
const unsigned char *const_tbyte_ptr;
} xcharp_u;
-#endif /* UNICODE && WIN32 */
+#endif /* UNICODE && _WIN32 */
#define curlx_unicodefree(ptr) \
do { \
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index cc0ed9167..6f6d75c03 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -111,6 +111,7 @@
# include <wincrypt.h>
#else
# error "Can't compile NTLM support without a crypto library with DES."
+# define CURL_NTLM_NOT_SUPPORTED
#endif
#include "urldata.h"
@@ -130,6 +131,7 @@
#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
+#if !defined(CURL_NTLM_NOT_SUPPORTED)
/*
* Turns a 56-bit key into being 64-bit wide.
*/
@@ -144,6 +146,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
}
+#endif
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
/*
@@ -337,6 +340,10 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
encrypt_des(plaintext, results + 16, keys + 14);
+#else
+ (void)keys;
+ (void)plaintext;
+ (void)results;
#endif
}
@@ -347,9 +354,11 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
unsigned char *lmbuffer /* 21 bytes */)
{
unsigned char pw[14];
+#if !defined(CURL_NTLM_NOT_SUPPORTED)
static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
};
+#endif
size_t len = CURLMIN(strlen(password), 14);
Curl_strntoupper((char *)pw, password, len);
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index aa7bea75e..0c7892ab7 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -68,7 +68,9 @@
/* Portable 'sclose_nolog' used only in child process instead of 'sclose'
to avoid fooling the socket leak detector */
-#if defined(HAVE_CLOSESOCKET)
+#ifdef HAVE_PIPE
+# define sclose_nolog(x) close((x))
+#elif defined(HAVE_CLOSESOCKET)
# define sclose_nolog(x) closesocket((x))
#elif defined(HAVE_CLOSESOCKET_CAMEL)
# define sclose_nolog(x) CloseSocket((x))
@@ -189,7 +191,7 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
goto done;
}
- if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
+ if(wakeup_create(sockfds)) {
failf(data, "Could not open socket pair. errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
goto done;
@@ -197,8 +199,8 @@ static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
child_pid = fork();
if(child_pid == -1) {
- sclose(sockfds[0]);
- sclose(sockfds[1]);
+ wakeup_close(sockfds[0]);
+ wakeup_close(sockfds[1]);
failf(data, "Could not fork. errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
goto done;
@@ -264,11 +266,11 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
size_t len_in = strlen(input), len_out = 0;
struct dynbuf b;
char *ptr = NULL;
- unsigned char *buf = (unsigned char *)data->state.buffer;
+ usigned char buf[1024]
Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE);
while(len_in > 0) {
- ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
+ ssize_t written = wakeup_write(ntlm->ntlm_auth_hlpr_socket, input, len_in);
if(written == -1) {
/* Interrupted by a signal, retry it */
if(errno == EINTR)
@@ -282,7 +284,7 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
/* Read one line */
while(1) {
ssize_t size =
- sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
+ wakeup_read(ntlm->ntlm_auth_hlpr_socket, buf, sizeof(buf));
if(size == -1) {
if(errno == EINTR)
continue;
@@ -479,7 +481,7 @@ CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
/* connection is already authenticated,
* don't send a header in future requests */
*state = NTLMSTATE_LAST;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case NTLMSTATE_LAST:
Curl_safefree(*allocuserpwd);
authp->done = TRUE;
diff --git a/lib/curl_path.h b/lib/curl_path.h
index 9ed09dea8..cbe51c221 100644
--- a/lib/curl_path.h
+++ b/lib/curl_path.h
@@ -28,7 +28,7 @@
#include <curl/curl.h>
#include "urldata.h"
-#ifdef WIN32
+#ifdef _WIN32
# undef PATH_MAX
# define PATH_MAX MAX_PATH
# ifndef R_OK
diff --git a/lib/curl_printf.h b/lib/curl_printf.h
index 46ef344f7..c2457d2a6 100644
--- a/lib/curl_printf.h
+++ b/lib/curl_printf.h
@@ -31,6 +31,10 @@
#include <curl/mprintf.h>
+#define MERR_OK 0
+#define MERR_MEM 1
+#define MERR_TOO_LARGE 2
+
# undef printf
# undef fprintf
# undef msnprintf
diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c
index 406fb42ac..147b12a3f 100644
--- a/lib/curl_rtmp.c
+++ b/lib/curl_rtmp.c
@@ -39,7 +39,7 @@
/* The last #include file should be: */
#include "memdebug.h"
-#if defined(WIN32) && !defined(USE_LWIPSOCK)
+#if defined(_WIN32) && !defined(USE_LWIPSOCK)
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
#elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD)
@@ -79,7 +79,7 @@ const struct Curl_handler Curl_handler_rtmp = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMP, /* defport */
@@ -102,7 +102,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPT, /* defport */
@@ -125,7 +125,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMP, /* defport */
@@ -148,7 +148,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPT, /* defport */
@@ -171,7 +171,7 @@ const struct Curl_handler Curl_handler_rtmps = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPS, /* defport */
@@ -194,7 +194,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTMPS, /* defport */
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 91ddf1062..66639cbac 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -205,18 +205,23 @@ void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
sasl->force_ir = FALSE; /* Respect external option */
if(auth != CURLAUTH_BASIC) {
- sasl->resetprefs = FALSE;
- sasl->prefmech = SASL_AUTH_NONE;
+ unsigned short mechs = SASL_AUTH_NONE;
+
+ /* If some usable http authentication options have been set, determine
+ new defaults from them. */
if(auth & CURLAUTH_BASIC)
- sasl->prefmech |= SASL_MECH_PLAIN | SASL_MECH_LOGIN;
+ mechs |= SASL_MECH_PLAIN | SASL_MECH_LOGIN;
if(auth & CURLAUTH_DIGEST)
- sasl->prefmech |= SASL_MECH_DIGEST_MD5;
+ mechs |= SASL_MECH_DIGEST_MD5;
if(auth & CURLAUTH_NTLM)
- sasl->prefmech |= SASL_MECH_NTLM;
+ mechs |= SASL_MECH_NTLM;
if(auth & CURLAUTH_BEARER)
- sasl->prefmech |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2;
+ mechs |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2;
if(auth & CURLAUTH_GSSAPI)
- sasl->prefmech |= SASL_MECH_GSSAPI;
+ mechs |= SASL_MECH_GSSAPI;
+
+ if(mechs != SASL_AUTH_NONE)
+ sasl->prefmech = mechs;
}
}
@@ -262,6 +267,8 @@ static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
sasl->state = newstate;
}
+#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH)
/* Get the SASL server message and convert it to binary. */
static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
struct bufref *out)
@@ -284,6 +291,7 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
}
return result;
}
+#endif
/* Encode the outgoing SASL message. */
static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index ba14972e2..703e903fa 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -28,6 +28,18 @@
#define CURL_NO_OLDIES
#endif
+/* FIXME: Delete this once the warnings have been fixed. */
+#if !defined(CURL_WARN_SIGN_CONVERSION)
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
+#endif
+
+/* Set default _WIN32_WINNT */
+#ifdef __MINGW32__
+#include <_mingw.h>
+#endif
+
/*
* Disable Visual Studio warnings:
* 4127 "conditional expression is constant"
@@ -36,15 +48,7 @@
#pragma warning(disable:4127)
#endif
-/*
- * Define WIN32 when build target is Win32 API
- */
-
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-#define WIN32
-#endif
-
-#ifdef WIN32
+#ifdef _WIN32
/*
* Don't include unneeded stuff in Windows headers to avoid compiler
* warnings and macro clashes.
@@ -82,7 +86,7 @@
#ifdef _WIN32_WCE
# include "config-win32ce.h"
#else
-# ifdef WIN32
+# ifdef _WIN32
# include "config-win32.h"
# endif
#endif
@@ -214,6 +218,23 @@
# define CURL_DISABLE_RTSP
#endif
+/*
+ * When HTTP is disabled, disable HTTP-only features
+ */
+
+#if defined(CURL_DISABLE_HTTP)
+# define CURL_DISABLE_ALTSVC 1
+# define CURL_DISABLE_COOKIES 1
+# define CURL_DISABLE_BASIC_AUTH 1
+# define CURL_DISABLE_BEARER_AUTH 1
+# define CURL_DISABLE_AWS 1
+# define CURL_DISABLE_DOH 1
+# define CURL_DISABLE_FORM_API 1
+# define CURL_DISABLE_HEADERS_API 1
+# define CURL_DISABLE_HSTS 1
+# define CURL_DISABLE_HTTP_AUTH 1
+#endif
+
/* ================================================================ */
/* No system header file shall be included in this file before this */
/* point. */
@@ -239,12 +260,39 @@
* Windows setup file includes some system headers.
*/
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# include "setup-win32.h"
#endif
#include <curl/system.h>
+/* curl uses its own printf() function internally. It understands the GNU
+ * format. Use this format, so that is matches the GNU format attribute we
+ * use with the mingw compiler, allowing it to verify them at compile-time.
+ */
+#ifdef __MINGW32__
+# undef CURL_FORMAT_CURL_OFF_T
+# undef CURL_FORMAT_CURL_OFF_TU
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+#endif
+
+/* based on logic in "curl/mprintf.h" */
+
+#if (defined(__GNUC__) || defined(__clang__)) && \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(CURL_NO_FMT_CHECKS)
+#if defined(__MINGW32__) && !defined(__clang__)
+#define CURL_PRINTF(fmt, arg) \
+ __attribute__((format(gnu_printf, fmt, arg)))
+#else
+#define CURL_PRINTF(fmt, arg) \
+ __attribute__((format(__printf__, fmt, arg)))
+#endif
+#else
+#define CURL_PRINTF(fmt, arg)
+#endif
+
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
* interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
@@ -331,23 +379,6 @@
#include <curl/stdcheaders.h>
#endif
-#ifdef __POCC__
-# include <sys/types.h>
-# include <unistd.h>
-# define sys_nerr EILSEQ
-#endif
-
-/*
- * Salford-C kludge section (mostly borrowed from wxWidgets).
- */
-#ifdef __SALFORDC__
- #pragma suppress 353 /* Possible nested comments */
- #pragma suppress 593 /* Define not used */
- #pragma suppress 61 /* enum has no name */
- #pragma suppress 106 /* unnamed, unused parameter */
- #include <clib.h>
-#endif
-
/*
* Large file (>2Gb) support using WIN32 functions.
*/
@@ -411,6 +442,24 @@
#define SIZEOF_TIME_T 4
#endif
+#ifndef SIZEOF_CURL_SOCKET_T
+/* configure and cmake check and set the define */
+# ifdef _WIN64
+# define SIZEOF_CURL_SOCKET_T 8
+# else
+/* default guess */
+# define SIZEOF_CURL_SOCKET_T 4
+# endif
+#endif
+
+#if SIZEOF_CURL_SOCKET_T < 8
+# define CURL_FORMAT_SOCKET_T "d"
+#elif defined(__MINGW32__)
+# define CURL_FORMAT_SOCKET_T "zd"
+#else
+# define CURL_FORMAT_SOCKET_T "qd"
+#endif
+
/*
* Default sizeof(off_t) in case it hasn't been defined in config file.
*/
@@ -500,11 +549,11 @@
5. set dir/file naming defines
*/
-#ifdef WIN32
+#ifdef _WIN32
# define DIR_CHAR "\\"
-#else /* WIN32 */
+#else /* _WIN32 */
# ifdef MSDOS /* Watt-32 */
@@ -529,27 +578,7 @@
# define DIR_CHAR "/"
-# ifndef fileno /* sunos 4 have this as a macro! */
- int fileno(FILE *stream);
-# endif
-
-#endif /* WIN32 */
-
-/*
- * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
- * defined in ws2tcpip.h as well as to provide IPv6 support.
- * Does not apply if lwIP is used.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK)
-# if !defined(HAVE_WS2TCPIP_H) || \
- ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
-# undef HAVE_GETADDRINFO_THREADSAFE
-# undef HAVE_FREEADDRINFO
-# undef HAVE_GETADDRINFO
-# undef ENABLE_IPV6
-# endif
-#endif
+#endif /* _WIN32 */
/* ---------------------------------------------------------------- */
/* resolver specialty compile-time defines */
@@ -557,20 +586,11 @@
/* ---------------------------------------------------------------- */
/*
- * lcc-win32 doesn't have _beginthreadex(), lacks threads support.
- */
-
-#if defined(__LCC__) && defined(WIN32)
-# undef USE_THREADS_POSIX
-# undef USE_THREADS_WIN32
-#endif
-
-/*
* MSVC threads support requires a multi-threaded runtime library.
* _beginthreadex() is not available in single-threaded ones.
*/
-#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
+#if defined(_MSC_VER) && !defined(_MT)
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
@@ -581,6 +601,9 @@
#if defined(ENABLE_IPV6) && defined(HAVE_GETADDRINFO)
# define CURLRES_IPV6
+#elif defined(ENABLE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__))
+/* assume on Windows that IPv6 without getaddrinfo is a broken build */
+# error "Unexpected build: IPv6 is enabled but getaddrinfo was not found."
#else
# define CURLRES_IPV4
#endif
@@ -600,35 +623,6 @@
/* ---------------------------------------------------------------- */
-/*
- * msvc 6.0 does not have struct sockaddr_storage and
- * does not define IPPROTO_ESP in winsock2.h. But both
- * are available if PSDK is properly installed.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__)
-# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
-# undef HAVE_STRUCT_SOCKADDR_STORAGE
-# endif
-#endif
-
-/*
- * Intentionally fail to build when using msvc 6.0 without PSDK installed.
- * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
- * in lib/config-win32.h although absolutely discouraged and unsupported.
- */
-
-#if defined(_MSC_VER) && !defined(__POCC__)
-# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
-# if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
-# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
- "Windows Server 2003 PSDK"
-# else
-# define CURL_DISABLE_LDAP 1
-# endif
-# endif
-#endif
-
#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
/* The lib and header are present */
#define USE_LIBIDN2
@@ -694,6 +688,29 @@
# define WARN_UNUSED_RESULT
#endif
+/* noreturn attribute */
+
+#if !defined(CURL_NORETURN)
+#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__)
+# define CURL_NORETURN __attribute__((__noreturn__))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+# define CURL_NORETURN __declspec(noreturn)
+#else
+# define CURL_NORETURN
+#endif
+#endif
+
+/* fallthrough attribute */
+
+#if !defined(FALLTHROUGH)
+#if (defined(__GNUC__) && __GNUC__ >= 7) || \
+ (defined(__clang__) && __clang_major__ >= 10)
+# define FALLTHROUGH() __attribute__((fallthrough))
+#else
+# define FALLTHROUGH() do {} while (0)
+#endif
+#endif
+
/*
* Include macros and defines that should only be processed once.
*/
@@ -715,10 +732,7 @@
*/
#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)
-# if defined(SOCKET) || \
- defined(USE_WINSOCK) || \
- defined(HAVE_WINSOCK2_H) || \
- defined(HAVE_WS2TCPIP_H)
+# if defined(SOCKET) || defined(USE_WINSOCK)
# error "WinSock and lwIP TCP/IP stack definitions shall not coexist!"
# endif
#endif
@@ -752,7 +766,7 @@
/* In Windows the default file mode is text but an application can override it.
Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
*/
-#if defined(WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
#define FOPEN_READTEXT "rt"
#define FOPEN_WRITETEXT "wt"
#define FOPEN_APPENDTEXT "at"
@@ -807,12 +821,19 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define UNITTEST static
#endif
-#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */
+#if defined(USE_NGHTTP2)
#define USE_HTTP2
#endif
#if (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
+ (defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)) || \
defined(USE_QUICHE) || defined(USE_MSH3)
+
+#ifdef CURL_WITH_MULTI_SSL
+#error "Multi-SSL combined with QUIC is not supported"
+#endif
+
#define ENABLE_QUIC
#define USE_HTTP3
#endif
@@ -820,11 +841,11 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
/* Certain Windows implementations are not aligned with what curl expects,
so always use the local one on this platform. E.g. the mingw-w64
implementation can return wrong results for non-ASCII inputs. */
-#if defined(HAVE_BASENAME) && defined(WIN32)
+#if defined(HAVE_BASENAME) && defined(_WIN32)
#undef HAVE_BASENAME
#endif
-#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
+#if defined(USE_UNIX_SOCKETS) && defined(_WIN32)
# if !defined(UNIX_PATH_MAX)
/* Replicating logic present in afunix.h
(distributed with newer Windows 10 SDK versions only) */
diff --git a/lib/curl_setup_once.h b/lib/curl_setup_once.h
index c1ed05907..bf0ee663d 100644
--- a/lib/curl_setup_once.h
+++ b/lib/curl_setup_once.h
@@ -56,7 +56,7 @@
#include <sys/time.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#endif
@@ -70,11 +70,7 @@
#endif
#ifdef USE_WOLFSSL
-# if defined(HAVE_STDINT_H)
-# include <stdint.h>
-# elif defined(HAVE_INTTYPES_H)
-# include <inttypes.h>
-# endif
+#include <stdint.h>
#endif
#ifdef USE_SCHANNEL
diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h
index 5af7c2483..b26c39156 100644
--- a/lib/curl_sspi.h
+++ b/lib/curl_sspi.h
@@ -88,6 +88,22 @@ extern PSecurityFunctionTable s_pSecFn;
# define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
#endif
+#ifndef CRYPT_E_NO_REVOCATION_DLL
+# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
+#endif
+
+#ifndef CRYPT_E_NO_REVOCATION_CHECK
+# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
+#endif
+
+#ifndef CRYPT_E_REVOCATION_OFFLINE
+# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
+#endif
+
+#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE
+# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
+#endif
+
#ifdef UNICODE
# define SECFLAG_WINNT_AUTH_IDENTITY \
(unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE
diff --git a/lib/curl_trc.c b/lib/curl_trc.c
index e53b30573..b8dccc419 100644
--- a/lib/curl_trc.c
+++ b/lib/curl_trc.c
@@ -61,10 +61,6 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
bool inCallback = Curl_is_in_callback(data);
- /* CURLOPT_DEBUGFUNCTION doc says the user may set CURLOPT_PRIVATE to
- distinguish their handle from internal handles. */
- if(data->internal)
- DEBUGASSERT(!data->set.private_data);
Curl_set_in_callback(data, true);
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
Curl_set_in_callback(data, inCallback);
@@ -109,6 +105,8 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
}
}
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
+
/* Curl_infof() is for info message along the way */
#define MAXINFO 2048
@@ -128,13 +126,11 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
}
}
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
-
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
DEBUGASSERT(cf);
- if(data && Curl_trc_cf_is_verbose(cf, data)) {
+ if(Curl_trc_cf_is_verbose(cf, data)) {
va_list ap;
int len;
char buffer[MAXINFO + 2];
@@ -161,8 +157,10 @@ static struct Curl_cftype *cf_types[] = {
#endif
#ifdef USE_SSL
&Curl_cft_ssl,
+#ifndef CURL_DISABLE_PROXY
&Curl_cft_ssl_proxy,
#endif
+#endif
#if !defined(CURL_DISABLE_PROXY)
#if !defined(CURL_DISABLE_HTTP)
&Curl_cft_h1_proxy,
@@ -232,24 +230,14 @@ CURLcode Curl_trc_init(void)
if(config) {
return Curl_trc_opt(config);
}
-#endif
+#endif /* DEBUGBUILD */
return CURLE_OK;
}
-#else /* !CURL_DISABLE_VERBOSE_STRINGS) */
+#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
CURLcode Curl_trc_init(void)
{
return CURLE_OK;
}
-#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
-void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
- const char *fmt, ...)
-{
- (void)data;
- (void)cf;
- (void)fmt;
-}
-#endif
-
-#endif /* !DEBUGBUILD */
+#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
diff --git a/lib/curl_trc.h b/lib/curl_trc.h
index 84b5471d8..3a5387a27 100644
--- a/lib/curl_trc.h
+++ b/lib/curl_trc.h
@@ -55,66 +55,22 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size);
/**
- * Output an informational message when transfer's verbose logging is enabled.
- */
-void Curl_infof(struct Curl_easy *data,
-#if defined(__GNUC__) && !defined(printf) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
- !defined(__MINGW32__)
- const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-#else
- const char *fmt, ...);
-#endif
-
-/**
* Output a failure message on registered callbacks for transfer.
*/
void Curl_failf(struct Curl_easy *data,
-#if defined(__GNUC__) && !defined(printf) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
- !defined(__MINGW32__)
- const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-#else
- const char *fmt, ...);
-#endif
+ const char *fmt, ...) CURL_PRINTF(2, 3);
#define failf Curl_failf
-/**
- * Output an informational message when both transfer's verbose logging
- * and connection filters verbose logging are enabled.
- */
-void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
-#if defined(__GNUC__) && !defined(printf) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
- !defined(__MINGW32__)
- const char *fmt, ...)
- __attribute__((format(printf, 3, 4)));
-#else
- const char *fmt, ...);
-#endif
-
#define CURL_LOG_LVL_NONE 0
#define CURL_LOG_LVL_INFO 1
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
-/* informational messages enabled */
-
-#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
-#define Curl_trc_cf_is_verbose(cf, data) \
- ((data) && (data)->set.verbose && \
- (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
-
-/* explainer: we have some mix configuration and werror settings
- * that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
- * on gnuc and some other compiler. Need to treat carefully.
- */
-#if defined(HAVE_VARIADIC_MACROS_C99) && \
- defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define CURL_HAVE_C99
+#endif
+#ifdef CURL_HAVE_C99
#define infof(data, ...) \
do { if(Curl_trc_is_verbose(data)) \
Curl_infof(data, __VA_ARGS__); } while(0)
@@ -122,29 +78,50 @@ void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
do { if(Curl_trc_cf_is_verbose(cf, data)) \
Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
-#else /* no variadic macro args */
+#else
#define infof Curl_infof
#define CURL_TRC_CF Curl_trc_cf_infof
-#endif /* variadic macro args */
+#endif
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+/* informational messages enabled */
+
+#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
+#define Curl_trc_cf_is_verbose(cf, data) \
+ ((data) && (data)->set.verbose && \
+ (cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
+
+/**
+ * Output an informational message when transfer's verbose logging is enabled.
+ */
+void Curl_infof(struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(2, 3);
+
+/**
+ * Output an informational message when both transfer's verbose logging
+ * and connection filters verbose logging are enabled.
+ */
+void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
+ const char *fmt, ...) CURL_PRINTF(3, 4);
-#else /* !CURL_DISABLE_VERBOSE_STRINGS */
+#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* All informational messages are not compiled in for size savings */
#define Curl_trc_is_verbose(d) ((void)(d), FALSE)
#define Curl_trc_cf_is_verbose(x,y) ((void)(x), (void)(y), FALSE)
-#if defined(HAVE_VARIADIC_MACROS_C99)
-#define infof(...) Curl_nop_stmt
-#define CURL_TRC_CF(...) Curl_nop_stmt
-#define Curl_trc_cf_infof(...) Curl_nop_stmt
-#elif defined(HAVE_VARIADIC_MACROS_GCC)
-#define infof(x...) Curl_nop_stmt
-#define CURL_TRC_CF(x...) Curl_nop_stmt
-#define Curl_trc_cf_infof(x...) Curl_nop_stmt
-#else
-#error "missing VARIADIC macro define, fix and rebuild!"
-#endif
+static void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
+{
+ (void)data; (void)fmt;
+}
+
+static void Curl_trc_cf_infof(struct Curl_easy *data,
+ struct Curl_cfilter *cf,
+ const char *fmt, ...)
+{
+ (void)data; (void)cf; (void)fmt;
+}
-#endif /* CURL_DISABLE_VERBOSE_STRINGS */
+#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
#endif /* HEADER_CURL_TRC_H */
diff --git a/lib/dict.c b/lib/dict.c
index 3172b3829..323984822 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -89,7 +89,7 @@ const struct Curl_handler Curl_handler_dict = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_DICT, /* defport */
@@ -123,6 +123,9 @@ static char *unescape_word(const char *input)
/* sendf() sends formatted data to the server */
static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
+ const char *fmt, ...) CURL_PRINTF(3, 4);
+
+static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
const char *fmt, ...)
{
ssize_t bytes_written;
diff --git a/lib/doh.c b/lib/doh.c
index bb0c89ec6..ef32d507d 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -218,7 +218,6 @@ static CURLcode dohprobe(struct Curl_easy *data,
struct curl_slist *headers)
{
struct Curl_easy *doh = NULL;
- char *nurl = NULL;
CURLcode result = CURLE_OK;
timediff_t timeout_ms;
DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
@@ -242,7 +241,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
struct dynbuf *resp = &p->serverdoh;
- doh->internal = true;
+ doh->state.internal = true;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
@@ -252,6 +251,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
#ifdef USE_HTTP2
ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+ ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L);
#endif
#ifndef CURLDEBUG
/* enforce HTTPS if not debug */
@@ -339,9 +339,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
doh->set.dohfor = data; /* identify for which transfer this is done */
p->easy = doh;
- /* DoH private_data must be null because the user must have a way to
- distinguish their transfer's handle from DoH handles in user
- callbacks (ie SSL CTX callback). */
+ /* DoH handles must not inherit private_data. The handles may be passed to
+ the user via callbacks and the user will be able to identify them as
+ internal handles because private data is not set. The user can then set
+ private_data via CURLOPT_PRIVATE if they so choose. */
DEBUGASSERT(!doh->set.private_data);
if(curl_multi_add_handle(multi, doh))
@@ -349,11 +350,9 @@ static CURLcode dohprobe(struct Curl_easy *data,
}
else
goto error;
- free(nurl);
return CURLE_OK;
error:
- free(nurl);
Curl_close(&doh);
return result;
}
@@ -372,7 +371,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
int slot;
struct dohdata *dohp;
struct connectdata *conn = data->conn;
- *waitp = TRUE; /* this never returns synchronously */
+ *waitp = FALSE;
(void)hostname;
(void)port;
@@ -380,7 +379,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
DEBUGASSERT(conn);
/* start clean, consider allocating this struct on demand */
- dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
+ dohp = data->req.doh = calloc(1, sizeof(struct dohdata));
if(!dohp)
return NULL;
@@ -412,12 +411,14 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
dohp->pending++;
}
#endif
+ *waitp = TRUE; /* this never returns synchronously */
return NULL;
error:
curl_slist_free_all(dohp->headers);
data->req.doh->headers = NULL;
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
+ (void)curl_multi_remove_handle(data->multi, dohp->probe[slot].easy);
Curl_close(&dohp->probe[slot].easy);
}
Curl_safefree(data->req.doh);
@@ -443,7 +444,7 @@ static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
return DOH_DNS_BAD_LABEL;
if(dohlen < (*indexp + 1 + length))
return DOH_DNS_OUT_OF_RANGE;
- *indexp += 1 + length;
+ *indexp += (unsigned int)(1 + length);
} while(length);
return DOH_OK;
}
@@ -455,14 +456,15 @@ static unsigned short get16bit(const unsigned char *doh, int index)
static unsigned int get32bit(const unsigned char *doh, int index)
{
- /* make clang and gcc optimize this to bswap by incrementing
- the pointer first. */
- doh += index;
-
- /* avoid undefined behavior by casting to unsigned before shifting
- 24 bits, possibly into the sign bit. codegen is same, but
- ub sanitizer won't be upset */
- return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
+ /* make clang and gcc optimize this to bswap by incrementing
+ the pointer first. */
+ doh += index;
+
+ /* avoid undefined behavior by casting to unsigned before shifting
+ 24 bits, possibly into the sign bit. codegen is same, but
+ ub sanitizer won't be upset */
+ return ((unsigned)doh[0] << 24) | ((unsigned)doh[1] << 16) |
+ ((unsigned)doh[2] << 8) | doh[3];
}
static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
@@ -787,8 +789,8 @@ static void showdoh(struct Curl_easy *data,
* must be an associated call later to Curl_freeaddrinfo().
*/
-static struct Curl_addrinfo *
-doh2ai(const struct dohentry *de, const char *hostname, int port)
+static CURLcode doh2ai(const struct dohentry *de, const char *hostname,
+ int port, struct Curl_addrinfo **aip)
{
struct Curl_addrinfo *ai;
struct Curl_addrinfo *prevai = NULL;
@@ -801,9 +803,10 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
int i;
size_t hostlen = strlen(hostname) + 1; /* include null-terminator */
- if(!de)
- /* no input == no output! */
- return NULL;
+ DEBUGASSERT(de);
+
+ if(!de->numaddr)
+ return CURLE_COULDNT_RESOLVE_HOST;
for(i = 0; i < de->numaddr; i++) {
size_t ss_size;
@@ -876,8 +879,9 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
Curl_freeaddrinfo(firstai);
firstai = NULL;
}
+ *aip = firstai;
- return firstai;
+ return result;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -932,10 +936,12 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
p->dnstype,
&de);
Curl_dyn_free(&p->serverdoh);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(rc[slot]) {
infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
type2name(p->dnstype), dohp->host);
}
+#endif
} /* next slot */
result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
@@ -947,10 +953,10 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
infof(data, "DoH Host name: %s", dohp->host);
showdoh(data, &de);
- ai = doh2ai(&de, dohp->host, dohp->port);
- if(!ai) {
+ result = doh2ai(&de, dohp->host, dohp->port, &ai);
+ if(result) {
de_cleanup(&de);
- return CURLE_OUT_OF_MEMORY;
+ return result;
}
if(data->share)
diff --git a/lib/dynbuf.c b/lib/dynbuf.c
index 0c9c491ae..a4c599d10 100644
--- a/lib/dynbuf.c
+++ b/lib/dynbuf.c
@@ -77,10 +77,11 @@ static CURLcode dyn_nappend(struct dynbuf *s,
DEBUGASSERT(indx < s->toobig);
DEBUGASSERT(!s->leng || s->bufr);
DEBUGASSERT(a <= s->toobig);
+ DEBUGASSERT(!len || mem);
if(fit > s->toobig) {
Curl_dyn_free(s);
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_TOO_LARGE;
}
else if(!a) {
DEBUGASSERT(!indx);
@@ -174,10 +175,12 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
*/
CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
{
- size_t n = strlen(str);
+ size_t n;
+ DEBUGASSERT(str);
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
+ n = strlen(str);
return dyn_nappend(s, (unsigned char *)str, n);
}
@@ -191,10 +194,14 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
DEBUGASSERT(!s->leng || s->bufr);
+ DEBUGASSERT(fmt);
rc = Curl_dyn_vprintf(s, fmt, ap);
if(!rc)
return CURLE_OK;
+ else if(rc == MERR_TOO_LARGE)
+ return CURLE_TOO_LARGE;
+ return CURLE_OUT_OF_MEMORY;
#else
char *str;
str = vaprintf(fmt, ap); /* this allocs a new string to append */
@@ -206,8 +213,8 @@ CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
}
/* If we failed, we cleanup the whole buffer and return error */
Curl_dyn_free(s);
+ return CURLE_OK;
#endif
- return CURLE_OUT_OF_MEMORY;
}
/*
diff --git a/lib/dynbuf.h b/lib/dynbuf.h
index 31a913019..7dbaab886 100644
--- a/lib/dynbuf.h
+++ b/lib/dynbuf.h
@@ -61,9 +61,9 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
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;
+ WARN_UNUSED_RESULT CURL_PRINTF(2, 3);
CURLcode Curl_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap)
- WARN_UNUSED_RESULT;
+ WARN_UNUSED_RESULT CURL_PRINTF(2, 0);
void Curl_dyn_reset(struct dynbuf *s);
CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
CURLcode Curl_dyn_setlen(struct dynbuf *s, size_t set);
diff --git a/lib/dynhds.c b/lib/dynhds.c
index 979b3e825..d7548959b 100644
--- a/lib/dynhds.c
+++ b/lib/dynhds.c
@@ -27,6 +27,10 @@
#include "strcase.h"
/* The last 3 #include files should be in this order */
+#ifdef USE_NGHTTP2
+#include <stdint.h>
+#include <nghttp2/nghttp2.h>
+#endif /* USE_NGHTTP2 */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
@@ -365,3 +369,28 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
return result;
}
+#ifdef USE_NGHTTP2
+
+nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount)
+{
+ nghttp2_nv *nva = calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len);
+ size_t i;
+
+ *pcount = 0;
+ if(!nva)
+ return NULL;
+
+ for(i = 0; i < dynhds->hds_len; ++i) {
+ struct dynhds_entry *e = dynhds->hds[i];
+ DEBUGASSERT(e);
+ nva[i].name = (unsigned char *)e->name;
+ nva[i].namelen = e->namelen;
+ nva[i].value = (unsigned char *)e->value;
+ nva[i].valuelen = e->valuelen;
+ nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+ }
+ *pcount = dynhds->hds_len;
+ return nva;
+}
+
+#endif /* USE_NGHTTP2 */
diff --git a/lib/dynhds.h b/lib/dynhds.h
index 8a053480e..3b536000a 100644
--- a/lib/dynhds.h
+++ b/lib/dynhds.h
@@ -171,4 +171,13 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
*/
CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf);
+#ifdef USE_NGHTTP2
+
+#include <stdint.h>
+#include <nghttp2/nghttp2.h>
+
+nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount);
+
+#endif /* USE_NGHTTP2 */
+
#endif /* HEADER_CURL_DYNHDS_H */
diff --git a/lib/easy.c b/lib/easy.c
index 6b4fb8efe..067b6d7b6 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -112,7 +112,7 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
#define system_strdup strdup
#endif
-#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+#if defined(_MSC_VER) && defined(_DLL)
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
#endif
@@ -125,11 +125,11 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup;
#endif
-#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
+#if defined(_MSC_VER) && defined(_DLL)
# pragma warning(default:4232) /* MSVC extension, dllimport identity */
#endif
@@ -153,7 +153,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
Curl_crealloc = (curl_realloc_callback)realloc;
Curl_cstrdup = (curl_strdup_callback)system_strdup;
Curl_ccalloc = (curl_calloc_callback)calloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif
}
@@ -188,18 +188,10 @@ static CURLcode global_init(long flags, bool memoryfuncs)
goto fail;
}
-#if defined(USE_SSH)
if(Curl_ssh_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_ssh_init failed\n"));
goto fail;
}
-#endif
-
-#ifdef USE_WOLFSSH
- if(WS_SUCCESS != wolfSSH_Init()) {
- DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
- return CURLE_FAILED_INIT;
- }
-#endif
easy_init_flags = flags;
@@ -295,7 +287,7 @@ void curl_global_cleanup(void)
Curl_ssl_cleanup();
Curl_resolver_global_cleanup();
-#ifdef WIN32
+#ifdef _WIN32
Curl_win32_cleanup(easy_init_flags);
#endif
@@ -488,13 +480,15 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
ev->list = nxt;
free(m);
m = nxt;
- infof(easy, "socket cb: socket %d REMOVED", s);
+ infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
+ " REMOVED", s);
}
else {
/* The socket 's' is already being monitored, update the activity
mask. Convert from libcurl bitmask to the poll one. */
m->socket.events = socketcb2poll(what);
- infof(easy, "socket cb: socket %d UPDATED as %s%s", s,
+ infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
+ " UPDATED as %s%s", s,
(what&CURL_POLL_IN)?"IN":"",
(what&CURL_POLL_OUT)?"OUT":"");
}
@@ -518,7 +512,8 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
m->socket.events = socketcb2poll(what);
m->socket.revents = 0;
ev->list = m;
- infof(easy, "socket cb: socket %d ADDED as %s%s", s,
+ infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
+ " ADDED as %s%s", s,
(what&CURL_POLL_IN)?"IN":"",
(what&CURL_POLL_OUT)?"OUT":"");
}
@@ -607,8 +602,9 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
if(fds[i].revents) {
/* socket activity, tell libcurl */
int act = poll2cselect(fds[i].revents); /* convert */
- infof(multi->easyp, "call curl_multi_socket_action(socket %d)",
- fds[i].fd);
+ infof(multi->easyp,
+ "call curl_multi_socket_action(socket "
+ "%" CURL_FORMAT_SOCKET_T ")", fds[i].fd);
mcode = curl_multi_socket_action(multi, fds[i].fd, act,
&ev->running_handles);
}
@@ -692,9 +688,9 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
/* Make sure to return some kind of error if there was a multi problem */
if(mcode) {
result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
- /* The other multi errors should never happen, so return
- something suitably generic */
- CURLE_BAD_FUNCTION_ARGUMENT;
+ /* The other multi errors should never happen, so return
+ something suitably generic */
+ CURLE_BAD_FUNCTION_ARGUMENT;
}
return result;
@@ -752,7 +748,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
return CURLE_RECURSIVE_API_CALL;
/* Copy the MAXCONNECTS option to the multi handle */
- curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
+ curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects);
mcode = curl_multi_add_handle(multi, data);
if(mcode) {
@@ -845,8 +841,10 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
dst->set = src->set;
Curl_mime_initpart(&dst->set.mimepost);
- /* clear all string pointers first */
+ /* clear all dest string and blob pointers first, in case we error out
+ mid-function */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
+ memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
/* duplicate all strings */
for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
@@ -855,8 +853,6 @@ 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]);
@@ -866,10 +862,13 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* duplicate memory areas pointed to */
i = STRING_COPYPOSTFIELDS;
- if(src->set.postfieldsize && src->set.str[i]) {
- /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
- dst->set.str[i] = Curl_memdup(src->set.str[i],
- curlx_sotouz(src->set.postfieldsize));
+ if(src->set.str[i]) {
+ if(src->set.postfieldsize == -1)
+ dst->set.str[i] = strdup(src->set.str[i]);
+ else
+ /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
+ dst->set.str[i] = Curl_memdup(src->set.str[i],
+ curlx_sotouz(src->set.postfieldsize));
if(!dst->set.str[i])
return CURLE_OUT_OF_MEMORY;
/* point to the new copy */
@@ -919,18 +918,19 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
outcurl->progress.callback = data->progress.callback;
#ifndef CURL_DISABLE_COOKIES
- if(data->cookies) {
+ outcurl->state.cookielist = NULL;
+ if(data->cookies && data->state.cookie_engine) {
/* If cookies are enabled in the parent handle, we enable them
in the clone as well! */
- outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies,
+ outcurl->cookies = Curl_cookie_init(outcurl, NULL, outcurl->cookies,
data->set.cookiesession);
if(!outcurl->cookies)
goto fail;
}
- if(data->set.cookielist) {
- outcurl->set.cookielist = Curl_slist_duplicate(data->set.cookielist);
- if(!outcurl->set.cookielist)
+ if(data->state.cookielist) {
+ outcurl->state.cookielist = Curl_slist_duplicate(data->state.cookielist);
+ if(!outcurl->state.cookielist)
goto fail;
}
#endif
@@ -976,11 +976,14 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
(void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
}
#endif
+
+#ifdef CURLRES_ASYNCH
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(outcurl,
&outcurl->state.async.resolver,
data->state.async.resolver))
goto fail;
+#endif
#ifdef USE_ARES
{
@@ -1016,13 +1019,10 @@ fail:
if(outcurl) {
#ifndef CURL_DISABLE_COOKIES
- curl_slist_free_all(outcurl->set.cookielist);
- outcurl->set.cookielist = NULL;
+ free(outcurl->cookies);
#endif
- Curl_safefree(outcurl->state.buffer);
+ free(outcurl->state.buffer);
Curl_dyn_free(&outcurl->state.headerb);
- Curl_safefree(outcurl->state.url);
- Curl_safefree(outcurl->state.referer);
Curl_altsvc_cleanup(&outcurl->asi);
Curl_hsts_cleanup(&outcurl->hsts);
Curl_freeset(outcurl);
@@ -1145,7 +1145,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
if(!data->state.tempcount)
/* if not pausing again, force a recv/send check of this connection as
the data might've been read off the socket already */
- data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
+ data->state.select_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
if(data->multi) {
if(Curl_update_timer(data->multi))
return CURLE_ABORTED_BY_CALLBACK;
diff --git a/lib/easy_lock.h b/lib/easy_lock.h
index d3fffd0d2..4f6764d42 100644
--- a/lib/easy_lock.h
+++ b/lib/easy_lock.h
@@ -93,6 +93,15 @@ static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
atomic_store_explicit(lock, false, memory_order_release);
}
+#elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+
+#include <pthread.h>
+
+#define curl_simple_lock pthread_mutex_t
+#define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
+#define curl_simple_lock_lock(m) pthread_mutex_lock(m)
+#define curl_simple_lock_unlock(m) pthread_mutex_unlock(m)
+
#else
#undef GLOBAL_INIT_IS_THREADSAFE
diff --git a/lib/easyoptions.c b/lib/easyoptions.c
index e69c658b0..da4c6111a 100644
--- a/lib/easyoptions.c
+++ b/lib/easyoptions.c
@@ -274,6 +274,8 @@ struct curl_easyoption Curl_easyopts[] = {
{"SEEKFUNCTION", CURLOPT_SEEKFUNCTION, CURLOT_FUNCTION, 0},
{"SERVER_RESPONSE_TIMEOUT", CURLOPT_SERVER_RESPONSE_TIMEOUT,
CURLOT_LONG, 0},
+ {"SERVER_RESPONSE_TIMEOUT_MS", CURLOPT_SERVER_RESPONSE_TIMEOUT_MS,
+ CURLOT_LONG, 0},
{"SERVICE_NAME", CURLOPT_SERVICE_NAME, CURLOT_STRING, 0},
{"SHARE", CURLOPT_SHARE, CURLOT_OBJECT, 0},
{"SOCKOPTDATA", CURLOPT_SOCKOPTDATA, CURLOT_CBPTR, 0},
@@ -373,6 +375,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != (323 + 1));
+ return ((CURLOPT_LASTENTRY%10000) != (324 + 1));
}
#endif
diff --git a/lib/file.c b/lib/file.c
index ffa9fb76d..b7ce3a8ed 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -69,7 +69,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
+#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__)
#define DOS_FILESYSTEM 1
#elif defined(__amigaos4__)
#define AMIGA_FILESYSTEM 1
@@ -113,7 +113,7 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
file_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
0, /* defport */
@@ -290,16 +290,15 @@ static CURLcode file_upload(struct Curl_easy *data)
int fd;
int mode;
CURLcode result = CURLE_OK;
- char *buf = data->state.buffer;
+ char buffer[8*1024], *uphere_save;
curl_off_t bytecount = 0;
struct_stat file_stat;
- const char *buf2;
+ const char *sendbuf;
/*
* Since FILE: doesn't do the full init, we need to provide some extra
* assignments here.
*/
- data->req.upload_fromhere = buf;
if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
@@ -338,11 +337,15 @@ static CURLcode file_upload(struct Curl_easy *data)
data->state.resume_from = (curl_off_t)file_stat.st_size;
}
+ /* Yikes! Curl_fillreadbuffer uses data->req.upload_fromhere to READ
+ * client data to! Please, someone fix... */
+ uphere_save = data->req.upload_fromhere;
while(!result) {
size_t nread;
ssize_t nwrite;
size_t readcount;
- result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount);
+ data->req.upload_fromhere = buffer;
+ result = Curl_fillreadbuffer(data, sizeof(buffer), &readcount);
if(result)
break;
@@ -356,19 +359,19 @@ static CURLcode file_upload(struct Curl_easy *data)
if((curl_off_t)nread <= data->state.resume_from) {
data->state.resume_from -= nread;
nread = 0;
- buf2 = buf;
+ sendbuf = buffer;
}
else {
- buf2 = buf + data->state.resume_from;
+ sendbuf = buffer + data->state.resume_from;
nread -= (size_t)data->state.resume_from;
data->state.resume_from = 0;
}
}
else
- buf2 = buf;
+ sendbuf = buffer;
/* write the data to the target */
- nwrite = write(fd, buf2, nread);
+ nwrite = write(fd, sendbuf, nread);
if((size_t)nwrite != nread) {
result = CURLE_SEND_ERROR;
break;
@@ -387,6 +390,7 @@ static CURLcode file_upload(struct Curl_easy *data)
result = CURLE_ABORTED_BY_CALLBACK;
close(fd);
+ data->req.upload_fromhere = uphere_save;
return result;
}
@@ -413,15 +417,11 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
curl_off_t expected_size = -1;
bool size_known;
bool fstated = FALSE;
- char *buf = data->state.buffer;
- curl_off_t bytecount = 0;
int fd;
struct FILEPROTO *file;
*done = TRUE; /* unconditionally */
- Curl_pgrsStartNow(data);
-
if(data->state.upload)
return file_upload(data);
@@ -544,34 +544,30 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
while(!result) {
+ char tmpbuf[8*1024];
ssize_t nread;
/* Don't fill a whole buffer if we want less than all data */
size_t bytestoread;
if(size_known) {
- bytestoread = (expected_size < data->set.buffer_size) ?
- curlx_sotouz(expected_size) : (size_t)data->set.buffer_size;
+ bytestoread = (expected_size < (curl_off_t)(sizeof(tmpbuf)-1)) ?
+ curlx_sotouz(expected_size) : (sizeof(tmpbuf)-1);
}
else
- bytestoread = data->set.buffer_size-1;
+ bytestoread = sizeof(tmpbuf)-1;
- nread = read(fd, buf, bytestoread);
+ nread = read(fd, tmpbuf, bytestoread);
if(nread > 0)
- buf[nread] = 0;
+ tmpbuf[nread] = 0;
if(nread <= 0 || (size_known && (expected_size == 0)))
break;
- bytecount += nread;
if(size_known)
expected_size -= nread;
- result = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
- if(result)
- return result;
-
- result = Curl_pgrsSetDownloadCounter(data, bytecount);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, tmpbuf, nread);
if(result)
return result;
diff --git a/lib/fopen.c b/lib/fopen.c
index 75b8a7aa5..851279fe1 100644
--- a/lib/fopen.c
+++ b/lib/fopen.c
@@ -40,6 +40,51 @@
#include "memdebug.h"
/*
+ The dirslash() function breaks a null-terminated pathname string into
+ directory and filename components then returns the directory component up
+ to, *AND INCLUDING*, a final '/'. If there is no directory in the path,
+ this instead returns a "" string.
+
+ This function returns a pointer to malloc'ed memory.
+
+ The input path to this function is expected to have a file name part.
+*/
+
+#ifdef _WIN32
+#define PATHSEP "\\"
+#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
+#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
+#define PATHSEP "\\"
+#define IS_SEP(x) ((x) == '\\')
+#else
+#define PATHSEP "/"
+#define IS_SEP(x) ((x) == '/')
+#endif
+
+static char *dirslash(const char *path)
+{
+ size_t n;
+ struct dynbuf out;
+ DEBUGASSERT(path);
+ Curl_dyn_init(&out, CURL_MAX_INPUT_LENGTH);
+ n = strlen(path);
+ if(n) {
+ /* find the rightmost path separator, if any */
+ while(n && !IS_SEP(path[n-1]))
+ --n;
+ /* skip over all the path separators, if any */
+ while(n && IS_SEP(path[n-1]))
+ --n;
+ }
+ if(Curl_dyn_addn(&out, path, n))
+ return NULL;
+ /* if there was a directory, append a single trailing slash */
+ if(n && Curl_dyn_addn(&out, PATHSEP, 1))
+ return NULL;
+ return Curl_dyn_ptr(&out);
+}
+
+/*
* Curl_fopen() opens a file for writing with a temp name, to be renamed
* to the final name when completed. If there is an existing file using this
* name at the time of the open, this function will clone the mode from that
@@ -50,47 +95,44 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
FILE **fh, char **tempname)
{
CURLcode result = CURLE_WRITE_ERROR;
- unsigned char randsuffix[9];
+ unsigned char randbuf[41];
char *tempstore = NULL;
struct_stat sb;
int fd = -1;
+ char *dir = NULL;
*tempname = NULL;
*fh = fopen(filename, FOPEN_WRITETEXT);
if(!*fh)
goto fail;
- if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode))
+ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) {
return CURLE_OK;
+ }
fclose(*fh);
*fh = NULL;
- result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix));
+ result = Curl_rand_alnum(data, randbuf, sizeof(randbuf));
if(result)
goto fail;
- tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
+ dir = dirslash(filename);
+ if(dir) {
+ /* The temp file name should not end up too long for the target file
+ system */
+ tempstore = aprintf("%s%s.tmp", dir, randbuf);
+ free(dir);
+ }
+
if(!tempstore) {
result = CURLE_OUT_OF_MEMORY;
goto fail;
}
result = CURLE_WRITE_ERROR;
- fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600|sb.st_mode);
if(fd == -1)
goto fail;
-#ifdef HAVE_FCHMOD
- {
- struct_stat nsb;
- if((fstat(fd, &nsb) != -1) &&
- (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
- /* if the user and group are the same, clone the original mode */
- if(fchmod(fd, (mode_t)sb.st_mode) == -1)
- goto fail;
- }
- }
-#endif
-
*fh = fdopen(fd, FOPEN_WRITETEXT);
if(!*fh)
goto fail;
@@ -105,7 +147,6 @@ fail:
}
free(tempstore);
-
return result;
}
diff --git a/lib/formdata.c b/lib/formdata.c
index e40c4bcb0..d6a1697aa 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -277,7 +277,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
case CURLFORM_PTRNAME:
current_form->flags |= HTTPPOST_PTRNAME; /* fall through */
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURLFORM_COPYNAME:
if(current_form->name)
return_value = CURL_FORMADD_OPTION_TWICE;
@@ -303,7 +303,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
*/
case CURLFORM_PTRCONTENTS:
current_form->flags |= HTTPPOST_PTRCONTENTS;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURLFORM_COPYCONTENTS:
if(current_form->value)
return_value = CURL_FORMADD_OPTION_TWICE;
@@ -603,9 +603,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
app passed in a bad combo, so we better check for that first. */
if(form->name) {
/* copy name (without strdup; possibly not null-terminated) */
- form->name = Curl_memdup(form->name, form->namelength?
- form->namelength:
- strlen(form->name) + 1);
+ form->name = Curl_memdup0(form->name, form->namelength?
+ form->namelength:
+ strlen(form->name));
}
if(!form->name) {
return_value = CURL_FORMADD_MEMORY;
@@ -779,11 +779,9 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
if(!name || !len)
return curl_mime_name(part, name);
- zname = malloc(len + 1);
+ zname = Curl_memdup0(name, len);
if(!zname)
return CURLE_OUT_OF_MEMORY;
- memcpy(zname, name, len);
- zname[len] = '\0';
res = curl_mime_name(part, zname);
free(zname);
return res;
@@ -792,7 +790,7 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
/* wrap call to fseeko so it matches the calling convention of callback */
static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
{
-#if defined(HAVE_FSEEKO)
+#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO)
return fseeko(stream, (off_t)offset, whence);
#elif defined(HAVE__FSEEKI64)
return _fseeki64(stream, (__int64)offset, whence);
diff --git a/lib/ftp.c b/lib/ftp.c
index 518c92332..f62108234 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -72,6 +72,7 @@
#include "warnless.h"
#include "http_proxy.h"
#include "socks.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -167,7 +168,7 @@ const struct Curl_handler Curl_handler_ftp = {
ftp_domore_getsock, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ftp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_FTP, /* defport */
@@ -198,7 +199,7 @@ const struct Curl_handler Curl_handler_ftps = {
ftp_domore_getsock, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ftp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_FTPS, /* defport */
@@ -362,10 +363,11 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
- int result;
+ int socketstate = 0;
timediff_t timeout_ms;
ssize_t nread;
int ftpcode;
+ bool response = FALSE;
*received = FALSE;
@@ -378,17 +380,21 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
}
/* First check whether there is a cached response from server */
- if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
+ if(Curl_dyn_len(&pp->recvbuf) && (*Curl_dyn_ptr(&pp->recvbuf) > '3')) {
/* Data connection could not be established, let's return */
infof(data, "There is negative response in cache while serv connect");
(void)Curl_GetFTPResponse(data, &nread, &ftpcode);
return CURLE_FTP_ACCEPT_FAILED;
}
- result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
+ if(pp->overflow)
+ /* there is pending control data still in the buffer to read */
+ response = TRUE;
+ else
+ socketstate = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
/* see if the connection request is already here */
- switch(result) {
+ switch(socketstate) {
case -1: /* error */
/* let's die here */
failf(data, "Error while waiting for server connect");
@@ -396,23 +402,23 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
case 0: /* Server connect is not received yet */
break; /* loop */
default:
-
- if(result & CURL_CSELECT_IN2) {
+ if(socketstate & CURL_CSELECT_IN2) {
infof(data, "Ready to accept data connection from server");
*received = TRUE;
}
- else if(result & CURL_CSELECT_IN) {
- infof(data, "Ctrl conn has data while waiting for data conn");
- (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
-
- if(ftpcode/100 > 3)
- return CURLE_FTP_ACCEPT_FAILED;
+ else if(socketstate & CURL_CSELECT_IN)
+ response = TRUE;
+ break;
+ }
+ if(response) {
+ infof(data, "Ctrl conn has data while waiting for data conn");
+ (void)Curl_GetFTPResponse(data, &nread, &ftpcode);
- return CURLE_WEIRD_SERVER_REPLY;
- }
+ if(ftpcode/100 > 3)
+ return CURLE_FTP_ACCEPT_FAILED;
- break;
- } /* switch() */
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
return CURLE_OK;
}
@@ -553,7 +559,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data,
#ifdef HAVE_GSSAPI
{
struct connectdata *conn = data->conn;
- char * const buf = data->state.buffer;
+ char * const buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
/* handle the security-oriented responses 6xx ***/
switch(code) {
@@ -659,7 +665,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
*
*/
- if(pp->cache && (cache_skip < 2)) {
+ if(Curl_dyn_len(&pp->recvbuf) && (cache_skip < 2)) {
/*
* There's a cache left since before. We then skipping the wait for
* socket action, unless this is the same cache like the previous round
@@ -687,7 +693,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
if(result)
break;
- if(!nread && pp->cache)
+ if(!nread && Curl_dyn_len(&pp->recvbuf))
/* bump cache skip counter as on repeated skips we must wait for more
data */
cache_skip++;
@@ -819,7 +825,7 @@ static int ftp_domore_getsock(struct Curl_easy *data,
DEBUGF(infof(data, "ftp_domore_getsock()"));
if(conn->cfilter[SECONDARYSOCKET]
&& !Curl_conn_is_connected(conn, SECONDARYSOCKET))
- return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks);
+ return 0;
if(FTP_STOP == ftpc->state) {
int bits = GETSOCK_READSOCK(0);
@@ -926,6 +932,8 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
bool possibly_non_local = TRUE;
char buffer[STRERROR_LEN];
char *addr = NULL;
+ size_t addrlen = 0;
+ char ipstr[50];
/* Step 1, figure out what is requested,
* accepted format :
@@ -934,32 +942,17 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(data->set.str[STRING_FTPPORT] &&
(strlen(data->set.str[STRING_FTPPORT]) > 1)) {
-
-#ifdef ENABLE_IPV6
- size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
- INET6_ADDRSTRLEN : strlen(string_ftpport);
-#else
- size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
- INET_ADDRSTRLEN : strlen(string_ftpport);
-#endif
- char *ip_start = string_ftpport;
char *ip_end = NULL;
- char *port_start = NULL;
- char *port_sep = NULL;
-
- addr = calloc(addrlen + 1, 1);
- if(!addr) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
#ifdef ENABLE_IPV6
if(*string_ftpport == '[') {
/* [ipv6]:port(-range) */
- ip_start = string_ftpport + 1;
- ip_end = strchr(string_ftpport, ']');
- if(ip_end)
- strncpy(addr, ip_start, ip_end - ip_start);
+ char *ip_start = string_ftpport + 1;
+ ip_end = strchr(ip_start, ']');
+ if(ip_end) {
+ addrlen = ip_end - ip_start;
+ addr = ip_start;
+ }
}
else
#endif
@@ -969,28 +962,27 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
}
else {
ip_end = strchr(string_ftpport, ':');
+ addr = string_ftpport;
if(ip_end) {
/* either ipv6 or (ipv4|domain|interface):port(-range) */
+ addrlen = ip_end - string_ftpport;
#ifdef ENABLE_IPV6
if(Curl_inet_pton(AF_INET6, string_ftpport, &sa6->sin6_addr) == 1) {
/* ipv6 */
port_min = port_max = 0;
- strcpy(addr, string_ftpport);
ip_end = NULL; /* this got no port ! */
}
- else
#endif
- /* (ipv4|domain|interface):port(-range) */
- strncpy(addr, string_ftpport, ip_end - ip_start);
}
else
/* ipv4|interface */
- strcpy(addr, string_ftpport);
+ addrlen = strlen(string_ftpport);
}
/* parse the port */
if(ip_end) {
- port_start = strchr(ip_end, ':');
+ char *port_sep = NULL;
+ char *port_start = strchr(ip_end, ':');
if(port_start) {
port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
port_sep = strchr(port_start, '-');
@@ -1011,22 +1003,29 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(port_min > port_max)
port_min = port_max = 0;
- if(*addr != '\0') {
+ if(addrlen) {
+ DEBUGASSERT(addr);
+ if(addrlen >= sizeof(ipstr))
+ goto out;
+ memcpy(ipstr, addr, addrlen);
+ ipstr[addrlen] = 0;
+
/* attempt to get the address of the given interface name */
switch(Curl_if2ip(conn->remote_addr->family,
#ifdef ENABLE_IPV6
Curl_ipv6_scope(&conn->remote_addr->sa_addr),
conn->scope_id,
#endif
- addr, hbuf, sizeof(hbuf))) {
+ ipstr, hbuf, sizeof(hbuf))) {
case IF2IP_NOT_FOUND:
/* not an interface, use the given string as host name instead */
- host = addr;
+ host = ipstr;
break;
case IF2IP_AF_NOT_SUPPORTED:
goto out;
case IF2IP_FOUND:
host = hbuf; /* use the hbuf for host name */
+ break;
}
}
else
@@ -1266,7 +1265,6 @@ out:
}
if(portsock != CURL_SOCKET_BAD)
Curl_socket_close(data, conn, portsock);
- free(addr);
return result;
}
@@ -1589,13 +1587,14 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
}
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
+ char scratch[4*1024];
size_t readthisamountnow =
- (data->state.resume_from - passed > data->set.buffer_size) ?
- (size_t)data->set.buffer_size :
+ (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ?
+ sizeof(scratch) :
curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
- data->state.fread_func(data->state.buffer, 1, readthisamountnow,
+ data->state.fread_func(scratch, 1, readthisamountnow,
data->state.in);
passed += actuallyread;
@@ -1828,7 +1827,9 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
struct Curl_dns_entry *addr = NULL;
enum resolve_t rc;
unsigned short connectport; /* the local port connect() should use! */
- char *str = &data->state.buffer[4]; /* start on the first letter */
+ struct pingpong *pp = &ftpc->pp;
+ char *str =
+ Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first letter */
/* if we come here again, make sure the former name is cleared */
Curl_safefree(ftpc->newhost);
@@ -2106,8 +2107,9 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
last .sss part is optional and means fractions of a second */
int year, month, day, hour, minute, second;
- if(ftp_213_date(&data->state.buffer[4],
- &year, &month, &day, &hour, &minute, &second)) {
+ struct pingpong *pp = &ftpc->pp;
+ char *resp = Curl_dyn_ptr(&pp->recvbuf) + 4;
+ if(ftp_213_date(resp, &year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
char timebuf[24];
msnprintf(timebuf, sizeof(timebuf),
@@ -2318,7 +2320,8 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
curl_off_t filesize = -1;
- char *buf = data->state.buffer;
+ char *buf = Curl_dyn_ptr(&data->conn->proto.ftpc.pp.recvbuf);
+ size_t len = data->conn->proto.ftpc.pp.nfinal;
/* get the size from the ascii string: */
if(ftpcode == 213) {
@@ -2326,13 +2329,13 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
for all the digits at the end of the response and parse only those as a
number. */
char *start = &buf[4];
- char *fdigit = strchr(start, '\r');
+ char *fdigit = memchr(start, '\r', len);
if(fdigit) {
- do
+ fdigit--;
+ if(*fdigit == '\n')
+ fdigit--;
+ while(ISDIGIT(fdigit[-1]) && (fdigit > start))
fdigit--;
- while(ISDIGIT(*fdigit) && (fdigit > start));
- if(!ISDIGIT(*fdigit))
- fdigit++;
}
else
fdigit = start;
@@ -2501,7 +2504,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
*
* Example D above makes this parsing a little tricky */
char *bytes;
- char *buf = data->state.buffer;
+ char *buf = Curl_dyn_ptr(&conn->proto.ftpc.pp.recvbuf);
bytes = strstr(buf, " bytes");
if(bytes) {
long in = (long)(--bytes-buf);
@@ -2770,7 +2773,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
case FTP_AUTH:
/* we have gotten the response to a previous AUTH command */
- if(pp->cache_size)
+ if(pp->overflow)
return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
/* RFC2228 (page 5) says:
@@ -2868,14 +2871,11 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
case FTP_PWD:
if(ftpcode == 257) {
- char *ptr = &data->state.buffer[4]; /* start on the first letter */
- const size_t buf_size = data->set.buffer_size;
- char *dir;
+ char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
+ letter */
bool entry_extracted = FALSE;
-
- dir = malloc(nread + 1);
- if(!dir)
- return CURLE_OUT_OF_MEMORY;
+ struct dynbuf out;
+ Curl_dyn_init(&out, 1000);
/* Reply format is like
257<space>[rubbish]"<directory-name>"<space><commentary> and the
@@ -2887,33 +2887,30 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
*/
/* scan for the first double-quote for non-standard responses */
- while(ptr < &data->state.buffer[buf_size]
- && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
+ while(*ptr != '\n' && *ptr != '\0' && *ptr != '"')
ptr++;
if('\"' == *ptr) {
/* it started good */
- char *store;
- ptr++;
- for(store = dir; *ptr;) {
+ for(ptr++; *ptr; ptr++) {
if('\"' == *ptr) {
if('\"' == ptr[1]) {
/* "quote-doubling" */
- *store = ptr[1];
+ result = Curl_dyn_addn(&out, &ptr[1], 1);
ptr++;
}
else {
/* end of path */
- entry_extracted = TRUE;
+ if(Curl_dyn_len(&out))
+ entry_extracted = TRUE;
break; /* get out of this loop */
}
}
else
- *store = *ptr;
- store++;
- ptr++;
+ result = Curl_dyn_addn(&out, ptr, 1);
+ if(result)
+ return result;
}
- *store = '\0'; /* null-terminate */
}
if(entry_extracted) {
/* If the path name does not look like an absolute path (i.e.: it
@@ -2927,6 +2924,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
The method used here is to check the server OS: we do it only
if the path name looks strange to minimize overhead on other
systems. */
+ char *dir = Curl_dyn_ptr(&out);
if(!ftpc->server_os && dir[0] != '/') {
result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST");
@@ -2951,7 +2949,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
}
else {
/* couldn't get the path */
- free(dir);
+ Curl_dyn_free(&out);
infof(data, "Failed to figure out path");
}
}
@@ -2961,25 +2959,23 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
case FTP_SYST:
if(ftpcode == 215) {
- char *ptr = &data->state.buffer[4]; /* start on the first letter */
+ char *ptr = Curl_dyn_ptr(&pp->recvbuf) + 4; /* start on the first
+ letter */
char *os;
- char *store;
-
- os = malloc(nread + 1);
- if(!os)
- return CURLE_OUT_OF_MEMORY;
+ char *start;
/* Reply format is like
215<space><OS-name><space><commentary>
*/
while(*ptr == ' ')
ptr++;
- for(store = os; *ptr && *ptr != ' ';)
- *store++ = *ptr++;
- *store = '\0'; /* null-terminate */
+ for(start = ptr; *ptr && *ptr != ' '; ptr++)
+ ;
+ os = Curl_memdup0(start, ptr - start);
+ if(!os)
+ return CURLE_OUT_OF_MEMORY;
/* Check for special servers here. */
-
if(strcasecompare(os, "OS/400")) {
/* Force OS400 name format 1. */
result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1");
@@ -3131,7 +3127,6 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
break;
case FTP_QUIT:
- /* fallthrough, just stop! */
default:
/* internal error */
ftp_state(data, FTP_STOP);
@@ -3206,8 +3201,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
conn->bits.ftp_use_control_ssl = TRUE;
}
- Curl_pp_setup(pp); /* once per transfer */
- Curl_pp_init(data, pp); /* init the generic pingpong data */
+ Curl_pp_init(pp); /* once per transfer */
/* When we connect, we start in the state where we await the 220
response */
@@ -3258,14 +3252,13 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
case CURLE_REMOTE_FILE_NOT_FOUND:
case CURLE_WRITE_ERROR:
/* the connection stays alive fine even though this happened */
- /* fall-through */
case CURLE_OK: /* doesn't affect the control connection's status */
if(!premature)
break;
/* until we cope better with prematurely ended requests, let them
* fallback as if in complete failure */
- /* FALLTHROUGH */
+ FALLTHROUGH();
default: /* by default, an error means the control connection is
wedged and should not be used anymore */
ftpc->ctl_valid = FALSE;
@@ -4177,13 +4170,12 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
}
- ftpc->dirs[0] = calloc(1, dirlen + 1);
+ ftpc->dirs[0] = Curl_memdup0(rawPath, dirlen);
if(!ftpc->dirs[0]) {
free(rawPath);
return CURLE_OUT_OF_MEMORY;
}
- strncpy(ftpc->dirs[0], rawPath, dirlen);
ftpc->dirdepth = 1; /* we consider it to be a single dir */
fileName = slashPos + 1; /* rest is file name */
}
@@ -4222,12 +4214,11 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
CWD requires a parameter and a non-existent parameter a) doesn't
work on many servers and b) has no effect on the others. */
if(compLen > 0) {
- char *comp = calloc(1, compLen + 1);
+ char *comp = Curl_memdup0(curPos, compLen);
if(!comp) {
free(rawPath);
return CURLE_OUT_OF_MEMORY;
}
- strncpy(comp, curPos, compLen);
ftpc->dirs[ftpc->dirdepth++] = comp;
}
curPos = slashPos + 1;
@@ -4379,7 +4370,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
- ftp = calloc(sizeof(struct FTP), 1);
+ ftp = calloc(1, sizeof(struct FTP));
if(!ftp)
return CURLE_OUT_OF_MEMORY;
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index 2a7ca5baf..82f1ea00d 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -55,9 +55,6 @@
/* The last #include file should be: */
#include "memdebug.h"
-/* allocs buffer which will contain one line of LIST command response */
-#define FTP_BUFFER_ALLOCSIZE 160
-
typedef enum {
PL_UNIX_TOTALSIZE = 0,
PL_UNIX_FILETYPE,
diff --git a/lib/functypes.h b/lib/functypes.h
index 075c02e54..ea66d3281 100644
--- a/lib/functypes.h
+++ b/lib/functypes.h
@@ -38,7 +38,7 @@
2. For systems with config-*.h files, define them there.
*/
-#ifdef WIN32
+#ifdef _WIN32
/* int recv(SOCKET, char *, int, int) */
#define RECV_TYPE_ARG1 SOCKET
#define RECV_TYPE_ARG2 char *
diff --git a/lib/getenv.c b/lib/getenv.c
index 806978472..48ee97228 100644
--- a/lib/getenv.c
+++ b/lib/getenv.c
@@ -31,10 +31,11 @@
static char *GetEnv(const char *variable)
{
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) || \
+ defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */
(void)variable;
return NULL;
-#elif defined(WIN32)
+#elif defined(_WIN32)
/* This uses Windows API instead of C runtime getenv() to get the environment
variable since some changes aren't always visible to the latter. #4774 */
char *buf = NULL;
diff --git a/lib/getinfo.c b/lib/getinfo.c
index f1574e097..2f74629e1 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -409,6 +409,9 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
case CURLINFO_STARTTRANSFER_TIME_T:
*param_offt = data->progress.t_starttransfer;
break;
+ case CURLINFO_QUEUE_TIME_T:
+ *param_offt = data->progress.t_postqueue;
+ break;
case CURLINFO_REDIRECT_TIME_T:
*param_offt = data->progress.t_redirect;
break;
@@ -420,7 +423,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
break;
case CURLINFO_CONN_ID:
*param_offt = data->conn?
- data->conn->connection_id : data->state.recent_conn_id;
+ data->conn->connection_id : data->state.recent_conn_id;
break;
default:
return CURLE_UNKNOWN_OPTION;
diff --git a/lib/gopher.c b/lib/gopher.c
index 61e41b7e4..9ca08289e 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -75,7 +75,7 @@ const struct Curl_handler Curl_handler_gopher = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_GOPHER, /* defport */
@@ -99,7 +99,7 @@ const struct Curl_handler Curl_handler_gophers = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_GOPHER, /* defport */
diff --git a/lib/headers.c b/lib/headers.c
index 3ff4d5eb0..8a3264ab5 100644
--- a/lib/headers.c
+++ b/lib/headers.c
@@ -185,7 +185,7 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
}
static CURLcode namevalue(char *header, size_t hlen, unsigned int type,
- char **name, char **value)
+ char **name, char **value)
{
char *end = header + hlen - 1; /* point to the last byte */
DEBUGASSERT(hlen);
@@ -292,9 +292,10 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
if(!end) {
end = strchr(header, '\n');
if(!end)
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ /* neither CR nor LF as terminator is not a valid header */
+ return CURLE_WEIRD_SERVER_REPLY;
}
- hlen = end - header + 1;
+ hlen = end - header;
if((header[0] == ' ') || (header[0] == '\t')) {
if(data->state.prevhead)
@@ -319,21 +320,19 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
hs->buffer[hlen] = 0; /* nul terminate */
result = namevalue(hs->buffer, hlen, type, &name, &value);
- if(result)
- goto fail;
-
- hs->name = name;
- hs->value = value;
- hs->type = type;
- hs->request = data->state.requests;
-
- /* insert this node into the list of headers */
- Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
- hs, &hs->node);
- data->state.prevhead = hs;
- return CURLE_OK;
-fail:
- free(hs);
+ if(!result) {
+ hs->name = name;
+ hs->value = value;
+ hs->type = type;
+ hs->request = data->state.requests;
+
+ /* insert this node into the list of headers */
+ Curl_llist_insert_next(&data->state.httphdrs, data->state.httphdrs.tail,
+ hs, &hs->node);
+ data->state.prevhead = hs;
+ }
+ else
+ free(hs);
return result;
}
diff --git a/lib/hostip.c b/lib/hostip.c
index 3cd9a65c5..4f44d348f 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -117,6 +117,13 @@
static void freednsentry(void *freethis);
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void show_resolve_info(struct Curl_easy *data,
+ struct Curl_dns_entry *dns);
+#else
+#define show_resolve_info(x,y) Curl_nop_stmt
+#endif
+
/*
* 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
@@ -481,9 +488,11 @@ Curl_cache_addr(struct Curl_easy *data,
return NULL;
}
#endif
+ if(!hostlen)
+ hostlen = strlen(hostname);
/* Create a new cache entry */
- dns = calloc(1, sizeof(struct Curl_dns_entry));
+ dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns) {
return NULL;
}
@@ -497,6 +506,9 @@ Curl_cache_addr(struct Curl_easy *data,
time(&dns->timestamp);
if(dns->timestamp == 0)
dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */
+ dns->hostport = port;
+ if(hostlen)
+ memcpy(dns->hostname, hostname, hostlen);
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
@@ -521,7 +533,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name)
struct sockaddr_in6 sa6;
unsigned char ipv6[16];
unsigned short port16 = (unsigned short)(port & 0xffff);
- ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+ ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
if(!ca)
return NULL;
@@ -568,7 +580,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name)
return NULL;
memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4));
- ca = calloc(sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1, 1);
+ ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1);
if(!ca)
return NULL;
ca->ai_flags = 0;
@@ -742,16 +754,22 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
#ifndef USE_RESOLVE_ON_IPS
/* First check if this is an IPv4 address string */
- if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
/* This is a dotted IP address 123.123.123.123-style */
addr = Curl_ip2addr(AF_INET, &in, hostname, port);
+ if(!addr)
+ return CURLRESOLV_ERROR;
+ }
#ifdef ENABLE_IPV6
- if(!addr) {
+ else {
struct in6_addr in6;
/* check if this is an IPv6 address string */
- if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
+ if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0) {
/* This is an IPv6 address literal */
addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
+ if(!addr)
+ return CURLRESOLV_ERROR;
+ }
}
#endif /* ENABLE_IPV6 */
@@ -823,8 +841,10 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
if(!dns)
/* returned failure, bail out nicely */
Curl_freeaddrinfo(addr);
- else
+ else {
rc = CURLRESOLV_RESOLVED;
+ show_resolve_info(data, dns);
+ }
}
}
@@ -839,7 +859,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
* execution. This effectively causes the remainder of the application to run
* within a signal handler which is nonportable and could lead to problems.
*/
-static
+CURL_NORETURN static
void alarmfunc(int sig)
{
(void)sig;
@@ -1269,9 +1289,11 @@ err:
Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "Added %.*s:%d:%s to DNS cache%s",
(int)hlen, host_begin, port, addresses,
permanent ? "" : " (non-permanent)");
+#endif
/* Wildcard hostname */
if((hlen == 1) && (host_begin[0] == '*')) {
@@ -1285,18 +1307,89 @@ err:
return CURLE_OK;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+static void show_resolve_info(struct Curl_easy *data,
+ struct Curl_dns_entry *dns)
+{
+ struct Curl_addrinfo *a;
+ CURLcode result = CURLE_OK;
+#ifdef CURLRES_IPV6
+ struct dynbuf out[2];
+#else
+ struct dynbuf out[1];
+#endif
+ DEBUGASSERT(data);
+ DEBUGASSERT(dns);
+
+ if(!data->set.verbose ||
+ /* ignore no name or numerical IP addresses */
+ !dns->hostname[0] || Curl_host_is_ipnum(dns->hostname))
+ return;
+
+ a = dns->addr;
+
+ infof(data, "Host %s:%d was resolved.",
+ (dns->hostname[0] ? dns->hostname : "(none)"), dns->hostport);
+
+ Curl_dyn_init(&out[0], 1024);
+#ifdef CURLRES_IPV6
+ Curl_dyn_init(&out[1], 1024);
+#endif
+
+ while(a) {
+ if(
+#ifdef CURLRES_IPV6
+ a->ai_family == PF_INET6 ||
+#endif
+ a->ai_family == PF_INET) {
+ char buf[MAX_IPADR_LEN];
+ struct dynbuf *d = &out[(a->ai_family != PF_INET)];
+ Curl_printable_address(a, buf, sizeof(buf));
+ if(Curl_dyn_len(d))
+ result = Curl_dyn_addn(d, ", ", 2);
+ if(!result)
+ result = Curl_dyn_add(d, buf);
+ if(result) {
+ infof(data, "too many IP, can't show");
+ goto fail;
+ }
+ }
+ a = a->ai_next;
+ }
+
+#ifdef CURLRES_IPV6
+ infof(data, "IPv6: %s",
+ (Curl_dyn_len(&out[1]) ? Curl_dyn_ptr(&out[1]) : "(none)"));
+#endif
+ infof(data, "IPv4: %s",
+ (Curl_dyn_len(&out[0]) ? Curl_dyn_ptr(&out[0]) : "(none)"));
+
+fail:
+ Curl_dyn_free(&out[0]);
+#ifdef CURLRES_IPV6
+ Curl_dyn_free(&out[1]);
+#endif
+}
+#endif
+
CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
+ CURLcode result;
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
(void)data;
(void)dns;
#endif
#ifndef CURL_DISABLE_DOH
- if(data->conn->bits.doh)
- return Curl_doh_is_resolved(data, dns);
+ if(data->conn->bits.doh) {
+ result = Curl_doh_is_resolved(data, dns);
+ }
+ else
#endif
- return Curl_resolver_is_resolved(data, dns);
+ result = Curl_resolver_is_resolved(data, dns);
+ if(*dns)
+ show_resolve_info(data, *dns);
+ return result;
}
int Curl_resolv_getsock(struct Curl_easy *data,
diff --git a/lib/hostip.h b/lib/hostip.h
index b68f539b2..fb53a5776 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -64,6 +64,10 @@ struct Curl_dns_entry {
time_t timestamp;
/* use-counter, use Curl_resolv_unlock to release reference */
long inuse;
+ /* hostname port number that resolved to addr. */
+ int hostport;
+ /* hostname that resolved to addr. may be NULL (unix domain sockets). */
+ char hostname[1];
};
bool Curl_host_is_ipnum(const char *hostname);
diff --git a/lib/hostip6.c b/lib/hostip6.c
index 6b0ba55e9..18969a7a7 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -71,8 +71,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
#if defined(CURLRES_SYNCH)
#ifdef DEBUG_ADDRINFO
-static void dump_addrinfo(struct connectdata *conn,
- const struct Curl_addrinfo *ai)
+static void dump_addrinfo(const struct Curl_addrinfo *ai)
{
printf("dump_addrinfo:\n");
for(; ai; ai = ai->ai_next) {
@@ -84,7 +83,7 @@ static void dump_addrinfo(struct connectdata *conn,
}
}
#else
-#define dump_addrinfo(x,y) Curl_nop_stmt
+#define dump_addrinfo(x) Curl_nop_stmt
#endif
/*
@@ -149,7 +148,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
Curl_addrinfo_set_port(res, port);
}
- dump_addrinfo(conn, res);
+ dump_addrinfo(res);
return res;
}
diff --git a/lib/hsts.c b/lib/hsts.c
index 7ecf0042a..8725a35c1 100644
--- a/lib/hsts.c
+++ b/lib/hsts.c
@@ -40,6 +40,7 @@
#include "fopen.h"
#include "rename.h"
#include "share.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -76,7 +77,7 @@ static time_t hsts_debugtime(void *unused)
struct hsts *Curl_hsts_init(void)
{
- struct hsts *h = calloc(sizeof(struct hsts), 1);
+ struct hsts *h = calloc(1, sizeof(struct hsts));
if(h) {
Curl_llist_init(&h->list, NULL);
}
@@ -108,7 +109,7 @@ void Curl_hsts_cleanup(struct hsts **hp)
static struct stsentry *hsts_entry(void)
{
- return calloc(sizeof(struct stsentry), 1);
+ return calloc(1, sizeof(struct stsentry));
}
static CURLcode hsts_create(struct hsts *h,
@@ -116,27 +117,31 @@ static CURLcode hsts_create(struct hsts *h,
bool subdomains,
curl_off_t expires)
{
- struct stsentry *sts = hsts_entry();
- char *duphost;
size_t hlen;
- if(!sts)
- return CURLE_OUT_OF_MEMORY;
+ DEBUGASSERT(h);
+ DEBUGASSERT(hostname);
+
+ hlen = strlen(hostname);
+ if(hlen && (hostname[hlen - 1] == '.'))
+ /* strip off any trailing dot */
+ --hlen;
+ if(hlen) {
+ char *duphost;
+ struct stsentry *sts = hsts_entry();
+ if(!sts)
+ return CURLE_OUT_OF_MEMORY;
+
+ duphost = Curl_memdup0(hostname, hlen);
+ if(!duphost) {
+ free(sts);
+ return CURLE_OUT_OF_MEMORY;
+ }
- duphost = strdup(hostname);
- if(!duphost) {
- free(sts);
- return CURLE_OUT_OF_MEMORY;
+ sts->host = duphost;
+ sts->expires = expires;
+ sts->includeSubDomains = subdomains;
+ Curl_llist_insert_next(&h->list, h->list.tail, sts, &sts->node);
}
-
- hlen = strlen(duphost);
- if(duphost[hlen - 1] == '.')
- /* strip off trailing any dot */
- duphost[--hlen] = 0;
-
- sts->host = duphost;
- sts->expires = expires;
- sts->includeSubDomains = subdomains;
- Curl_llist_insert_next(&h->list, h->list.tail, sts, &sts->node);
return CURLE_OK;
}
@@ -473,6 +478,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
if(sc == CURLSTS_OK) {
time_t expires;
CURLcode result;
+ DEBUGASSERT(e.name[0]);
if(!e.name[0])
/* bail out if no name was stored */
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -564,7 +570,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
void Curl_hsts_loadfiles(struct Curl_easy *data)
{
- struct curl_slist *l = data->set.hstslist;
+ struct curl_slist *l = data->state.hstslist;
if(l) {
Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE);
diff --git a/lib/http.c b/lib/http.c
index 40ef70df5..679931e4b 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -100,24 +100,14 @@
* Forward declarations.
*/
-static int http_getsock_do(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks);
static bool http_should_fail(struct Curl_easy *data);
-static CURLcode http_setup_conn(struct Curl_easy *data,
- struct connectdata *conn);
-#ifdef USE_WEBSOCKETS
-static CURLcode ws_setup_conn(struct Curl_easy *data,
- struct connectdata *conn);
-#endif
-
/*
* HTTP handler interface.
*/
const struct Curl_handler Curl_handler_http = {
"HTTP", /* scheme */
- http_setup_conn, /* setup_connection */
+ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -125,11 +115,11 @@ const struct Curl_handler Curl_handler_http = {
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
- http_getsock_do, /* doing_getsock */
+ Curl_http_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ Curl_http_write_resp, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_HTTP, /* defport */
@@ -139,39 +129,13 @@ const struct Curl_handler Curl_handler_http = {
PROTOPT_USERPWDCTRL
};
-#ifdef USE_WEBSOCKETS
-const struct Curl_handler Curl_handler_ws = {
- "WS", /* scheme */
- ws_setup_conn, /* setup_connection */
- Curl_http, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- Curl_http_connect, /* connect_it */
- ZERO_NULL, /* connecting */
- ZERO_NULL, /* doing */
- ZERO_NULL, /* proto_getsock */
- http_getsock_do, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- ZERO_NULL, /* perform_getsock */
- Curl_ws_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- PORT_HTTP, /* defport */
- CURLPROTO_WS, /* protocol */
- CURLPROTO_HTTP, /* family */
- PROTOPT_CREDSPERREQUEST | /* flags */
- PROTOPT_USERPWDCTRL
-};
-#endif
-
#ifdef USE_SSL
/*
* HTTPS handler interface.
*/
const struct Curl_handler Curl_handler_https = {
"HTTPS", /* scheme */
- http_setup_conn, /* setup_connection */
+ Curl_http_setup_conn, /* setup_connection */
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
@@ -179,11 +143,11 @@ const struct Curl_handler Curl_handler_https = {
NULL, /* connecting */
ZERO_NULL, /* doing */
NULL, /* proto_getsock */
- http_getsock_do, /* doing_getsock */
+ Curl_http_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ Curl_http_write_resp, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_HTTPS, /* defport */
@@ -193,36 +157,10 @@ const struct Curl_handler Curl_handler_https = {
PROTOPT_USERPWDCTRL
};
-#ifdef USE_WEBSOCKETS
-const struct Curl_handler Curl_handler_wss = {
- "WSS", /* scheme */
- ws_setup_conn, /* setup_connection */
- Curl_http, /* do_it */
- Curl_http_done, /* done */
- ZERO_NULL, /* do_more */
- Curl_http_connect, /* connect_it */
- NULL, /* connecting */
- ZERO_NULL, /* doing */
- NULL, /* proto_getsock */
- http_getsock_do, /* doing_getsock */
- ZERO_NULL, /* domore_getsock */
- ZERO_NULL, /* perform_getsock */
- Curl_ws_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
- ZERO_NULL, /* connection_check */
- ZERO_NULL, /* attach connection */
- PORT_HTTPS, /* defport */
- CURLPROTO_WSS, /* protocol */
- CURLPROTO_HTTP, /* family */
- PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
- PROTOPT_USERPWDCTRL
-};
-#endif
-
#endif
-static CURLcode http_setup_conn(struct Curl_easy *data,
- struct connectdata *conn)
+CURLcode Curl_http_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
{
/* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
@@ -245,16 +183,6 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
return CURLE_OK;
}
-#ifdef USE_WEBSOCKETS
-static CURLcode ws_setup_conn(struct Curl_easy *data,
- struct connectdata *conn)
-{
- /* websockets is 1.1 only (for now) */
- data->state.httpwant = CURL_HTTP_VERSION_1_1;
- return http_setup_conn(data, conn);
-}
-#endif
-
#ifndef CURL_DISABLE_PROXY
/*
* checkProxyHeaders() checks the linked list of custom proxy headers
@@ -297,7 +225,6 @@ char *Curl_copy_header_value(const char *header)
{
const char *start;
const char *end;
- char *value;
size_t len;
/* Find the end of the header name */
@@ -330,14 +257,7 @@ char *Curl_copy_header_value(const char *header)
/* get length of the type */
len = end - start + 1;
- value = malloc(len + 1);
- if(!value)
- return NULL;
-
- memcpy(value, start, len);
- value[len] = 0; /* null-terminate */
-
- return value;
+ return Curl_memdup0(start, len);
}
#ifndef CURL_DISABLE_HTTP_AUTH
@@ -836,6 +756,7 @@ output_auth_headers(struct Curl_easy *data,
(data->state.aptr.user ?
data->state.aptr.user : ""));
#else
+ (void)proxy;
infof(data, "Server auth using %s with user '%s'",
auth, data->state.aptr.user ?
data->state.aptr.user : "");
@@ -845,7 +766,7 @@ output_auth_headers(struct Curl_easy *data,
else
authstatus->multipass = FALSE;
- return CURLE_OK;
+ return result;
}
/**
@@ -970,17 +891,21 @@ Curl_http_output_auth(struct Curl_easy *data,
}
#endif
-/*
- * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
- * headers. They are dealt with both in the transfer.c main loop and in the
- * proxy CONNECT loop.
- */
-
+#if defined(USE_SPNEGO) || defined(USE_NTLM) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ !defined(CURL_DISABLE_BASIC_AUTH) || \
+ !defined(CURL_DISABLE_BEARER_AUTH)
static int is_valid_auth_separator(char ch)
{
return ch == '\0' || ch == ',' || ISSPACE(ch);
}
+#endif
+/*
+ * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
+ * headers. They are dealt with both in the transfer.c main loop and in the
+ * proxy CONNECT loop.
+ */
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
const char *auth) /* the first non-space */
{
@@ -992,11 +917,15 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
&conn->http_negotiate_state;
#endif
+#if defined(USE_SPNEGO) || \
+ defined(USE_NTLM) || \
+ !defined(CURL_DISABLE_DIGEST_AUTH) || \
+ !defined(CURL_DISABLE_BASIC_AUTH) || \
+ !defined(CURL_DISABLE_BEARER_AUTH)
+
unsigned long *availp;
struct auth *authp;
- (void) conn; /* In case conditionals make it unused. */
-
if(proxy) {
availp = &data->info.proxyauthavail;
authp = &data->state.authproxy;
@@ -1005,6 +934,11 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
availp = &data->info.httpauthavail;
authp = &data->state.authhost;
}
+#else
+ (void) proxy;
+#endif
+
+ (void) conn; /* In case conditionals make it unused. */
/*
* Here we check if we want the specific single authentication (using ==) and
@@ -1140,7 +1074,14 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
}
}
#else
- ;
+ {
+ /*
+ * Empty block to terminate the if-else chain correctly.
+ *
+ * A semicolon would yield the same result here, but can cause a
+ * compiler warning when -Wextra is enabled.
+ */
+ }
#endif
/* there may be multiple methods on one line, so keep reading */
@@ -1403,7 +1344,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
* and install our own `data->state.fread_func` that
* on subsequent calls reads `in` empty.
* - when the whisked away `in` is empty, the `fread_func`
- * is restored ot its original state.
+ * is restored to its original state.
* The problem is that `fread_func` can only return
* `upload_buffer_size` lengths. If the send we do here
* is larger and blocks, we do re-sending with smaller
@@ -1576,9 +1517,9 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
the single socket to become writable only */
-static int http_getsock_do(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
+int Curl_http_getsock_do(struct Curl_easy *data,
+ struct connectdata *conn,
+ curl_socket_t *socks)
{
/* write mode */
(void)conn;
@@ -1678,8 +1619,6 @@ static CURLcode expect100(struct Curl_easy *data,
struct dynbuf *req)
{
CURLcode result = CURLE_OK;
- data->state.expect100header = FALSE; /* default to false unless it is set
- to TRUE below */
if(!data->state.disableexpect && Curl_use_http_1_1plus(data, conn) &&
(conn->httpversion < 20)) {
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
@@ -2084,6 +2023,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
switch(data->set.timecondition) {
default:
+ DEBUGF(infof(data, "invalid time condition"));
return CURLE_BAD_FUNCTION_ARGUMENT;
case CURL_TIMECOND_IFMODSINCE:
@@ -2252,7 +2192,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
}
#endif
- if(strcmp("Host:", ptr)) {
+ if(!strcasecompare("Host:", ptr)) {
aptr->host = aprintf("Host:%s\r\n", &ptr[5]);
if(!aptr->host)
return CURLE_OUT_OF_MEMORY;
@@ -2340,9 +2280,7 @@ CURLcode Curl_http_target(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
}
- /* Extract the URL to use in the request. Store in STRING_TEMP_URL for
- clean-up reasons if the function returns before the free() further
- down. */
+ /* Extract the URL to use in the request. */
uc = curl_url_get(h, CURLUPART_URL, &url, CURLU_NO_DEFAULT_PORT);
if(uc) {
curl_url_cleanup(h);
@@ -2414,14 +2352,16 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
/* Convert the form structure into a mime structure, then keep
the conversion */
if(!data->state.formp) {
- data->state.formp = calloc(sizeof(curl_mimepart), 1);
+ data->state.formp = calloc(1, sizeof(curl_mimepart));
if(!data->state.formp)
return CURLE_OUT_OF_MEMORY;
Curl_mime_cleanpart(data->state.formp);
result = Curl_getformdata(data, data->state.formp, data->set.httppost,
data->state.fread_func);
- if(result)
+ if(result) {
+ Curl_safefree(data->state.formp);
return result;
+ }
data->state.mimepost = data->state.formp;
}
break;
@@ -2494,6 +2434,29 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
return result;
}
+static CURLcode addexpect(struct Curl_easy *data, struct connectdata *conn,
+ struct dynbuf *r)
+{
+ data->state.expect100header = FALSE;
+ /* Avoid Expect: 100-continue if Upgrade: is used */
+ if(data->req.upgr101 == UPGR101_INIT) {
+ struct HTTP *http = data->req.p.http;
+ /* For really small puts we don't use Expect: headers at all, and for
+ the somewhat bigger ones we allow the app to disable it. Just make
+ sure that the expect100header is always set to the preferred value
+ here. */
+ char *ptr = Curl_checkheaders(data, STRCONST("Expect"));
+ if(ptr) {
+ data->state.expect100header =
+ Curl_compareheader(ptr, STRCONST("Expect:"),
+ STRCONST("100-continue"));
+ }
+ else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0)
+ return expect100(data, conn, r);
+ }
+ return CURLE_OK;
+}
+
CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
struct dynbuf *r, Curl_HttpReq httpreq)
{
@@ -2506,14 +2469,8 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
#endif
CURLcode result = CURLE_OK;
struct HTTP *http = data->req.p.http;
- const char *ptr;
-
- /* If 'authdone' is FALSE, we must not set the write socket index to the
- Curl_transfer() call below, as we're not ready to actually upload any
- data yet. */
switch(httpreq) {
-
case HTTPREQ_PUT: /* Let's PUT the data to the server! */
if(conn->bits.authneg)
@@ -2531,20 +2488,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result;
}
- /* For really small puts we don't use Expect: headers at all, and for
- the somewhat bigger ones we allow the app to disable it. Just make
- sure that the expect100header is always set to the preferred value
- here. */
- ptr = Curl_checkheaders(data, STRCONST("Expect"));
- if(ptr) {
- data->state.expect100header =
- Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
- }
- else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
- result = expect100(data, conn, r);
- if(result)
- return result;
- }
+ result = addexpect(data, conn, r);
+ if(result)
+ return result;
/* end of headers */
result = Curl_dyn_addn(r, STRCONST("\r\n"));
@@ -2617,22 +2563,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
}
#endif
- /* For really small posts we don't use Expect: headers at all, and for
- the somewhat bigger ones we allow the app to disable it. Just make
- sure that the expect100header is always set to the preferred value
- here. */
- ptr = Curl_checkheaders(data, STRCONST("Expect"));
- if(ptr) {
- data->state.expect100header =
- Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
- }
- else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
- result = expect100(data, conn, r);
- if(result)
- return result;
- }
- else
- data->state.expect100header = FALSE;
+ result = addexpect(data, conn, r);
+ if(result)
+ return result;
/* make the request end in a true CRLF */
result = Curl_dyn_addn(r, STRCONST("\r\n"));
@@ -2692,22 +2625,9 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
return result;
}
- /* For really small posts we don't use Expect: headers at all, and for
- the somewhat bigger ones we allow the app to disable it. Just make
- sure that the expect100header is always set to the preferred value
- here. */
- ptr = Curl_checkheaders(data, STRCONST("Expect"));
- if(ptr) {
- data->state.expect100header =
- Curl_compareheader(ptr, STRCONST("Expect:"), STRCONST("100-continue"));
- }
- else if(http->postsize > EXPECT_100_THRESHOLD || http->postsize < 0) {
- result = expect100(data, conn, r);
- if(result)
- return result;
- }
- else
- data->state.expect100header = FALSE;
+ result = addexpect(data, conn, r);
+ if(result)
+ return result;
#ifndef USE_HYPER
/* With Hyper the body is always passed on separately */
@@ -3020,13 +2940,14 @@ CURLcode Curl_http_resume(struct Curl_easy *data,
}
/* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
+ char scratch[4*1024];
size_t readthisamountnow =
- (data->state.resume_from - passed > data->set.buffer_size) ?
- (size_t)data->set.buffer_size :
+ (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ?
+ sizeof(scratch) :
curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
- data->state.fread_func(data->state.buffer, 1, readthisamountnow,
+ data->state.fread_func(scratch, 1, readthisamountnow,
data->state.in);
passed += actuallyread;
@@ -3061,6 +2982,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
{
struct SingleRequest *k = &data->req;
+ *done = FALSE;
if(data->req.newurl) {
if(conn->bits.close) {
/* Abort after the headers if "follow Location" is set
@@ -3186,14 +3108,14 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
) {
result = Curl_http2_switch(data, conn, FIRSTSOCKET);
if(result)
- return result;
+ goto fail;
}
else
#endif
DEBUGASSERT(Curl_conn_is_http2(data, conn, FIRSTSOCKET));
break;
case CURL_HTTP_VERSION_1_1:
- /* continue with HTTP/1.1 when explicitly requested */
+ /* continue with HTTP/1.x when explicitly requested */
break;
default:
/* Check if user wants to use HTTP/2 with clear TCP */
@@ -3201,7 +3123,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
DEBUGF(infof(data, "HTTP/2 over clean TCP"));
result = Curl_http2_switch(data, conn, FIRSTSOCKET);
if(result)
- return result;
+ goto fail;
}
break;
}
@@ -3211,11 +3133,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
result = Curl_http_host(data, conn);
if(result)
- return result;
+ goto fail;
result = Curl_http_useragent(data);
if(result)
- return result;
+ goto fail;
Curl_http_method(data, conn, &request, &httpreq);
@@ -3231,7 +3153,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
(pq ? pq : data->state.up.path), FALSE);
free(pq);
if(result)
- return result;
+ goto fail;
}
Curl_safefree(data->state.aptr.ref);
@@ -3256,23 +3178,23 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
/* we only consider transfer-encoding magic if libz support is built-in */
result = Curl_transferencode(data);
if(result)
- return result;
+ goto fail;
#endif
result = Curl_http_body(data, conn, httpreq, &te);
if(result)
- return result;
+ goto fail;
p_accept = Curl_checkheaders(data,
STRCONST("Accept"))?NULL:"Accept: */*\r\n";
result = Curl_http_resume(data, conn, httpreq);
if(result)
- return result;
+ goto fail;
result = Curl_http_range(data, httpreq);
if(result)
- return result;
+ goto fail;
httpstring = get_http_string(data, conn);
@@ -3290,7 +3212,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
result = Curl_http_target(data, conn, &req);
if(result) {
Curl_dyn_free(&req);
- return result;
+ goto fail;
}
#ifndef CURL_DISABLE_ALTSVC
@@ -3361,7 +3283,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(result) {
Curl_dyn_free(&req);
- return result;
+ goto fail;
}
if(!(conn->handler->flags&PROTOPT_SSL) &&
@@ -3397,7 +3319,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
if(result) {
Curl_dyn_free(&req);
- return result;
+ goto fail;
}
if((http->postsize > -1) &&
@@ -3433,6 +3355,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
but is disabled here again to avoid that the chunked encoded version is
actually used when sending the request body over h2 */
data->req.upload_chunky = FALSE;
+fail:
+ if(CURLE_TOO_LARGE == result)
+ failf(data, "HTTP request too large");
return result;
}
@@ -3685,7 +3610,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
k->content_range = TRUE;
}
}
- else
+ else if(k->httpcode < 300)
data->state.resume_from = 0; /* get everything */
}
#if !defined(CURL_DISABLE_COOKIES)
@@ -3895,7 +3820,7 @@ CURLcode Curl_http_statusline(struct Curl_easy *data,
* fields. */
if(data->set.timecondition)
data->info.timecond = TRUE;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case 204:
/* (quote from RFC2616, section 10.2.5): The server has
* fulfilled the request but does not need to return an
@@ -3994,37 +3919,33 @@ CURLcode Curl_bump_headersize(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)
+static CURLcode http_rw_headers(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t *pconsumed)
{
- CURLcode result;
+ struct connectdata *conn = data->conn;
+ CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
- ssize_t onread = *nread;
- char *ostr = k->str;
char *headp;
- char *str_start;
char *end_ptr;
+ bool leftover_body = FALSE;
/* header line within buffer loop */
+ *pconsumed = 0;
do {
- size_t rest_length;
- size_t full_length;
+ size_t line_length;
int writetype;
- /* str_start is start of line within buf */
- str_start = k->str;
-
/* data is in network encoding so use 0x0a instead of '\n' */
- end_ptr = memchr(str_start, 0x0a, *nread);
+ end_ptr = memchr(buf, 0x0a, blen);
if(!end_ptr) {
/* Not a complete header line within buffer, append the data to
the end of the headerbuff. */
- result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
+ result = Curl_dyn_addn(&data->state.headerb, buf, blen);
if(result)
return result;
+ *pconsumed += blen;
if(!k->headerline) {
/* check if this looks like a protocol header */
@@ -4036,31 +3957,28 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(st == STATUS_BAD) {
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
- k->badheader = HEADER_ALLBAD;
streamclose(conn, "bad HTTP: No end-of-message indicator");
if(!data->set.http09_allowed) {
failf(data, "Received HTTP/0.9 when not allowed");
return CURLE_UNSUPPORTED_PROTOCOL;
}
- break;
+ leftover_body = TRUE;
+ goto out;
}
}
-
- break; /* read more and try again */
+ goto out; /* read more and try again */
}
/* decrease the size of the remaining (supposed) header line */
- rest_length = (end_ptr - k->str) + 1;
- *nread -= (ssize_t)rest_length;
-
- k->str = end_ptr + 1; /* move past new line */
-
- full_length = k->str - str_start;
-
- result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
+ line_length = (end_ptr - buf) + 1;
+ result = Curl_dyn_addn(&data->state.headerb, buf, line_length);
if(result)
return result;
+ blen -= line_length;
+ buf += line_length;
+ *pconsumed += line_length;
+
/****
* We now have a FULL header line in 'headerb'.
*****/
@@ -4078,17 +3996,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return CURLE_UNSUPPORTED_PROTOCOL;
}
k->header = FALSE;
- if(*nread)
- /* since there's more, this is a partial bad header */
- k->badheader = HEADER_PARTHEADER;
- else {
- /* this was all we read so it's all a bad header */
- k->badheader = HEADER_ALLBAD;
- *nread = onread;
- k->str = ostr;
- return CURLE_OK;
- }
- break;
+ leftover_body = TRUE;
+ goto out;
}
}
@@ -4097,6 +4006,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
headp = Curl_dyn_ptr(&data->state.headerb);
if((0x0a == *headp) || (0x0d == *headp)) {
size_t headerlen;
+ bool switch_to_h2 = FALSE;
/* Zero-length header line means end of headers! */
if('\r' == *headp)
@@ -4126,41 +4036,40 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
break;
case 101:
- /* Switching Protocols */
- if(k->upgr101 == UPGR101_H2) {
- /* Switching to HTTP/2 */
- DEBUGASSERT(conn->httpversion < 20);
- infof(data, "Received 101, Switching to HTTP/2");
- k->upgr101 = UPGR101_RECEIVED;
-
- /* we'll get more headers (HTTP/2 response) */
- k->header = TRUE;
- k->headerline = 0; /* restart the header line counter */
-
- /* switch to http2 now. The bytes after response headers
- are also processed here, otherwise they are lost. */
- result = Curl_http2_upgrade(data, conn, FIRSTSOCKET,
- k->str, *nread);
- if(result)
- return result;
- *nread = 0;
- }
+ if(conn->httpversion == 11) {
+ /* Switching Protocols only allowed from HTTP/1.1 */
+ if(k->upgr101 == UPGR101_H2) {
+ /* Switching to HTTP/2 */
+ infof(data, "Received 101, Switching to HTTP/2");
+ k->upgr101 = UPGR101_RECEIVED;
+
+ /* we'll get more headers (HTTP/2 response) */
+ k->header = TRUE;
+ k->headerline = 0; /* restart the header line counter */
+ switch_to_h2 = TRUE;
+ }
#ifdef USE_WEBSOCKETS
- else if(k->upgr101 == UPGR101_WS) {
- /* verify the response */
- result = Curl_ws_accept(data, k->str, *nread);
- if(result)
- return result;
- k->header = FALSE; /* no more header to parse! */
- if(data->set.connect_only) {
- k->keepon &= ~KEEP_RECV; /* read no more content */
- *nread = 0;
+ else if(k->upgr101 == UPGR101_WS) {
+ /* verify the response */
+ result = Curl_ws_accept(data, buf, blen);
+ if(result)
+ return result;
+ k->header = FALSE; /* no more header to parse! */
+ *pconsumed += blen; /* ws accept handled the data */
+ blen = 0;
+ if(data->set.connect_only)
+ k->keepon &= ~KEEP_RECV; /* read no more content */
}
- }
#endif
+ else {
+ /* Not switching to another protocol */
+ k->header = FALSE; /* no more header to parse! */
+ }
+ }
else {
- /* Not switching to another protocol */
- k->header = FALSE; /* no more header to parse! */
+ /* invalid for other HTTP versions */
+ failf(data, "unexpected 101 response code");
+ return CURLE_WEIRD_SERVER_REPLY;
}
break;
default:
@@ -4366,17 +4275,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* out and return home.
*/
if(data->req.no_body)
- *stop_reading = TRUE;
-#ifndef CURL_DISABLE_RTSP
- else if((conn->handler->protocol & CURLPROTO_RTSP) &&
- (data->set.rtspreq == RTSPREQ_DESCRIBE) &&
- (k->size <= -1))
- /* Respect section 4.4 of rfc2326: If the Content-Length header is
- absent, a length 0 must be assumed. It will prevent libcurl from
- hanging on DESCRIBE request that got refused for whatever
- reason */
- *stop_reading = TRUE;
-#endif
+ k->download_done = TRUE;
/* If max download size is *zero* (nothing) we already have
nothing and can safely return ok now! But for HTTP/2, we'd
@@ -4386,19 +4285,27 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(0 == k->maxdownload
&& !Curl_conn_is_http2(data, conn, FIRSTSOCKET)
&& !Curl_conn_is_http3(data, conn, FIRSTSOCKET))
- *stop_reading = TRUE;
+ k->download_done = TRUE;
- if(*stop_reading) {
- /* we make sure that this socket isn't read more now */
- k->keepon &= ~KEEP_RECV;
- }
-
- Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
- break; /* exit header line loop */
+ Curl_debug(data, CURLINFO_HEADER_IN,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
+ goto out; /* exit header line loop */
}
/* We continue reading headers, reset the line-based header */
Curl_dyn_reset(&data->state.headerb);
+ if(switch_to_h2) {
+ /* Having handled the headers, we can do the HTTP/2 switch.
+ * Any remaining `buf` bytes are already HTTP/2 and passed to
+ * be processed. */
+ result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
+ if(result)
+ return result;
+ *pconsumed += blen;
+ blen = 0;
+ }
+
continue;
}
@@ -4583,15 +4490,84 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
Curl_dyn_reset(&data->state.headerb);
}
- while(*k->str); /* header line within buffer */
+ while(blen);
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read
buffer. */
-
+out:
+ if(!k->header && !leftover_body) {
+ Curl_dyn_free(&data->state.headerb);
+ }
return CURLE_OK;
}
+/*
+ * HTTP protocol `write_resp` implementation. Will parse headers
+ * when not done yet and otherwise return without consuming data.
+ */
+CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t *pconsumed,
+ bool *done)
+{
+ *done = FALSE;
+ if(!data->req.header) {
+ *pconsumed = 0;
+ return CURLE_OK;
+ }
+ else {
+ CURLcode result;
+
+ result = http_rw_headers(data, buf, blen, pconsumed);
+ if(!result && !data->req.header) {
+ /* we have successfully finished parsing the HEADERs */
+ result = Curl_http_firstwrite(data, data->conn, done);
+
+ if(!data->req.no_body && Curl_dyn_len(&data->state.headerb)) {
+ /* leftover from parsing something that turned out not
+ * to be a header, only happens if we allow for
+ * HTTP/0.9 like responses */
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
+ }
+ Curl_dyn_free(&data->state.headerb);
+ }
+ return result;
+ }
+}
+
+CURLcode Curl_http_write_resp(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ bool is_eos,
+ bool *done)
+{
+ CURLcode result;
+ size_t consumed;
+ int flags;
+
+ *done = FALSE;
+ result = Curl_http_write_resp_hds(data, buf, blen, &consumed, done);
+ if(result || *done)
+ goto out;
+
+ DEBUGASSERT(consumed <= blen);
+ blen -= consumed;
+ buf += consumed;
+ /* either all was consumed in header parsing, or we have data left
+ * and are done with heders, e.g. it is BODY data */
+ DEBUGASSERT(!blen || !data->req.header);
+ if(!data->req.header && (blen || is_eos)) {
+ /* BODY data after header been parsed, write and consume */
+ flags = CLIENTWRITE_BODY;
+ if(is_eos)
+ flags |= CLIENTWRITE_EOS;
+ result = Curl_client_write(data, flags, (char *)buf, blen);
+ }
+out:
+ return result;
+}
/* Decode HTTP status code string. */
CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len)
@@ -4618,17 +4594,6 @@ out:
return result;
}
-/* simple implementation of strndup(), which isn't portable */
-static char *my_strndup(const char *ptr, size_t len)
-{
- char *copy = malloc(len + 1);
- if(!copy)
- return NULL;
- memcpy(copy, ptr, len);
- copy[len] = '\0';
- return copy;
-}
-
CURLcode Curl_http_req_make(struct httpreq **preq,
const char *method, size_t m_len,
const char *scheme, size_t s_len,
@@ -4639,7 +4604,7 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(method);
- if(m_len + 1 >= sizeof(req->method))
+ if(m_len + 1 > sizeof(req->method))
return CURLE_BAD_FUNCTION_ARGUMENT;
req = calloc(1, sizeof(*req));
@@ -4647,17 +4612,17 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
goto out;
memcpy(req->method, method, m_len);
if(scheme) {
- req->scheme = my_strndup(scheme, s_len);
+ req->scheme = Curl_memdup0(scheme, s_len);
if(!req->scheme)
goto out;
}
if(authority) {
- req->authority = my_strndup(authority, a_len);
+ req->authority = Curl_memdup0(authority, a_len);
if(!req->authority)
goto out;
}
if(path) {
- req->path = my_strndup(path, p_len);
+ req->path = Curl_memdup0(path, p_len);
if(!req->path)
goto out;
}
@@ -4795,7 +4760,7 @@ CURLcode Curl_http_req_make2(struct httpreq **preq,
CURLUcode uc;
DEBUGASSERT(method);
- if(m_len + 1 >= sizeof(req->method))
+ if(m_len + 1 > sizeof(req->method))
return CURLE_BAD_FUNCTION_ARGUMENT;
req = calloc(1, sizeof(*req));
diff --git a/lib/http.h b/lib/http.h
index 9ee3c6537..ad2697c9e 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -54,14 +54,6 @@ extern const struct Curl_handler Curl_handler_http;
extern const struct Curl_handler Curl_handler_https;
#endif
-#ifdef USE_WEBSOCKETS
-extern const struct Curl_handler Curl_handler_ws;
-
-#ifdef USE_SSL
-extern const struct Curl_handler Curl_handler_wss;
-#endif
-#endif /* websockets */
-
struct dynhds;
CURLcode Curl_bump_headersize(struct Curl_easy *data,
@@ -147,9 +139,17 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
bool *done);
/* protocol-specific functions set up to be called by the main engine */
+CURLcode Curl_http_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn);
CURLcode Curl_http(struct Curl_easy *data, bool *done);
CURLcode Curl_http_done(struct Curl_easy *data, CURLcode, bool premature);
CURLcode Curl_http_connect(struct Curl_easy *data, bool *done);
+int Curl_http_getsock_do(struct Curl_easy *data, struct connectdata *conn,
+ curl_socket_t *socks);
+CURLcode Curl_http_write_resp(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ bool is_eos,
+ bool *done);
/* These functions are in http.c */
CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
@@ -225,10 +225,10 @@ struct HTTP {
CURLcode Curl_http_size(struct Curl_easy *data);
-CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
- struct connectdata *conn,
- ssize_t *nread,
- bool *stop_reading);
+CURLcode Curl_http_write_resp_hds(struct Curl_easy *data,
+ const char *buf, size_t blen,
+ size_t *pconsumed,
+ bool *done);
/**
* Curl_http_output_auth() setups the authentication headers for the
@@ -263,7 +263,7 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len);
* All about a core HTTP request, excluding body and trailers
*/
struct httpreq {
- char method[12];
+ char method[24];
char *scheme;
char *authority;
char *path;
diff --git a/lib/http2.c b/lib/http2.c
index c8b059498..c3157d1ef 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -107,14 +107,14 @@ static int populate_settings(nghttp2_settings_entry *iv,
return 3;
}
-static size_t populate_binsettings(uint8_t *binsettings,
- struct Curl_easy *data)
+static ssize_t populate_binsettings(uint8_t *binsettings,
+ struct Curl_easy *data)
{
nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN];
int ivlen;
ivlen = populate_settings(iv, data);
- /* this returns number of bytes it wrote */
+ /* this returns number of bytes it wrote or a negative number on error. */
return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
iv, ivlen);
}
@@ -219,10 +219,10 @@ static void drain_stream(struct Curl_cfilter *cf,
if(!stream->send_closed &&
(stream->upload_left || stream->upload_blocked_len))
bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
+ if(data->state.select_bits != bits) {
+ CURL_TRC_CF(data, cf, "[%d] DRAIN select_bits=%x",
stream->id, bits);
- data->state.dselect_bits = bits;
+ data->state.select_bits = bits;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
@@ -283,13 +283,20 @@ static void http2_data_done(struct Curl_cfilter *cf,
return;
if(ctx->h2) {
+ bool flush_egress = FALSE;
+ /* returns error if stream not known, which is fine here */
+ (void)nghttp2_session_set_stream_user_data(ctx->h2, stream->id, NULL);
+
if(!stream->closed && stream->id > 0) {
/* RST_STREAM */
CURL_TRC_CF(data, cf, "[%d] premature DATA_DONE, RST stream",
stream->id);
- if(!nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
- stream->id, NGHTTP2_STREAM_CLOSED))
- (void)nghttp2_session_send(ctx->h2);
+ stream->closed = TRUE;
+ stream->reset = TRUE;
+ stream->send_closed = TRUE;
+ nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
+ stream->id, NGHTTP2_STREAM_CLOSED);
+ flush_egress = TRUE;
}
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
/* Anything in the recvbuf is still being counted
@@ -299,19 +306,11 @@ static void http2_data_done(struct Curl_cfilter *cf,
nghttp2_session_consume(ctx->h2, stream->id,
Curl_bufq_len(&stream->recvbuf));
/* give WINDOW_UPATE a chance to be sent, but ignore any error */
- (void)h2_progress_egress(cf, data);
+ flush_egress = TRUE;
}
- /* -1 means unassigned and 0 means cleared */
- if(nghttp2_session_get_stream_user_data(ctx->h2, stream->id)) {
- int rv = nghttp2_session_set_stream_user_data(ctx->h2,
- stream->id, 0);
- if(rv) {
- infof(data, "http/2: failed to clear user_data for stream %u",
- stream->id);
- DEBUGASSERT(0);
- }
- }
+ if(flush_egress)
+ nghttp2_session_send(ctx->h2);
}
Curl_bufq_free(&stream->sendbuf);
@@ -369,12 +368,15 @@ static ssize_t nw_out_writer(void *writer_ctx,
{
struct Curl_cfilter *cf = writer_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
- ssize_t nwritten;
- nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
- if(nwritten > 0)
- CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
- return nwritten;
+ if(data) {
+ ssize_t nwritten = Curl_conn_cf_send(cf->next, data,
+ (const char *)buf, buflen, err);
+ if(nwritten > 0)
+ CURL_TRC_CF(data, cf, "[0] egress: wrote %zd bytes", nwritten);
+ return nwritten;
+ }
+ return 0;
}
static ssize_t send_callback(nghttp2_session *h2,
@@ -452,9 +454,14 @@ static CURLcode cf_h2_ctx_init(struct Curl_cfilter *cf,
* in the H1 request and we upgrade from there. This stream
* is opened implicitly as #1. */
uint8_t binsettings[H2_BINSETTINGS_LEN];
- size_t binlen; /* length of the binsettings data */
+ ssize_t binlen; /* length of the binsettings data */
binlen = populate_binsettings(binsettings, data);
+ if(binlen <= 0) {
+ failf(data, "nghttp2 unexpectedly failed on pack_settings_payload");
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
result = http2_data_setup(cf, data, &stream);
if(result)
@@ -1076,16 +1083,11 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
stream->reset = TRUE;
}
stream->send_closed = TRUE;
- data->req.keepon &= ~KEEP_SEND_HOLD;
drain_stream(cf, data, stream);
break;
case NGHTTP2_WINDOW_UPDATE:
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
+ if(CURL_WANT_SEND(data)) {
drain_stream(cf, data, stream);
- CURL_TRC_CF(data, cf, "[%d] un-holding after win update",
- stream_id);
}
break;
default:
@@ -1230,15 +1232,10 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
* window and *assume* that we treat this like a WINDOW_UPDATE. Some
* servers send an explicit WINDOW_UPDATE, but not all seem to do that.
* To be safe, we UNHOLD a stream in order not to stall. */
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
+ if(CURL_WANT_SEND(data)) {
struct stream_ctx *stream = H2_STREAM_CTX(data);
- data->req.keepon &= ~KEEP_SEND_HOLD;
- if(stream) {
+ if(stream)
drain_stream(cf, data, stream);
- CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
- stream_id);
- }
}
}
break;
@@ -1318,27 +1315,43 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *userp)
{
struct Curl_cfilter *cf = userp;
- struct Curl_easy *data_s;
+ struct Curl_easy *data_s, *call_data = CF_DATA_CURRENT(cf);
struct stream_ctx *stream;
int rv;
(void)session;
+ DEBUGASSERT(call_data);
/* get the stream from the hash based on Stream ID, stream ID zero is for
connection-oriented stuff */
data_s = stream_id?
nghttp2_session_get_stream_user_data(session, stream_id) : NULL;
if(!data_s) {
+ CURL_TRC_CF(call_data, cf,
+ "[%d] on_stream_close, no easy set on stream", stream_id);
return 0;
}
+ if(!GOOD_EASY_HANDLE(data_s)) {
+ /* nghttp2 still has an easy registered for the stream which has
+ * been freed be libcurl. This points to a code path that does not
+ * trigger DONE or DETACH events as it must. */
+ CURL_TRC_CF(call_data, cf,
+ "[%d] on_stream_close, not a GOOD easy on stream", stream_id);
+ (void)nghttp2_session_set_stream_user_data(session, stream_id, 0);
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
stream = H2_STREAM_CTX(data_s);
- if(!stream)
+ if(!stream) {
+ CURL_TRC_CF(data_s, cf,
+ "[%d] on_stream_close, GOOD easy but no stream", stream_id);
return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
stream->closed = TRUE;
stream->error = error_code;
- if(stream->error)
+ if(stream->error) {
stream->reset = TRUE;
- data_s->req.keepon &= ~KEEP_SEND_HOLD;
+ stream->send_closed = TRUE;
+ }
if(stream->error)
CURL_TRC_CF(data_s, cf, "[%d] RESET: %s (err %d)",
@@ -1602,10 +1615,10 @@ static int error_callback(nghttp2_session *session,
size_t len,
void *userp)
{
+ struct Curl_cfilter *cf = userp;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
(void)session;
- (void)msg;
- (void)len;
- (void)userp;
+ failf(data, "%.*s", (int)len, msg);
return 0;
}
#endif
@@ -1621,7 +1634,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
size_t blen;
struct SingleRequest *k = &data->req;
uint8_t binsettings[H2_BINSETTINGS_LEN];
- size_t binlen; /* length of the binsettings data */
+ ssize_t binlen; /* length of the binsettings data */
binlen = populate_binsettings(binsettings, data);
if(binlen <= 0) {
@@ -2052,23 +2065,13 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
/* no longer needed */
Curl_h1_req_parse_free(&stream->h1);
- nheader = Curl_dynhds_count(&h2_headers);
- nva = malloc(sizeof(nghttp2_nv) * nheader);
+ nva = Curl_dynhds_to_nva(&h2_headers, &nheader);
if(!nva) {
*err = CURLE_OUT_OF_MEMORY;
nwritten = -1;
goto out;
}
- for(i = 0; i < nheader; ++i) {
- struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
- nva[i].name = (unsigned char *)e->name;
- nva[i].namelen = e->namelen;
- nva[i].value = (unsigned char *)e->value;
- nva[i].valuelen = e->valuelen;
- nva[i].flags = NGHTTP2_NV_FLAG_NONE;
- }
-
h2_pri_spec(data, &pri_spec);
if(!nghttp2_session_check_request_allowed(ctx->h2))
CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)");
@@ -2272,14 +2275,6 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
* frame buffer or our network out buffer. */
size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
stream->id);
- if(rwin == 0) {
- /* H2 flow window exhaustion. We need to HOLD upload until we get
- * a WINDOW_UPDATE from the server. */
- data->req.keepon |= KEEP_SEND_HOLD;
- CURL_TRC_CF(data, cf, "[%d] holding send as remote flow "
- "window is exhausted", stream->id);
- }
-
/* Whatever the cause, we need to return CURL_EAGAIN for this call.
* We have unwritten state that needs us being invoked again and EAGAIN
* is the only way to ensure that. */
@@ -2331,37 +2326,37 @@ out:
return nwritten;
}
-static int cf_h2_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *sock)
+static void cf_h2_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_h2_ctx *ctx = cf->ctx;
- struct SingleRequest *k = &data->req;
- struct stream_ctx *stream = H2_STREAM_CTX(data);
- int bitmap = GETSOCK_BLANK;
- struct cf_call_data save;
+ curl_socket_t sock;
+ bool want_recv, want_send;
- CF_DATA_SAVE(save, cf, data);
- sock[0] = Curl_conn_cf_get_socket(cf, data);
-
- if(!(k->keepon & (KEEP_RECV_PAUSE|KEEP_RECV_HOLD)))
- /* Unless paused - in an HTTP/2 connection we can basically always get a
- frame so we should always be ready for one */
- bitmap |= GETSOCK_READSOCK(0);
-
- /* we're (still uploading OR the HTTP/2 layer wants to send data) AND
- there's a window to send data in */
- if((((k->keepon & KEEP_SENDBITS) == KEEP_SEND) ||
- nghttp2_session_want_write(ctx->h2)) &&
- (nghttp2_session_get_remote_window_size(ctx->h2) &&
- nghttp2_session_get_stream_remote_window_size(ctx->h2,
- stream->id)))
- bitmap |= GETSOCK_WRITESOCK(0);
+ if(!ctx->h2)
+ return;
- CF_DATA_RESTORE(cf, save);
- return bitmap;
-}
+ sock = Curl_conn_cf_get_socket(cf, data);
+ Curl_pollset_check(data, ps, sock, &want_recv, &want_send);
+ if(want_recv || want_send) {
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ struct cf_call_data save;
+ bool c_exhaust, s_exhaust;
+ CF_DATA_SAVE(save, cf, data);
+ c_exhaust = want_send && !nghttp2_session_get_remote_window_size(ctx->h2);
+ s_exhaust = want_send && stream && stream->id >= 0 &&
+ !nghttp2_session_get_stream_remote_window_size(ctx->h2,
+ stream->id);
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ (!c_exhaust && nghttp2_session_want_write(ctx->h2));
+
+ Curl_pollset_set(data, ps, sock, want_recv, want_send);
+ CF_DATA_RESTORE(cf, save);
+ }
+}
static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
@@ -2511,14 +2506,15 @@ static CURLcode cf_h2_cntrl(struct Curl_cfilter *cf,
case CF_CTRL_DATA_PAUSE:
result = http2_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DONE_SEND: {
+ case CF_CTRL_DATA_DONE_SEND:
result = http2_data_done_send(cf, data);
break;
- }
- case CF_CTRL_DATA_DONE: {
+ case CF_CTRL_DATA_DETACH:
+ http2_data_done(cf, data, TRUE);
+ break;
+ case CF_CTRL_DATA_DONE:
http2_data_done(cf, data, arg1 != 0);
break;
- }
default:
break;
}
@@ -2606,7 +2602,7 @@ struct Curl_cftype Curl_cft_nghttp2 = {
cf_h2_connect,
cf_h2_close,
Curl_cf_def_get_host,
- cf_h2_get_select_socks,
+ cf_h2_adjust_pollset,
cf_h2_data_pending,
cf_h2_send,
cf_h2_recv,
@@ -2626,7 +2622,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(data->conn);
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
@@ -2652,7 +2648,7 @@ static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf,
CURLcode result = CURLE_OUT_OF_MEMORY;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx)
goto out;
diff --git a/lib/http_aws_sigv4.c b/lib/http_aws_sigv4.c
index 901c22fbb..c9382918e 100644
--- a/lib/http_aws_sigv4.c
+++ b/lib/http_aws_sigv4.c
@@ -247,7 +247,7 @@ static CURLcode make_headers(struct Curl_easy *data,
}
else {
char *value;
-
+ char *endp;
value = strchr(*date_header, ':');
if(!value) {
*date_header = NULL;
@@ -256,8 +256,17 @@ static CURLcode make_headers(struct Curl_easy *data,
++value;
while(ISBLANK(*value))
++value;
- strncpy(timestamp, value, TIMESTAMP_SIZE - 1);
- timestamp[TIMESTAMP_SIZE - 1] = 0;
+ endp = value;
+ while(*endp && ISALNUM(*endp))
+ ++endp;
+ /* 16 bytes => "19700101T000000Z" */
+ if((endp - value) == TIMESTAMP_SIZE - 1) {
+ memcpy(timestamp, value, TIMESTAMP_SIZE - 1);
+ timestamp[TIMESTAMP_SIZE - 1] = 0;
+ }
+ else
+ /* bad timestamp length */
+ timestamp[0] = 0;
*date_header = NULL;
}
@@ -456,6 +465,7 @@ static CURLcode canon_query(struct Curl_easy *data,
for(i = 0; !result && (i < entry); i++, ap++) {
size_t len;
const char *q = ap->p;
+ bool found_equals = false;
if(!ap->len)
continue;
for(len = ap->len; len && !result; q++, len--) {
@@ -467,9 +477,13 @@ static CURLcode canon_query(struct Curl_easy *data,
case '.':
case '_':
case '~':
+ /* allowed as-is */
+ result = Curl_dyn_addn(dq, q, 1);
+ break;
case '=':
/* allowed as-is */
result = Curl_dyn_addn(dq, q, 1);
+ found_equals = true;
break;
case '%':
/* uppercase the following if hexadecimal */
@@ -497,7 +511,11 @@ static CURLcode canon_query(struct Curl_easy *data,
}
}
}
- if(i < entry - 1) {
+ if(!result && !found_equals) {
+ /* queries without value still need an equals */
+ result = Curl_dyn_addn(dq, "=", 1);
+ }
+ if(!result && i < entry - 1) {
/* insert ampersands between query pairs */
result = Curl_dyn_addn(dq, "&", 1);
}
@@ -596,7 +614,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
result = CURLE_URL_MALFORMAT;
goto fail;
}
- strncpy(service, hostname, len);
+ memcpy(service, hostname, len);
service[len] = '\0';
infof(data, "aws_sigv4: picked service %s from host", service);
@@ -615,7 +633,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
result = CURLE_URL_MALFORMAT;
goto fail;
}
- strncpy(region, reg, len);
+ memcpy(region, reg, len);
region[len] = '\0';
infof(data, "aws_sigv4: picked region %s from host", region);
}
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index 2a401d14c..039c179c4 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -75,86 +75,110 @@
*/
-#define isxdigit_ascii(x) Curl_isxdigit(x)
+void Curl_httpchunk_init(struct Curl_easy *data, struct Curl_chunker *ch,
+ bool ignore_body)
+{
+ (void)data;
+ ch->hexindex = 0; /* start at 0 */
+ ch->state = CHUNK_HEX; /* we get hex first! */
+ ch->last_code = CHUNKE_OK;
+ Curl_dyn_init(&ch->trailer, DYN_H1_TRAILER);
+ ch->ignore_body = ignore_body;
+}
-void Curl_httpchunk_init(struct Curl_easy *data)
+void Curl_httpchunk_reset(struct Curl_easy *data, struct Curl_chunker *ch,
+ bool ignore_body)
{
- struct connectdata *conn = data->conn;
- struct Curl_chunker *chunk = &conn->chunk;
- chunk->hexindex = 0; /* start at 0 */
- chunk->state = CHUNK_HEX; /* we get hex first! */
- Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
+ (void)data;
+ ch->hexindex = 0; /* start at 0 */
+ ch->state = CHUNK_HEX; /* we get hex first! */
+ ch->last_code = CHUNKE_OK;
+ Curl_dyn_reset(&ch->trailer);
+ ch->ignore_body = ignore_body;
}
-/*
- * chunk_read() returns a OK for normal operations, or a positive return code
- * for errors. STOP means this sequence of chunks is complete. The 'wrote'
- * argument is set to tell the caller how many bytes we actually passed to the
- * client (for byte-counting and whatever).
- *
- * The states and the state-machine is further explained in the header file.
- *
- * This function always uses ASCII hex values to accommodate non-ASCII hosts.
- * For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
- */
-CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
- char *datap,
- ssize_t datalen,
- ssize_t *wrote,
- CURLcode *extrap)
+void Curl_httpchunk_free(struct Curl_easy *data, struct Curl_chunker *ch)
+{
+ (void)data;
+ Curl_dyn_free(&ch->trailer);
+}
+
+bool Curl_httpchunk_is_done(struct Curl_easy *data, struct Curl_chunker *ch)
+{
+ (void)data;
+ return ch->state == CHUNK_DONE;
+}
+
+static CURLcode httpchunk_readwrite(struct Curl_easy *data,
+ struct Curl_chunker *ch,
+ struct Curl_cwriter *cw_next,
+ const char *buf, size_t blen,
+ size_t *pconsumed)
{
CURLcode result = CURLE_OK;
- struct connectdata *conn = data->conn;
- struct Curl_chunker *ch = &conn->chunk;
- struct SingleRequest *k = &data->req;
size_t piece;
- curl_off_t length = (curl_off_t)datalen;
- *wrote = 0; /* nothing's written yet */
+ *pconsumed = 0; /* nothing's written yet */
+ /* first check terminal states that will not progress anywhere */
+ if(ch->state == CHUNK_DONE)
+ return CURLE_OK;
+ if(ch->state == CHUNK_FAILED)
+ return CURLE_RECV_ERROR;
/* the original data is written to the client, but we go on with the
chunk read process, to properly calculate the content length */
- if(data->set.http_te_skip && !k->ignorebody) {
- result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
+ if(data->set.http_te_skip && !ch->ignore_body) {
+ if(cw_next)
+ result = Curl_cwriter_write(data, cw_next, CLIENTWRITE_BODY, buf, blen);
+ else
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)buf, blen);
if(result) {
- *extrap = result;
- return CHUNKE_PASSTHRU_ERROR;
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_PASSTHRU_ERROR;
+ return result;
}
}
- while(length) {
+ while(blen) {
switch(ch->state) {
case CHUNK_HEX:
- if(ISXDIGIT(*datap)) {
- if(ch->hexindex < CHUNK_MAXNUM_LEN) {
- ch->hexbuffer[ch->hexindex] = *datap;
- datap++;
- length--;
- ch->hexindex++;
- }
- else {
- return CHUNKE_TOO_LONG_HEX; /* longer hex than we support */
+ if(ISXDIGIT(*buf)) {
+ if(ch->hexindex >= CHUNK_MAXNUM_LEN) {
+ failf(data, "chunk hex-length longer than %d", CHUNK_MAXNUM_LEN);
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_TOO_LONG_HEX; /* longer than we support */
+ return CURLE_RECV_ERROR;
}
+ ch->hexbuffer[ch->hexindex++] = *buf;
+ buf++;
+ blen--;
}
else {
char *endptr;
- if(0 == ch->hexindex)
+ if(0 == ch->hexindex) {
/* This is illegal data, we received junk where we expected
a hexadecimal digit. */
- return CHUNKE_ILLEGAL_HEX;
+ failf(data, "chunk hex-length char not a hex digit: 0x%x", *buf);
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_ILLEGAL_HEX;
+ return CURLE_RECV_ERROR;
+ }
- /* length and datap are unmodified */
+ /* blen and buf are unmodified */
ch->hexbuffer[ch->hexindex] = 0;
-
- if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
- return CHUNKE_ILLEGAL_HEX;
+ if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize)) {
+ failf(data, "chunk hex-length not valid: '%s'", ch->hexbuffer);
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_ILLEGAL_HEX;
+ return CURLE_RECV_ERROR;
+ }
ch->state = CHUNK_LF; /* now wait for the CRLF */
}
break;
case CHUNK_LF:
/* waiting for the LF after a chunk size */
- if(*datap == 0x0a) {
+ if(*buf == 0x0a) {
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
ch->state = CHUNK_TRAILER; /* now check for trailers */
@@ -163,30 +187,37 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
ch->state = CHUNK_DATA;
}
- datap++;
- length--;
+ buf++;
+ blen--;
break;
case CHUNK_DATA:
- /* We expect 'datasize' of data. We have 'length' right now, it can be
+ /* We expect 'datasize' of data. We have 'blen' right now, it can be
more or less than 'datasize'. Get the smallest piece.
*/
- piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
+ piece = blen;
+ if(ch->datasize < (curl_off_t)blen)
+ piece = curlx_sotouz(ch->datasize);
/* Write the data portion available */
- if(!data->set.http_te_skip && !k->ignorebody) {
- result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
-
+ if(!data->set.http_te_skip && !ch->ignore_body) {
+ if(cw_next)
+ result = Curl_cwriter_write(data, cw_next, CLIENTWRITE_BODY,
+ buf, piece);
+ else
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ (char *)buf, piece);
if(result) {
- *extrap = result;
- return CHUNKE_PASSTHRU_ERROR;
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_PASSTHRU_ERROR;
+ return result;
}
}
- *wrote += piece;
+ *pconsumed += piece;
ch->datasize -= piece; /* decrease amount left to expect */
- datap += piece; /* move read pointer forward */
- length -= piece; /* decrease space left in this round */
+ buf += piece; /* move read pointer forward */
+ blen -= piece; /* decrease space left in this round */
if(0 == ch->datasize)
/* end of data this round, we now expect a trailing CRLF */
@@ -194,42 +225,55 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
break;
case CHUNK_POSTLF:
- if(*datap == 0x0a) {
+ if(*buf == 0x0a) {
/* The last one before we go back to hex state and start all over. */
- Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */
+ Curl_httpchunk_reset(data, ch, ch->ignore_body);
}
- else if(*datap != 0x0d)
- return CHUNKE_BAD_CHUNK;
- datap++;
- length--;
+ else if(*buf != 0x0d) {
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_BAD_CHUNK;
+ return CURLE_RECV_ERROR;
+ }
+ buf++;
+ blen--;
break;
case CHUNK_TRAILER:
- if((*datap == 0x0d) || (*datap == 0x0a)) {
- char *tr = Curl_dyn_ptr(&conn->trailer);
+ if((*buf == 0x0d) || (*buf == 0x0a)) {
+ char *tr = Curl_dyn_ptr(&ch->trailer);
/* this is the end of a trailer, but if the trailer was zero bytes
there was no trailer and we move on */
if(tr) {
size_t trlen;
- result = Curl_dyn_addn(&conn->trailer, (char *)STRCONST("\x0d\x0a"));
- if(result)
- return CHUNKE_OUT_OF_MEMORY;
-
- tr = Curl_dyn_ptr(&conn->trailer);
- trlen = Curl_dyn_len(&conn->trailer);
+ result = Curl_dyn_addn(&ch->trailer, (char *)STRCONST("\x0d\x0a"));
+ if(result) {
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_OUT_OF_MEMORY;
+ return result;
+ }
+ tr = Curl_dyn_ptr(&ch->trailer);
+ trlen = Curl_dyn_len(&ch->trailer);
if(!data->set.http_te_skip) {
- result = Curl_client_write(data,
- CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER,
- tr, trlen);
+ if(cw_next)
+ result = Curl_cwriter_write(data, cw_next,
+ CLIENTWRITE_HEADER|
+ CLIENTWRITE_TRAILER,
+ tr, trlen);
+ else
+ result = Curl_client_write(data,
+ CLIENTWRITE_HEADER|
+ CLIENTWRITE_TRAILER,
+ tr, trlen);
if(result) {
- *extrap = result;
- return CHUNKE_PASSTHRU_ERROR;
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_PASSTHRU_ERROR;
+ return result;
}
}
- Curl_dyn_reset(&conn->trailer);
+ Curl_dyn_reset(&ch->trailer);
ch->state = CHUNK_TRAILER_CR;
- if(*datap == 0x0a)
+ if(*buf == 0x0a)
/* already on the LF */
break;
}
@@ -240,59 +284,73 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
}
}
else {
- result = Curl_dyn_addn(&conn->trailer, datap, 1);
- if(result)
- return CHUNKE_OUT_OF_MEMORY;
+ result = Curl_dyn_addn(&ch->trailer, buf, 1);
+ if(result) {
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_OUT_OF_MEMORY;
+ return result;
+ }
}
- datap++;
- length--;
+ buf++;
+ blen--;
break;
case CHUNK_TRAILER_CR:
- if(*datap == 0x0a) {
+ if(*buf == 0x0a) {
ch->state = CHUNK_TRAILER_POSTCR;
- datap++;
- length--;
+ buf++;
+ blen--;
+ }
+ else {
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_BAD_CHUNK;
+ return CURLE_RECV_ERROR;
}
- else
- return CHUNKE_BAD_CHUNK;
break;
case CHUNK_TRAILER_POSTCR:
/* We enter this state when a CR should arrive so we expect to
have to first pass a CR before we wait for LF */
- if((*datap != 0x0d) && (*datap != 0x0a)) {
+ if((*buf != 0x0d) && (*buf != 0x0a)) {
/* not a CR then it must be another header in the trailer */
ch->state = CHUNK_TRAILER;
break;
}
- if(*datap == 0x0d) {
+ if(*buf == 0x0d) {
/* skip if CR */
- datap++;
- length--;
+ buf++;
+ blen--;
}
/* now wait for the final LF */
ch->state = CHUNK_STOP;
break;
case CHUNK_STOP:
- if(*datap == 0x0a) {
- length--;
-
+ if(*buf == 0x0a) {
+ blen--;
/* Record the length of any data left in the end of the buffer
even if there's no more chunks to read */
- ch->datasize = curlx_sotouz(length);
-
- return CHUNKE_STOP; /* return stop */
+ ch->datasize = blen;
+ ch->state = CHUNK_DONE;
+ return CURLE_OK;
+ }
+ else {
+ ch->state = CHUNK_FAILED;
+ ch->last_code = CHUNKE_BAD_CHUNK;
+ return CURLE_RECV_ERROR;
}
- else
- return CHUNKE_BAD_CHUNK;
+ case CHUNK_DONE:
+ return CURLE_OK;
+
+ case CHUNK_FAILED:
+ return CURLE_RECV_ERROR;
}
+
}
- return CHUNKE_OK;
+ return CURLE_OK;
}
-const char *Curl_chunked_strerror(CHUNKcode code)
+static const char *Curl_chunked_strerror(CHUNKcode code)
{
switch(code) {
default:
@@ -304,8 +362,7 @@ const char *Curl_chunked_strerror(CHUNKcode code)
case CHUNKE_BAD_CHUNK:
return "Malformed encoding found";
case CHUNKE_PASSTHRU_ERROR:
- DEBUGASSERT(0); /* never used */
- return "";
+ return "Error writing data to client";
case CHUNKE_BAD_ENCODING:
return "Bad content-encoding found";
case CHUNKE_OUT_OF_MEMORY:
@@ -313,4 +370,86 @@ const char *Curl_chunked_strerror(CHUNKcode code)
}
}
+CURLcode Curl_httpchunk_read(struct Curl_easy *data,
+ struct Curl_chunker *ch,
+ char *buf, size_t blen,
+ size_t *pconsumed)
+{
+ return httpchunk_readwrite(data, ch, NULL, buf, blen, pconsumed);
+}
+
+struct chunked_writer {
+ struct Curl_cwriter super;
+ struct Curl_chunker ch;
+};
+
+static CURLcode cw_chunked_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
+{
+ struct chunked_writer *ctx = (struct chunked_writer *)writer;
+
+ data->req.chunk = TRUE; /* chunks coming our way. */
+ Curl_httpchunk_init(data, &ctx->ch, FALSE);
+ return CURLE_OK;
+}
+
+static void cw_chunked_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
+{
+ struct chunked_writer *ctx = (struct chunked_writer *)writer;
+ Curl_httpchunk_free(data, &ctx->ch);
+}
+
+static CURLcode cw_chunked_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t blen)
+{
+ struct chunked_writer *ctx = (struct chunked_writer *)writer;
+ CURLcode result;
+ size_t consumed;
+
+ if(!(type & CLIENTWRITE_BODY))
+ return Curl_cwriter_write(data, writer->next, type, buf, blen);
+
+ consumed = 0;
+ result = httpchunk_readwrite(data, &ctx->ch, writer->next, buf, blen,
+ &consumed);
+
+ if(result) {
+ if(CHUNKE_PASSTHRU_ERROR == ctx->ch.last_code) {
+ failf(data, "Failed reading the chunked-encoded stream");
+ }
+ else {
+ failf(data, "%s in chunked-encoding",
+ Curl_chunked_strerror(ctx->ch.last_code));
+ }
+ return result;
+ }
+
+ blen -= consumed;
+ if(CHUNK_DONE == ctx->ch.state) {
+ /* chunks read successfully, download is complete */
+ data->req.download_done = TRUE;
+ if(blen) {
+ infof(data, "Leftovers after chunking: %zu bytes", blen);
+ }
+ }
+ else if((type & CLIENTWRITE_EOS) && !data->req.no_body) {
+ failf(data, "transfer closed with outstanding read data remaining");
+ return CURLE_PARTIAL_FILE;
+ }
+
+ return CURLE_OK;
+}
+
+/* HTTP chunked Transfer-Encoding decoder */
+const struct Curl_cwtype Curl_httpchunk_unencoder = {
+ "chunked",
+ NULL,
+ cw_chunked_init,
+ cw_chunked_write,
+ cw_chunked_close,
+ sizeof(struct chunked_writer)
+};
+
#endif /* CURL_DISABLE_HTTP */
diff --git a/lib/http_chunks.h b/lib/http_chunks.h
index ed5071316..07f2984c3 100644
--- a/lib/http_chunks.h
+++ b/lib/http_chunks.h
@@ -24,6 +24,10 @@
*
***************************************************************************/
+#ifndef CURL_DISABLE_HTTP
+
+#include "dynbuf.h"
+
struct connectdata;
/*
@@ -67,34 +71,68 @@ typedef enum {
signalled If this is an empty trailer CHUNKE_STOP will be signalled.
Otherwise the trailer will be broadcasted via Curl_client_write() and the
next state will be CHUNK_TRAILER */
- CHUNK_TRAILER_POSTCR
+ CHUNK_TRAILER_POSTCR,
+
+ /* Successfully de-chunked everything */
+ CHUNK_DONE,
+
+ /* Failed on seeing a bad or not correctly terminated chunk */
+ CHUNK_FAILED
} ChunkyState;
typedef enum {
- CHUNKE_STOP = -1,
CHUNKE_OK = 0,
CHUNKE_TOO_LONG_HEX = 1,
CHUNKE_ILLEGAL_HEX,
CHUNKE_BAD_CHUNK,
CHUNKE_BAD_ENCODING,
CHUNKE_OUT_OF_MEMORY,
- CHUNKE_PASSTHRU_ERROR, /* Curl_httpchunk_read() returns a CURLcode to use */
- CHUNKE_LAST
+ CHUNKE_PASSTHRU_ERROR /* Curl_httpchunk_read() returns a CURLcode to use */
} CHUNKcode;
-const char *Curl_chunked_strerror(CHUNKcode code);
-
struct Curl_chunker {
curl_off_t datasize;
ChunkyState state;
+ CHUNKcode last_code;
+ struct dynbuf trailer; /* for chunked-encoded trailer */
unsigned char hexindex;
- char hexbuffer[ CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */
+ char hexbuffer[CHUNK_MAXNUM_LEN + 1]; /* +1 for null-terminator */
+ BIT(ignore_body); /* never write response body data */
};
/* The following functions are defined in http_chunks.c */
-void Curl_httpchunk_init(struct Curl_easy *data);
-CHUNKcode Curl_httpchunk_read(struct Curl_easy *data, char *datap,
- ssize_t length, ssize_t *wrote,
- CURLcode *passthru);
+void Curl_httpchunk_init(struct Curl_easy *data, struct Curl_chunker *ch,
+ bool ignore_body);
+void Curl_httpchunk_free(struct Curl_easy *data, struct Curl_chunker *ch);
+void Curl_httpchunk_reset(struct Curl_easy *data, struct Curl_chunker *ch,
+ bool ignore_body);
+
+/*
+ * Read BODY bytes in HTTP/1.1 chunked encoding from `buf` and return
+ * the amount of bytes consumed. The actual response bytes and trailer
+ * headers are written out to the client.
+ * On success, this will consume all bytes up to the end of the response,
+ * e.g. the last chunk, has been processed.
+ * @param data the transfer involved
+ * @param ch the chunker instance keeping state across calls
+ * @param buf the response data
+ * @param blen amount of bytes in `buf`
+ * @param pconsumed on successful return, the number of bytes in `buf`
+ * consumed
+ *
+ * This function always uses ASCII hex values to accommodate non-ASCII hosts.
+ * For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
+ */
+CURLcode Curl_httpchunk_read(struct Curl_easy *data, struct Curl_chunker *ch,
+ char *buf, size_t blen, size_t *pconsumed);
+
+/**
+ * @return TRUE iff chunked decoded has finished successfully.
+ */
+bool Curl_httpchunk_is_done(struct Curl_easy *data, struct Curl_chunker *ch);
+
+extern const struct Curl_cwtype Curl_httpchunk_unencoder;
+
+#endif /* !CURL_DISABLE_HTTP */
#endif /* HEADER_CURL_HTTP_CHUNKS_H */
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index a1d6da954..113c43a41 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -131,8 +131,8 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
goto out;
}
- if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent"))
- && data->set.str[STRING_USERAGENT]) {
+ if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent")) &&
+ data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) {
result = Curl_dynhds_cadd(&req->headers, "User-Agent",
data->set.str[STRING_USERAGENT]);
if(result)
@@ -299,7 +299,7 @@ struct Curl_cftype Curl_cft_http_proxy = {
http_proxy_cf_connect,
http_proxy_cf_close,
Curl_cf_http_proxy_get_host,
- Curl_cf_def_get_select_socks,
+ Curl_cf_def_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
diff --git a/lib/idn.c b/lib/idn.c
index a024691d1..81a177f8c 100644
--- a/lib/idn.c
+++ b/lib/idn.c
@@ -36,7 +36,7 @@
#ifdef USE_LIBIDN2
#include <idn2.h>
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
#define IDN2_LOOKUP(name, host, flags) \
idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
#else
diff --git a/lib/imap.c b/lib/imap.c
index de64c2a7f..f9211d966 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -97,7 +97,8 @@ static CURLcode imap_doing(struct Curl_easy *data, bool *dophase_done);
static CURLcode imap_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
static char *imap_atom(const char *str, bool escape_only);
-static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...);
+static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
+ CURL_PRINTF(2, 3);
static CURLcode imap_parse_url_options(struct connectdata *conn);
static CURLcode imap_parse_url_path(struct Curl_easy *data);
static CURLcode imap_parse_custom_request(struct Curl_easy *data);
@@ -129,7 +130,7 @@ const struct Curl_handler Curl_handler_imap = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
imap_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_IMAP, /* defport */
@@ -158,7 +159,7 @@ const struct Curl_handler Curl_handler_imaps = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
imap_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_IMAPS, /* defport */
@@ -354,8 +355,8 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn,
*/
static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
{
- char *message = data->state.buffer;
- size_t len = strlen(message);
+ char *message = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
+ size_t len = data->conn->proto.imapc.pp.nfinal;
if(len > 2) {
/* Find the start of the message */
@@ -895,7 +896,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct imap_conn *imapc = &conn->proto.imapc;
- const char *line = data->state.buffer;
+ const char *line = Curl_dyn_ptr(&imapc->pp.recvbuf);
(void)instate; /* no use for this yet */
@@ -981,7 +982,7 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
/* Pipelining in response is forbidden. */
- if(data->conn->proto.imapc.pp.cache_size)
+ if(data->conn->proto.imapc.pp.overflow)
return CURLE_WEIRD_SERVER_REPLY;
if(imapcode != IMAP_RESP_OK) {
@@ -1057,17 +1058,13 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
imapstate instate)
{
CURLcode result = CURLE_OK;
- char *line = data->state.buffer;
- size_t len = strlen(line);
+ char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
+ size_t len = data->conn->proto.imapc.pp.nfinal;
(void)instate; /* No use for this yet */
- if(imapcode == '*') {
- /* Temporarily add the LF character back and send as body to the client */
- line[len] = '\n';
- result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
- line[len] = '\0';
- }
+ if(imapcode == '*')
+ result = Curl_client_write(data, CLIENTWRITE_BODY, line, len);
else if(imapcode != IMAP_RESP_OK)
result = CURLE_QUOTE_ERROR;
else
@@ -1085,7 +1082,7 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
struct connectdata *conn = data->conn;
struct IMAP *imap = data->req.p.imap;
struct imap_conn *imapc = &conn->proto.imapc;
- const char *line = data->state.buffer;
+ const char *line = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
(void)instate; /* no use for this yet */
@@ -1144,7 +1141,8 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
- const char *ptr = data->state.buffer;
+ const char *ptr = Curl_dyn_ptr(&data->conn->proto.imapc.pp.recvbuf);
+ size_t len = data->conn->proto.imapc.pp.nfinal;
bool parsed = FALSE;
curl_off_t size = 0;
@@ -1158,16 +1156,12 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
/* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
the continuation data contained within the curly brackets */
- while(*ptr && (*ptr != '{'))
- ptr++;
-
- if(*ptr == '{') {
+ ptr = memchr(ptr, '{', len);
+ if(ptr) {
char *endptr;
- if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size)) {
- if(endptr - ptr > 1 && endptr[0] == '}' &&
- endptr[1] == '\r' && endptr[2] == '\0')
- parsed = TRUE;
- }
+ if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size) &&
+ (endptr - ptr > 1 && *endptr == '}'))
+ parsed = TRUE;
}
if(parsed) {
@@ -1175,11 +1169,15 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
size);
Curl_pgrsSetDownloadSize(data, size);
- if(pp->cache) {
- /* At this point there is a bunch of data in the header "cache" that is
- actually body content, send it as body and then skip it. Do note
- that there may even be additional "headers" after the body. */
- size_t chunk = pp->cache_size;
+ if(pp->overflow) {
+ /* At this point there is a data in the receive buffer that is body
+ content, send it as body and then skip it. Do note that there may
+ even be additional "headers" after the body. */
+ size_t chunk = pp->overflow;
+
+ /* keep only the overflow */
+ Curl_dyn_tail(&pp->recvbuf, chunk);
+ pp->nfinal = 0; /* done */
if(chunk > (size_t)size)
/* The conversion from curl_off_t to size_t is always fine here */
@@ -1190,27 +1188,24 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
imap_state(data, IMAP_STOP);
return CURLE_OK;
}
- result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
+ result = Curl_client_write(data, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&pp->recvbuf), chunk);
if(result)
return result;
- data->req.bytecount += chunk;
-
infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
" bytes are left for transfer", chunk, size - chunk);
- /* Have we used the entire cache or just part of it?*/
- if(pp->cache_size > chunk) {
- /* Only part of it so shrink the cache to fit the trailing data */
- memmove(pp->cache, pp->cache + chunk, pp->cache_size - chunk);
- pp->cache_size -= chunk;
+ /* Have we used the entire overflow or just part of it?*/
+ if(pp->overflow > chunk) {
+ /* remember the remaining trailing overflow data */
+ pp->overflow -= chunk;
+ Curl_dyn_tail(&pp->recvbuf, pp->overflow);
}
else {
+ pp->overflow = 0; /* handled */
/* Free the cache */
- Curl_safefree(pp->cache);
-
- /* Reset the cache size */
- pp->cache_size = 0;
+ Curl_dyn_reset(&pp->recvbuf);
}
}
@@ -1222,7 +1217,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
data->req.maxdownload = size;
/* force a recv/send check of this connection, as the data might've been
read off the socket already */
- data->conn->cselect_bits = CURL_CSELECT_IN;
+ data->state.select_bits = CURL_CSELECT_IN;
Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
}
}
@@ -1378,7 +1373,6 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
break;
case IMAP_LOGOUT:
- /* fallthrough, just stop! */
default:
/* internal error */
imap_state(data, IMAP_STOP);
@@ -1430,7 +1424,7 @@ static CURLcode imap_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct IMAP *imap;
- imap = data->req.p.imap = calloc(sizeof(struct IMAP), 1);
+ imap = data->req.p.imap = calloc(1, sizeof(struct IMAP));
if(!imap)
result = CURLE_OUT_OF_MEMORY;
@@ -1474,9 +1468,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
Curl_sasl_init(&imapc->sasl, data, &saslimap);
Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
- /* Initialise the pingpong layer */
- Curl_pp_setup(pp);
- Curl_pp_init(data, pp);
+ Curl_pp_init(pp);
/* Parse the URL options */
result = imap_parse_url_options(conn);
@@ -1797,7 +1789,14 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
if(!result) {
va_list ap;
va_start(ap, fmt);
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
result = Curl_pp_vsendf(data, &imapc->pp, Curl_dyn_ptr(&imapc->dyn), ap);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
va_end(ap);
}
return result;
diff --git a/lib/inet_pton.c b/lib/inet_pton.c
index 7d3c69879..176cc956f 100644
--- a/lib/inet_pton.c
+++ b/lib/inet_pton.c
@@ -112,7 +112,8 @@ inet_pton4(const char *src, unsigned char *dst)
pch = strchr(digits, ch);
if(pch) {
- unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
+ unsigned int val = (unsigned int)(*tp * 10) +
+ (unsigned int)(pch - digits);
if(saw_digit && *tp == 0)
return (0);
diff --git a/lib/inet_pton.h b/lib/inet_pton.h
index 82fde7e2e..f8562fa8a 100644
--- a/lib/inet_pton.h
+++ b/lib/inet_pton.h
@@ -31,9 +31,6 @@ int Curl_inet_pton(int, const char *, void *);
#ifdef HAVE_INET_PTON
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
-#elif defined(HAVE_WS2TCPIP_H)
-/* inet_pton() exists in Vista or later */
-#include <ws2tcpip.h>
#endif
#define Curl_inet_pton(x,y,z) inet_pton(x,y,z)
#endif
diff --git a/lib/krb5.c b/lib/krb5.c
index 18e73debb..4db19fb27 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -75,8 +75,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
unsigned char data_sec = conn->data_prot;
#endif
- if(!cmd)
- return CURLE_BAD_FUNCTION_ARGUMENT;
+ DEBUGASSERT(cmd);
write_len = strlen(cmd);
if(!write_len || write_len > (sizeof(s) -3))
@@ -236,9 +235,12 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
if(Curl_GetFTPResponse(data, &nread, NULL))
return -1;
-
- if(data->state.buffer[0] != '3')
- return -1;
+ else {
+ struct pingpong *pp = &conn->proto.ftpc.pp;
+ char *line = Curl_dyn_ptr(&pp->recvbuf);
+ if(line[0] != '3')
+ return -1;
+ }
}
stringp = aprintf("%s@%s", service, host);
@@ -322,15 +324,19 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
ret = -1;
break;
}
-
- if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3') {
- infof(data, "Server didn't accept auth data");
- ret = AUTH_ERROR;
- break;
+ else {
+ struct pingpong *pp = &conn->proto.ftpc.pp;
+ size_t len = Curl_dyn_len(&pp->recvbuf);
+ p = Curl_dyn_ptr(&pp->recvbuf);
+ if((len < 4) || (p[0] != '2' && p[0] != '3')) {
+ infof(data, "Server didn't accept auth data");
+ ret = AUTH_ERROR;
+ break;
+ }
}
_gssresp.value = NULL; /* make sure it is initialized */
- p = data->state.buffer + 4;
+ p += 4; /* over '789 ' */
p = strstr(p, "ADAT=");
if(p) {
result = Curl_base64_decode(p + 5,
@@ -417,7 +423,6 @@ static char level_to_char(int level)
case PROT_PRIVATE:
return 'P';
case PROT_CMD:
- /* Fall through */
default:
/* Those 2 cases should not be reached! */
break;
@@ -430,6 +435,9 @@ static char level_to_char(int level)
/* Send an FTP command defined by |message| and the optional arguments. The
function returns the ftp_code. If an error occurs, -1 is returned. */
static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
+ CURL_PRINTF(2, 3);
+
+static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
{
int ftp_code;
ssize_t nread = 0;
@@ -750,6 +758,8 @@ static int sec_set_protection_level(struct Curl_easy *data)
if(level) {
char *pbsz;
unsigned int buffer_size = 1 << 20; /* 1048576 */
+ struct pingpong *pp = &conn->proto.ftpc.pp;
+ char *line;
code = ftp_send_command(data, "PBSZ %u", buffer_size);
if(code < 0)
@@ -761,10 +771,11 @@ static int sec_set_protection_level(struct Curl_easy *data)
}
conn->buffer_size = buffer_size;
- pbsz = strstr(data->state.buffer, "PBSZ=");
+ line = Curl_dyn_ptr(&pp->recvbuf);
+ pbsz = strstr(line, "PBSZ=");
if(pbsz) {
/* stick to default value if the check fails */
- if(!strncmp(pbsz, "PBSZ=", 5) && ISDIGIT(pbsz[5]))
+ if(ISDIGIT(pbsz[5]))
buffer_size = atoi(&pbsz[5]);
if(buffer_size < conn->buffer_size)
conn->buffer_size = buffer_size;
diff --git a/lib/ldap.c b/lib/ldap.c
index 239d3fbf0..4c04647f4 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -137,7 +137,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp);
_ldap_trace x; \
} while(0)
- static void _ldap_trace(const char *fmt, ...);
+ static void _ldap_trace(const char *fmt, ...) CURL_PRINTF(1, 2);
#else
#define LDAP_TRACE(x) Curl_nop_stmt
#endif
@@ -177,7 +177,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_LDAP, /* defport */
@@ -205,7 +205,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_LDAPS, /* defport */
@@ -313,7 +313,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
int ldap_ssl = 0;
char *val_b64 = NULL;
size_t val_b64_sz = 0;
- curl_off_t dlsize = 0;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
struct timeval ldap_timeout = {10, 0}; /* 10 sec connection/search timeout */
#endif
@@ -327,7 +326,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
*done = TRUE; /* unconditionally */
infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d",
- LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
+ LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
infof(data, "LDAP local: %s", data->state.url);
#ifdef HAVE_LDAP_URL_PARSE
@@ -345,7 +344,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
if(conn->given->flags & PROTOPT_SSL)
ldap_ssl = 1;
infof(data, "LDAP local: trying to establish %s connection",
- ldap_ssl ? "encrypted" : "cleartext");
+ ldap_ssl ? "encrypted" : "cleartext");
#if defined(USE_WIN32_LDAP)
host = curlx_convert_UTF8_to_tchar(conn->host.name);
@@ -535,6 +534,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
+ Curl_pgrsSetDownloadCounter(data, 0);
rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);
@@ -596,8 +596,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
- dlsize += name_len + 5;
-
FREE_ON_WINLDAP(name);
ldap_memfree(dn);
}
@@ -659,8 +657,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
- dlsize += attr_len + 3;
-
if((attr_len > 7) &&
(strcmp(";binary", attr + (attr_len - 7)) == 0)) {
/* Binary attribute, encode to base64. */
@@ -689,8 +685,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
-
- dlsize += val_b64_sz;
}
}
else {
@@ -705,8 +699,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
-
- dlsize += vals[i]->bv_len;
}
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
@@ -719,8 +711,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
-
- dlsize++;
}
/* Free memory used to store values */
@@ -734,10 +724,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result)
goto quit;
- dlsize++;
- result = Curl_pgrsSetDownloadCounter(data, dlsize);
- if(result)
- goto quit;
}
if(ber)
diff --git a/lib/md4.c b/lib/md4.c
index 30ab62e60..067c211e4 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -32,9 +32,8 @@
#include "warnless.h"
#ifdef USE_OPENSSL
-#include <openssl/opensslconf.h>
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
- !defined(USE_AMISSL)
+#include <openssl/opensslv.h>
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) && !defined(USE_AMISSL)
/* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
#define OPENSSL_NO_MD4
#endif
@@ -195,11 +194,9 @@ static int MD4_Init(MD4_CTX *ctx)
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
{
if(!ctx->data) {
- ctx->data = malloc(size);
- if(ctx->data) {
- memcpy(ctx->data, data, size);
+ ctx->data = Curl_memdup(data, size);
+ if(ctx->data)
ctx->size = size;
- }
}
}
diff --git a/lib/memdebug.c b/lib/memdebug.c
index d6952a07a..fce933a32 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -208,7 +208,7 @@ ALLOC_FUNC char *curl_dbg_strdup(const char *str,
return mem;
}
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
int line, const char *source)
{
@@ -304,12 +304,6 @@ void curl_dbg_free(void *ptr, int line, const char *source)
curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
int line, const char *source)
{
- const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
- "FD %s:%d socket() = %d\n" :
- (sizeof(curl_socket_t) == sizeof(long)) ?
- "FD %s:%d socket() = %ld\n" :
- "FD %s:%d socket() = %zd\n";
-
curl_socket_t sockfd;
if(countcheck("socket", line, source))
@@ -318,7 +312,8 @@ curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
sockfd = socket(domain, type, protocol);
if(source && (sockfd != CURL_SOCKET_BAD))
- curl_dbg_log(fmt, source, line, sockfd);
+ curl_dbg_log("FD %s:%d socket() = %" CURL_FORMAT_SOCKET_T "\n",
+ source, line, sockfd);
return sockfd;
}
@@ -357,16 +352,12 @@ int curl_dbg_socketpair(int domain, int type, int protocol,
curl_socket_t socket_vector[2],
int line, const char *source)
{
- const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
- "FD %s:%d socketpair() = %d %d\n" :
- (sizeof(curl_socket_t) == sizeof(long)) ?
- "FD %s:%d socketpair() = %ld %ld\n" :
- "FD %s:%d socketpair() = %zd %zd\n";
-
int res = socketpair(domain, type, protocol, socket_vector);
if(source && (0 == res))
- curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]);
+ curl_dbg_log("FD %s:%d socketpair() = "
+ "%" CURL_FORMAT_SOCKET_T " %" CURL_FORMAT_SOCKET_T "\n",
+ source, line, socket_vector[0], socket_vector[1]);
return res;
}
@@ -375,19 +366,14 @@ int curl_dbg_socketpair(int domain, int type, int protocol,
curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
int line, const char *source)
{
- const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
- "FD %s:%d accept() = %d\n" :
- (sizeof(curl_socket_t) == sizeof(long)) ?
- "FD %s:%d accept() = %ld\n" :
- "FD %s:%d accept() = %zd\n";
-
struct sockaddr *addr = (struct sockaddr *)saddr;
curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
curl_socket_t sockfd = accept(s, addr, addrlen);
if(source && (sockfd != CURL_SOCKET_BAD))
- curl_dbg_log(fmt, source, line, sockfd);
+ curl_dbg_log("FD %s:%d accept() = %" CURL_FORMAT_SOCKET_T "\n",
+ source, line, sockfd);
return sockfd;
}
@@ -395,14 +381,9 @@ curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
/* separate function to allow libcurl to mark a "faked" close */
void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source)
{
- const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
- "FD %s:%d sclose(%d)\n":
- (sizeof(curl_socket_t) == sizeof(long)) ?
- "FD %s:%d sclose(%ld)\n":
- "FD %s:%d sclose(%zd)\n";
-
if(source)
- curl_dbg_log(fmt, source, line, sockfd);
+ curl_dbg_log("FD %s:%d sclose(%" CURL_FORMAT_SOCKET_T ")\n",
+ source, line, sockfd);
}
/* this is our own defined way to close sockets on *ALL* platforms */
diff --git a/lib/memdebug.h b/lib/memdebug.h
index c9eb5dc37..51147cdcb 100644
--- a/lib/memdebug.h
+++ b/lib/memdebug.h
@@ -64,7 +64,7 @@ CURL_EXTERN ALLOC_SIZE(2) void *curl_dbg_realloc(void *ptr,
CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
CURL_EXTERN ALLOC_FUNC char *curl_dbg_strdup(const char *str, int line,
const char *src);
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
int line,
const char *source);
@@ -72,7 +72,7 @@ CURL_EXTERN ALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
CURL_EXTERN void curl_dbg_memdebug(const char *logname);
CURL_EXTERN void curl_dbg_memlimit(long limit);
-CURL_EXTERN void curl_dbg_log(const char *format, ...);
+CURL_EXTERN void curl_dbg_log(const char *format, ...) CURL_PRINTF(1, 2);
/* file descriptor manipulators */
CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
@@ -121,7 +121,7 @@ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__)
#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__)
-#ifdef WIN32
+#ifdef _WIN32
# ifdef UNICODE
# undef wcsdup
# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
diff --git a/lib/mime.c b/lib/mime.c
index 3b27e59e1..d712331d0 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -30,6 +30,7 @@
#include "warnless.h"
#include "urldata.h"
#include "sendf.h"
+#include "strdup.h"
#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
!defined(CURL_DISABLE_SMTP) || \
@@ -48,7 +49,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef WIN32
+#ifdef _WIN32
# ifndef R_OK
# define R_OK 4
# endif
@@ -311,8 +312,7 @@ static char *escape_string(struct Curl_easy *data,
table = formtable;
/* data can be NULL when this function is called indirectly from
curl_formget(). */
- if(strategy == MIMESTRATEGY_MAIL ||
- (data && (data->set.mime_options & CURLMIMEOPT_FORMESCAPE)))
+ if(strategy == MIMESTRATEGY_MAIL || (data && (data->set.mime_formescape)))
table = mimetable;
Curl_dyn_init(&db, CURL_MAX_INPUT_LENGTH);
@@ -818,7 +818,7 @@ static size_t read_part_content(curl_mimepart *part,
case MIMEKIND_FILE:
if(part->fp && feof(part->fp))
break; /* At EOF. */
- /* FALLTHROUGH */
+ FALLTHROUGH();
default:
if(part->readfunc) {
if(!(part->flags & MIME_FAST_READ)) {
@@ -937,7 +937,7 @@ static size_t readback_part(curl_mimepart *part,
mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next);
break;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case MIMESTATE_CURLHEADERS:
if(!hdr)
mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders);
@@ -971,7 +971,7 @@ static size_t readback_part(curl_mimepart *part,
fclose(part->fp);
part->fp = NULL;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURL_READFUNC_ABORT:
case CURL_READFUNC_PAUSE:
case READ_ERROR:
@@ -1236,6 +1236,7 @@ CURLcode Curl_mime_duppart(struct Curl_easy *data,
}
break;
default: /* Invalid kind: should not occur. */
+ DEBUGF(infof(data, "invalid MIMEKIND* attempt"));
res = CURLE_BAD_FUNCTION_ARGUMENT; /* Internal error? */
break;
}
@@ -1371,27 +1372,22 @@ CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
/* Set mime part content from memory data. */
CURLcode curl_mime_data(curl_mimepart *part,
- const char *data, size_t datasize)
+ const char *ptr, size_t datasize)
{
if(!part)
return CURLE_BAD_FUNCTION_ARGUMENT;
cleanup_part_content(part);
- if(data) {
+ if(ptr) {
if(datasize == CURL_ZERO_TERMINATED)
- datasize = strlen(data);
+ datasize = strlen(ptr);
- part->data = malloc(datasize + 1);
+ part->data = Curl_memdup0(ptr, datasize);
if(!part->data)
return CURLE_OUT_OF_MEMORY;
part->datasize = datasize;
-
- if(datasize)
- memcpy(part->data, data, datasize);
- part->data[datasize] = '\0'; /* Set a null terminator as sentinel. */
-
part->readfunc = mime_mem_read;
part->seekfunc = mime_mem_seek;
part->freefunc = mime_mem_free;
diff --git a/lib/mime.h b/lib/mime.h
index 0a05c2a5a..a64f41d4b 100644
--- a/lib/mime.h
+++ b/lib/mime.h
@@ -130,7 +130,8 @@ struct curl_mimepart {
size_t lastreadstatus; /* Last read callback returned status. */
};
-CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
+ CURL_PRINTF(2, 3);
#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
!defined(CURL_DISABLE_SMTP) || \
diff --git a/lib/mprintf.c b/lib/mprintf.c
index af5d753d6..63f7f2409 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -20,25 +20,11 @@
*
* SPDX-License-Identifier: curl
*
- *
- * Purpose:
- * A merge of Bjorn Reese's format() function and Daniel's dsprintf()
- * 1.0. A full blooded printf() clone with full support for <num>$
- * everywhere (parameters, widths and precisions) including variabled
- * sized parameters (like doubles, long longs, long doubles and even
- * void * in 64-bit architectures).
- *
- * Current restrictions:
- * - Max 128 parameters
- * - No 'long double' support.
- *
- * If you ever want truly portable and good *printf() clones, the project that
- * took on from here is named 'Trio' and you find more details on the trio web
- * page at https://daniel.haxx.se/projects/trio/
*/
#include "curl_setup.h"
#include "dynbuf.h"
+#include "curl_printf.h"
#include <curl/mprintf.h>
#include "curl_memory.h"
@@ -66,9 +52,7 @@
* Non-ANSI integer extensions
*/
-#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
- (defined(__POCC__) && defined(_MSC_VER)) || \
- (defined(_WIN32_WCE)) || \
+#if (defined(_WIN32_WCE)) || \
(defined(__MINGW32__)) || \
(defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
# define MP_HAVE_INT_EXTENSIONS
@@ -88,7 +72,8 @@
#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
fit negative DBL_MAX (317 letters) */
-#define MAX_PARAMETERS 128 /* lame static limit */
+#define MAX_PARAMETERS 128 /* number of input arguments */
+#define MAX_SEGMENTS 128 /* number of output segments */
#ifdef __AMIGA__
# undef FORMAT_INT
@@ -100,31 +85,33 @@ static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
/* Upper-case digits. */
static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-#define OUTCHAR(x) \
- do { \
- if(stream((unsigned char)(x), (FILE *)data) != -1) \
- done++; \
- else \
- return done; /* return immediately on failure */ \
+#define OUTCHAR(x) \
+ do { \
+ if(!stream(x, userp)) \
+ done++; \
+ else \
+ return done; /* return on failure */ \
} while(0)
/* Data type to read from the arglist */
typedef enum {
- FORMAT_UNKNOWN = 0,
FORMAT_STRING,
FORMAT_PTR,
- FORMAT_INT,
FORMAT_INTPTR,
+ FORMAT_INT,
FORMAT_LONG,
FORMAT_LONGLONG,
+ FORMAT_INTU,
+ FORMAT_LONGU,
+ FORMAT_LONGLONGU,
FORMAT_DOUBLE,
FORMAT_LONGDOUBLE,
- FORMAT_WIDTH /* For internal use */
+ FORMAT_WIDTH,
+ FORMAT_PRECISION
} FormatType;
/* conversion and display flags */
enum {
- FLAGS_NEW = 0,
FLAGS_SPACE = 1<<0,
FLAGS_SHOWSIGN = 1<<1,
FLAGS_LEFT = 1<<2,
@@ -144,23 +131,40 @@ enum {
FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */
FLAGS_CHAR = 1<<17, /* %c story */
FLAGS_FLOATE = 1<<18, /* %e or %E */
- FLAGS_FLOATG = 1<<19 /* %g or %G */
+ FLAGS_FLOATG = 1<<19, /* %g or %G */
+ FLAGS_SUBSTR = 1<<20 /* no input, only substring */
};
-struct va_stack {
- FormatType type;
- int flags;
- long width; /* width OR width parameter number */
- long precision; /* precision OR precision parameter number */
+enum {
+ DOLLAR_UNKNOWN,
+ DOLLAR_NOPE,
+ DOLLAR_USE
+};
+
+/*
+ * Describes an input va_arg type and hold its value.
+ */
+struct va_input {
+ FormatType type; /* FormatType */
union {
char *str;
void *ptr;
- union {
- mp_intmax_t as_signed;
- mp_uintmax_t as_unsigned;
- } num;
+ mp_intmax_t nums; /* signed */
+ mp_uintmax_t numu; /* unsigned */
double dnum;
- } data;
+ } val;
+};
+
+/*
+ * Describes an output segment.
+ */
+struct outsegment {
+ int width; /* width OR width parameter number */
+ int precision; /* precision OR precision parameter number */
+ unsigned int flags;
+ unsigned int input; /* input argument array index */
+ char *start; /* format string start to output */
+ size_t outlen; /* number of bytes from the format string to output */
};
struct nsprintf {
@@ -171,118 +175,123 @@ struct nsprintf {
struct asprintf {
struct dynbuf *b;
- bool fail; /* if an alloc has failed and thus the output is not the complete
- data */
+ char merr;
};
-static long dprintf_DollarString(char *input, char **end)
-{
- int number = 0;
- while(ISDIGIT(*input)) {
- if(number < MAX_PARAMETERS) {
- number *= 10;
- number += *input - '0';
- }
- input++;
- }
- if(number <= MAX_PARAMETERS && ('$' == *input)) {
- *end = ++input;
- return number;
- }
- return 0;
-}
+/* the provided input number is 1-based but this returns the number 0-based.
-static bool dprintf_IsQualifierNoDollar(const char *fmt)
+ returns -1 if no valid number was provided.
+*/
+static int dollarstring(char *input, char **end)
{
-#if defined(MP_HAVE_INT_EXTENSIONS)
- if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
- return TRUE;
- }
-#endif
-
- switch(*fmt) {
- case '-': case '+': case ' ': case '#': case '.':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- case 'h': case 'l': case 'L': case 'z': case 'q':
- case '*': case 'O':
-#if defined(MP_HAVE_INT_EXTENSIONS)
- case 'I':
-#endif
- return TRUE;
+ if(ISDIGIT(*input)) {
+ int number = 0;
+ do {
+ if(number < MAX_PARAMETERS) {
+ number *= 10;
+ number += *input - '0';
+ }
+ input++;
+ } while(ISDIGIT(*input));
- default:
- return FALSE;
+ if(number && (number <= MAX_PARAMETERS) && ('$' == *input)) {
+ *end = ++input;
+ return number - 1;
+ }
}
+ return -1;
}
-/******************************************************************
+/*
+ * Parse the format string.
*
- * Pass 1:
- * Create an index with the type of each parameter entry and its
- * value (may vary in size)
+ * Create two arrays. One describes the inputs, one describes the outputs.
*
* Returns zero on success.
- *
- ******************************************************************/
+ */
-static int dprintf_Pass1(const char *format, struct va_stack *vto,
- char **endpos, va_list arglist)
+#define PFMT_OK 0
+#define PFMT_DOLLAR 1 /* bad dollar for main param */
+#define PFMT_DOLLARWIDTH 2 /* bad dollar use for width */
+#define PFMT_DOLLARPREC 3 /* bad dollar use for precision */
+#define PFMT_MANYARGS 4 /* too many input arguments used */
+#define PFMT_PREC 5 /* precision overflow */
+#define PFMT_PRECMIX 6 /* bad mix of precision specifiers */
+#define PFMT_WIDTH 7 /* width overflow */
+#define PFMT_INPUTGAP 8 /* gap in arguments */
+#define PFMT_WIDTHARG 9 /* attempted to use same arg twice, for width */
+#define PFMT_PRECARG 10 /* attempted to use same arg twice, for prec */
+#define PFMT_MANYSEGS 11 /* maxed out output segments */
+
+static int parsefmt(const char *format,
+ struct outsegment *out,
+ struct va_input *in,
+ int *opieces,
+ int *ipieces, va_list arglist)
{
char *fmt = (char *)format;
int param_num = 0;
- long this_param;
- long width;
- long precision;
- int flags;
- long max_param = 0;
- long i;
+ int param;
+ int width;
+ int precision;
+ unsigned int flags;
+ FormatType type;
+ int max_param = -1;
+ int i;
+ int ocount = 0;
+ unsigned char usedinput[MAX_PARAMETERS/8];
+ size_t outlen = 0;
+ struct outsegment *optr;
+ int use_dollar = DOLLAR_UNKNOWN;
+ char *start = fmt;
+
+ /* clear, set a bit for each used input */
+ memset(usedinput, 0, sizeof(usedinput));
while(*fmt) {
- if(*fmt++ == '%') {
+ if(*fmt == '%') {
+ struct va_input *iptr;
+ bool loopit = TRUE;
+ fmt++;
+ outlen = fmt - start - 1;
if(*fmt == '%') {
+ /* this means a %% that should be output only as %. Create an output
+ segment. */
+ if(outlen) {
+ optr = &out[ocount++];
+ if(ocount > MAX_SEGMENTS)
+ return PFMT_MANYSEGS;
+ optr->input = 0;
+ optr->flags = FLAGS_SUBSTR;
+ optr->start = start;
+ optr->outlen = outlen;
+ }
+ start = fmt;
fmt++;
continue; /* while */
}
- flags = FLAGS_NEW;
-
- /* Handle the positional case (N$) */
-
- param_num++;
-
- this_param = dprintf_DollarString(fmt, &fmt);
- if(0 == this_param)
- /* we got no positional, get the next counter */
- this_param = param_num;
-
- if(this_param > max_param)
- max_param = this_param;
+ flags = width = precision = 0;
- /*
- * The parameter with number 'i' should be used. Next, we need
- * to get SIZE and TYPE of the parameter. Add the information
- * to our array.
- */
+ if(use_dollar != DOLLAR_NOPE) {
+ param = dollarstring(fmt, &fmt);
+ if(param < 0) {
+ if(use_dollar == DOLLAR_USE)
+ /* illegal combo */
+ return PFMT_DOLLAR;
- width = 0;
- precision = 0;
-
- /* Handle the flags */
-
- while(dprintf_IsQualifierNoDollar(fmt)) {
-#if defined(MP_HAVE_INT_EXTENSIONS)
- if(!strncmp(fmt, "I32", 3)) {
- flags |= FLAGS_LONG;
- fmt += 3;
- }
- else if(!strncmp(fmt, "I64", 3)) {
- flags |= FLAGS_LONGLONG;
- fmt += 3;
+ /* we got no positional, just get the next arg */
+ param = -1;
+ use_dollar = DOLLAR_NOPE;
}
else
-#endif
+ use_dollar = DOLLAR_USE;
+ }
+ else
+ param = -1;
+ /* Handle the flags */
+ while(loopit) {
switch(*fmt++) {
case ' ':
flags |= FLAGS_SPACE;
@@ -300,40 +309,63 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
case '.':
if('*' == *fmt) {
/* The precision is picked from a specified parameter */
-
flags |= FLAGS_PRECPARAM;
fmt++;
- param_num++;
- i = dprintf_DollarString(fmt, &fmt);
- if(i)
- precision = i;
+ if(use_dollar == DOLLAR_USE) {
+ precision = dollarstring(fmt, &fmt);
+ if(precision < 0)
+ /* illegal combo */
+ return PFMT_DOLLARPREC;
+ }
else
- precision = param_num;
-
- if(precision > max_param)
- max_param = precision;
+ /* get it from the next argument */
+ precision = -1;
}
else {
+ bool is_neg = FALSE;
flags |= FLAGS_PREC;
- precision = strtol(fmt, &fmt, 10);
+ precision = 0;
+ if('-' == *fmt) {
+ is_neg = TRUE;
+ fmt++;
+ }
+ while(ISDIGIT(*fmt)) {
+ if(precision > INT_MAX/10)
+ return PFMT_PREC;
+ precision *= 10;
+ precision += *fmt - '0';
+ fmt++;
+ }
+ if(is_neg)
+ precision = -precision;
}
if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
(FLAGS_PREC | FLAGS_PRECPARAM))
/* it is not permitted to use both kinds of precision for the same
argument */
- return 1;
+ return PFMT_PRECMIX;
break;
case 'h':
flags |= FLAGS_SHORT;
break;
#if defined(MP_HAVE_INT_EXTENSIONS)
case 'I':
+ if((fmt[0] == '3') && (fmt[1] == '2')) {
+ flags |= FLAGS_LONG;
+ fmt += 2;
+ }
+ else if((fmt[0] == '6') && (fmt[1] == '4')) {
+ flags |= FLAGS_LONGLONG;
+ fmt += 2;
+ }
+ else {
#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
- flags |= FLAGS_LONGLONG;
+ flags |= FLAGS_LONGLONG;
#else
- flags |= FLAGS_LONG;
+ flags |= FLAGS_LONG;
#endif
+ }
break;
#endif
case 'l':
@@ -367,401 +399,421 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
case '0':
if(!(flags & FLAGS_LEFT))
flags |= FLAGS_PAD_NIL;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
flags |= FLAGS_WIDTH;
- width = strtol(fmt-1, &fmt, 10);
+ width = 0;
+ fmt--;
+ do {
+ if(width > INT_MAX/10)
+ return PFMT_WIDTH;
+ width *= 10;
+ width += *fmt - '0';
+ fmt++;
+ } while(ISDIGIT(*fmt));
break;
- case '*': /* Special case */
+ case '*': /* read width from argument list */
flags |= FLAGS_WIDTHPARAM;
- param_num++;
-
- i = dprintf_DollarString(fmt, &fmt);
- if(i)
- width = i;
+ if(use_dollar == DOLLAR_USE) {
+ width = dollarstring(fmt, &fmt);
+ if(width < 0)
+ /* illegal combo */
+ return PFMT_DOLLARWIDTH;
+ }
else
- width = param_num;
- if(width > max_param)
- max_param = width;
+ /* pick from the next argument */
+ width = -1;
break;
- case '\0':
- fmt--;
default:
+ loopit = FALSE;
+ fmt--;
break;
- }
- } /* switch */
-
- /* Handle the specifier */
-
- i = this_param - 1;
-
- if((i < 0) || (i >= MAX_PARAMETERS))
- /* out of allowed range */
- return 1;
+ } /* switch */
+ } /* while */
switch(*fmt) {
case 'S':
flags |= FLAGS_ALT;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case 's':
- vto[i].type = FORMAT_STRING;
+ type = FORMAT_STRING;
break;
case 'n':
- vto[i].type = FORMAT_INTPTR;
+ type = FORMAT_INTPTR;
break;
case 'p':
- vto[i].type = FORMAT_PTR;
+ type = FORMAT_PTR;
break;
- case 'd': case 'i':
- vto[i].type = FORMAT_INT;
+ case 'd':
+ case 'i':
+ if(flags & FLAGS_LONGLONG)
+ type = FORMAT_LONGLONG;
+ else if(flags & FLAGS_LONG)
+ type = FORMAT_LONG;
+ else
+ type = FORMAT_INT;
break;
case 'u':
- vto[i].type = FORMAT_INT;
+ if(flags & FLAGS_LONGLONG)
+ type = FORMAT_LONGLONGU;
+ else if(flags & FLAGS_LONG)
+ type = FORMAT_LONGU;
+ else
+ type = FORMAT_INTU;
flags |= FLAGS_UNSIGNED;
break;
case 'o':
- vto[i].type = FORMAT_INT;
+ type = FORMAT_INT;
flags |= FLAGS_OCTAL;
break;
case 'x':
- vto[i].type = FORMAT_INT;
+ type = FORMAT_INTU;
flags |= FLAGS_HEX|FLAGS_UNSIGNED;
break;
case 'X':
- vto[i].type = FORMAT_INT;
+ type = FORMAT_INTU;
flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
break;
case 'c':
- vto[i].type = FORMAT_INT;
+ type = FORMAT_INT;
flags |= FLAGS_CHAR;
break;
case 'f':
- vto[i].type = FORMAT_DOUBLE;
+ type = FORMAT_DOUBLE;
break;
case 'e':
- vto[i].type = FORMAT_DOUBLE;
+ type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATE;
break;
case 'E':
- vto[i].type = FORMAT_DOUBLE;
+ type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATE|FLAGS_UPPER;
break;
case 'g':
- vto[i].type = FORMAT_DOUBLE;
+ type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATG;
break;
case 'G':
- vto[i].type = FORMAT_DOUBLE;
+ type = FORMAT_DOUBLE;
flags |= FLAGS_FLOATG|FLAGS_UPPER;
break;
default:
- vto[i].type = FORMAT_UNKNOWN;
- break;
+ /* invalid instruction, disregard and continue */
+ continue;
} /* switch */
- vto[i].flags = flags;
- vto[i].width = width;
- vto[i].precision = precision;
-
if(flags & FLAGS_WIDTHPARAM) {
- /* we have the width specified from a parameter, so we make that
- parameter's info setup properly */
- long k = width - 1;
- if((k < 0) || (k >= MAX_PARAMETERS))
- /* out of allowed range */
- return 1;
- vto[i].width = k;
- vto[k].type = FORMAT_WIDTH;
- vto[k].flags = FLAGS_NEW;
- /* can't use width or precision of width! */
- vto[k].width = 0;
- vto[k].precision = 0;
+ if(width < 0)
+ width = param_num++;
+ else {
+ /* if this identifies a parameter already used, this
+ is illegal */
+ if(usedinput[width/8] & (1 << (width&7)))
+ return PFMT_WIDTHARG;
+ }
+ if(width >= MAX_PARAMETERS)
+ return PFMT_MANYARGS;
+ if(width >= max_param)
+ max_param = width;
+
+ in[width].type = FORMAT_WIDTH;
+ /* mark as used */
+ usedinput[width/8] |= (unsigned char)(1 << (width&7));
}
+
if(flags & FLAGS_PRECPARAM) {
- /* we have the precision specified from a parameter, so we make that
- parameter's info setup properly */
- long k = precision - 1;
- if((k < 0) || (k >= MAX_PARAMETERS))
- /* out of allowed range */
- return 1;
- vto[i].precision = k;
- vto[k].type = FORMAT_WIDTH;
- vto[k].flags = FLAGS_NEW;
- /* can't use width or precision of width! */
- vto[k].width = 0;
- vto[k].precision = 0;
+ if(precision < 0)
+ precision = param_num++;
+ else {
+ /* if this identifies a parameter already used, this
+ is illegal */
+ if(usedinput[precision/8] & (1 << (precision&7)))
+ return PFMT_PRECARG;
+ }
+ if(precision >= MAX_PARAMETERS)
+ return PFMT_MANYARGS;
+ if(precision >= max_param)
+ max_param = precision;
+
+ in[precision].type = FORMAT_PRECISION;
+ usedinput[precision/8] |= (unsigned char)(1 << (precision&7));
}
- *endpos++ = fmt + ((*fmt == '\0') ? 0 : 1); /* end of this sequence */
+
+ /* Handle the specifier */
+ if(param < 0)
+ param = param_num++;
+ if(param >= MAX_PARAMETERS)
+ return PFMT_MANYARGS;
+ if(param >= max_param)
+ max_param = param;
+
+ iptr = &in[param];
+ iptr->type = type;
+
+ /* mark this input as used */
+ usedinput[param/8] |= (unsigned char)(1 << (param&7));
+
+ fmt++;
+ optr = &out[ocount++];
+ if(ocount > MAX_SEGMENTS)
+ return PFMT_MANYSEGS;
+ optr->input = param;
+ optr->flags = flags;
+ optr->width = width;
+ optr->precision = precision;
+ optr->start = start;
+ optr->outlen = outlen;
+ start = fmt;
}
+ else
+ fmt++;
}
- /* Read the arg list parameters into our data list */
- for(i = 0; i<max_param; i++) {
- /* Width/precision arguments must be read before the main argument
- they are attached to */
- if(vto[i].flags & FLAGS_WIDTHPARAM) {
- vto[vto[i].width].data.num.as_signed =
- (mp_intmax_t)va_arg(arglist, int);
- }
- if(vto[i].flags & FLAGS_PRECPARAM) {
- vto[vto[i].precision].data.num.as_signed =
- (mp_intmax_t)va_arg(arglist, int);
- }
+ /* is there a trailing piece */
+ outlen = fmt - start;
+ if(outlen) {
+ optr = &out[ocount++];
+ if(ocount > MAX_SEGMENTS)
+ return PFMT_MANYSEGS;
+ optr->input = 0;
+ optr->flags = FLAGS_SUBSTR;
+ optr->start = start;
+ optr->outlen = outlen;
+ }
- switch(vto[i].type) {
+ /* Read the arg list parameters into our data list */
+ for(i = 0; i < max_param + 1; i++) {
+ struct va_input *iptr = &in[i];
+ if(!(usedinput[i/8] & (1 << (i&7))))
+ /* bad input */
+ return PFMT_INPUTGAP;
+
+ /* based on the type, read the correct argument */
+ switch(iptr->type) {
case FORMAT_STRING:
- vto[i].data.str = va_arg(arglist, char *);
+ iptr->val.str = va_arg(arglist, char *);
break;
case FORMAT_INTPTR:
- case FORMAT_UNKNOWN:
case FORMAT_PTR:
- vto[i].data.ptr = va_arg(arglist, void *);
+ iptr->val.ptr = va_arg(arglist, void *);
break;
- case FORMAT_INT:
-#ifdef HAVE_LONG_LONG_TYPE
- if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
- vto[i].data.num.as_unsigned =
- (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
- else if(vto[i].flags & FLAGS_LONGLONG)
- vto[i].data.num.as_signed =
- (mp_intmax_t)va_arg(arglist, mp_intmax_t);
- else
-#endif
- {
- if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
- vto[i].data.num.as_unsigned =
- (mp_uintmax_t)va_arg(arglist, unsigned long);
- else if(vto[i].flags & FLAGS_LONG)
- vto[i].data.num.as_signed =
- (mp_intmax_t)va_arg(arglist, long);
- else if(vto[i].flags & FLAGS_UNSIGNED)
- vto[i].data.num.as_unsigned =
- (mp_uintmax_t)va_arg(arglist, unsigned int);
- else
- vto[i].data.num.as_signed =
- (mp_intmax_t)va_arg(arglist, int);
- }
+ case FORMAT_LONGLONGU:
+ iptr->val.numu = (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
break;
- case FORMAT_DOUBLE:
- vto[i].data.dnum = va_arg(arglist, double);
+ case FORMAT_LONGLONG:
+ iptr->val.nums = (mp_intmax_t)va_arg(arglist, mp_intmax_t);
+ break;
+
+ case FORMAT_LONGU:
+ iptr->val.numu = (mp_uintmax_t)va_arg(arglist, unsigned long);
+ break;
+
+ case FORMAT_LONG:
+ iptr->val.nums = (mp_intmax_t)va_arg(arglist, long);
break;
+ case FORMAT_INTU:
+ iptr->val.numu = (mp_uintmax_t)va_arg(arglist, unsigned int);
+ break;
+
+ case FORMAT_INT:
case FORMAT_WIDTH:
- /* Argument has been read. Silently convert it into an integer
- * for later use
- */
- vto[i].type = FORMAT_INT;
+ case FORMAT_PRECISION:
+ iptr->val.nums = (mp_intmax_t)va_arg(arglist, int);
+ break;
+
+ case FORMAT_DOUBLE:
+ iptr->val.dnum = va_arg(arglist, double);
break;
default:
+ DEBUGASSERT(NULL); /* unexpected */
break;
}
}
+ *ipieces = max_param + 1;
+ *opieces = ocount;
- return 0;
-
+ return PFMT_OK;
}
-static int dprintf_formatf(
- void *data, /* untouched by format(), just sent to the stream() function in
- the second argument */
+/*
+ * formatf() - the general printf function.
+ *
+ * It calls parsefmt() to parse the format string. It populates two arrays;
+ * one that describes the input arguments and one that describes a number of
+ * output segments.
+ *
+ * On success, the input array describes the type of all arguments and their
+ * values.
+ *
+ * The function then iterates over the output sengments and outputs them one
+ * by one until done. Using the appropriate input arguments (if any).
+ *
+ * All output is sent to the 'stream()' callback, one byte at a time.
+ */
+
+static int formatf(
+ void *userp, /* untouched by format(), just sent to the stream() function in
+ the second argument */
/* function pointer called for each output character */
- int (*stream)(int, FILE *),
+ int (*stream)(unsigned char, void *),
const char *format, /* %-formatted string */
va_list ap_save) /* list of parameters */
{
- /* Base-36 digits for numbers. */
- const char *digits = lower_digits;
-
- /* Pointer into the format string. */
- char *f;
-
- /* Number of characters written. */
- int done = 0;
-
- long param; /* current parameter to read */
- long param_num = 0; /* parameter counter */
-
- struct va_stack vto[MAX_PARAMETERS];
- char *endpos[MAX_PARAMETERS];
- char **end;
+ static const char nilstr[] = "(nil)";
+ const char *digits = lower_digits; /* Base-36 digits for numbers. */
+ int done = 0; /* number of characters written */
+ int i;
+ int ocount = 0; /* number of output segments */
+ int icount = 0; /* number of input arguments */
+
+ struct outsegment output[MAX_SEGMENTS];
+ struct va_input input[MAX_PARAMETERS];
char work[BUFFSIZE];
- 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
otherwise */
char *workend = &work[sizeof(work) - 2];
- /* Do the actual %-code parsing */
- if(dprintf_Pass1(format, vto, endpos, ap_save))
+ /* Parse the format string */
+ if(parsefmt(format, output, input, &ocount, &icount, ap_save))
return 0;
- end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
- created for us */
-
- f = (char *)format;
- while(*f != '\0') {
- /* Format spec modifiers. */
- int is_alt;
-
- /* Width of a field. */
- long width;
-
- /* Precision of a field. */
- long prec;
-
- /* Decimal integer is negative. */
- int is_neg;
-
- /* Base of a number to be written. */
- unsigned long base;
-
- /* Integral values to be written. */
- mp_uintmax_t num;
-
- /* Used to convert negative in positive. */
- mp_intmax_t signed_num;
-
+ for(i = 0; i < ocount; i++) {
+ struct outsegment *optr = &output[i];
+ struct va_input *iptr;
+ bool is_alt; /* Format spec modifiers. */
+ int width; /* Width of a field. */
+ int prec; /* Precision of a field. */
+ bool is_neg; /* Decimal integer is negative. */
+ unsigned long base; /* Base of a number to be written. */
+ mp_uintmax_t num; /* Integral values to be written. */
+ mp_intmax_t signed_num; /* Used to convert negative in positive. */
char *w;
-
- if(*f != '%') {
- /* This isn't a format spec, so write everything out until the next one
- OR end of string is reached. */
- do {
- OUTCHAR(*f);
- } while(*++f && ('%' != *f));
- continue;
+ size_t outlen = optr->outlen;
+ int flags = optr->flags;
+
+ if(outlen) {
+ char *str = optr->start;
+ for(; outlen && *str; outlen--)
+ OUTCHAR(*str++);
+ if(optr->flags & FLAGS_SUBSTR)
+ /* this is just a substring */
+ continue;
}
- ++f;
-
- /* Check for "%%". Note that although the ANSI standard lists
- '%' as a conversion specifier, it says "The complete format
- specification shall be `%%'," so we can avoid all the width
- and precision processing. */
- if(*f == '%') {
- ++f;
- OUTCHAR('%');
- continue;
- }
-
- /* If this is a positional parameter, the position must follow immediately
- after the %, thus create a %<num>$ sequence */
- param = dprintf_DollarString(f, &f);
-
- if(!param)
- param = param_num;
- else
- --param;
-
- param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
- third %s will pick the 3rd argument */
-
- p = &vto[param];
-
/* pick up the specified width */
- if(p->flags & FLAGS_WIDTHPARAM) {
- width = (long)vto[p->width].data.num.as_signed;
- param_num++; /* since the width is extracted from a parameter, we
- must skip that to get to the next one properly */
+ if(flags & FLAGS_WIDTHPARAM) {
+ width = (int)input[optr->width].val.nums;
if(width < 0) {
/* "A negative field width is taken as a '-' flag followed by a
positive field width." */
- width = -width;
- p->flags |= FLAGS_LEFT;
- p->flags &= ~FLAGS_PAD_NIL;
+ if(width == INT_MIN)
+ width = INT_MAX;
+ else
+ width = -width;
+ flags |= FLAGS_LEFT;
+ flags &= ~FLAGS_PAD_NIL;
}
}
else
- width = p->width;
+ width = optr->width;
/* pick up the specified precision */
- if(p->flags & FLAGS_PRECPARAM) {
- prec = (long)vto[p->precision].data.num.as_signed;
- param_num++; /* since the precision is extracted from a parameter, we
- must skip that to get to the next one properly */
+ if(flags & FLAGS_PRECPARAM) {
+ prec = (int)input[optr->precision].val.nums;
if(prec < 0)
/* "A negative precision is taken as if the precision were
omitted." */
prec = -1;
}
- else if(p->flags & FLAGS_PREC)
- prec = p->precision;
+ else if(flags & FLAGS_PREC)
+ prec = optr->precision;
else
prec = -1;
- is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
+ is_alt = (flags & FLAGS_ALT) ? 1 : 0;
+ iptr = &input[optr->input];
- switch(p->type) {
+ switch(iptr->type) {
+ case FORMAT_INTU:
+ case FORMAT_LONGU:
+ case FORMAT_LONGLONGU:
+ flags |= FLAGS_UNSIGNED;
+ FALLTHROUGH();
case FORMAT_INT:
- num = p->data.num.as_unsigned;
- if(p->flags & FLAGS_CHAR) {
+ case FORMAT_LONG:
+ case FORMAT_LONGLONG:
+ num = iptr->val.numu;
+ if(flags & FLAGS_CHAR) {
/* Character. */
- if(!(p->flags & FLAGS_LEFT))
+ if(!(flags & FLAGS_LEFT))
while(--width > 0)
OUTCHAR(' ');
OUTCHAR((char) num);
- if(p->flags & FLAGS_LEFT)
+ if(flags & FLAGS_LEFT)
while(--width > 0)
OUTCHAR(' ');
break;
}
- if(p->flags & FLAGS_OCTAL) {
- /* Octal unsigned integer. */
+ if(flags & FLAGS_OCTAL) {
+ /* Octal unsigned integer */
base = 8;
- goto unsigned_number;
+ is_neg = FALSE;
}
- else if(p->flags & FLAGS_HEX) {
- /* Hexadecimal unsigned integer. */
-
- digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
+ else if(flags & FLAGS_HEX) {
+ /* Hexadecimal unsigned integer */
+ digits = (flags & FLAGS_UPPER)? upper_digits : lower_digits;
base = 16;
- goto unsigned_number;
+ is_neg = FALSE;
}
- else if(p->flags & FLAGS_UNSIGNED) {
- /* Decimal unsigned integer. */
+ else if(flags & FLAGS_UNSIGNED) {
+ /* Decimal unsigned integer */
base = 10;
- goto unsigned_number;
+ is_neg = FALSE;
}
+ else {
+ /* Decimal integer. */
+ base = 10;
- /* Decimal integer. */
- base = 10;
-
- is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
- if(is_neg) {
- /* signed_num might fail to hold absolute negative minimum by 1 */
- signed_num = p->data.num.as_signed + (mp_intmax_t)1;
- signed_num = -signed_num;
- num = (mp_uintmax_t)signed_num;
- num += (mp_uintmax_t)1;
+ is_neg = (iptr->val.nums < (mp_intmax_t)0);
+ if(is_neg) {
+ /* signed_num might fail to hold absolute negative minimum by 1 */
+ signed_num = iptr->val.nums + (mp_intmax_t)1;
+ signed_num = -signed_num;
+ num = (mp_uintmax_t)signed_num;
+ num += (mp_uintmax_t)1;
+ }
}
-
- goto number;
-
-unsigned_number:
- /* Unsigned number of base BASE. */
- is_neg = 0;
-
number:
- /* Number of base BASE. */
-
/* Supply a default precision if none was given. */
if(prec == -1)
prec = 1;
/* Put the number in WORK. */
w = workend;
- while(num > 0) {
- *w-- = digits[num % base];
- num /= base;
+ switch(base) {
+ case 10:
+ while(num > 0) {
+ *w-- = (char)('0' + (num % 10));
+ num /= 10;
+ }
+ break;
+ default:
+ while(num > 0) {
+ *w-- = digits[num % base];
+ num /= base;
+ }
+ break;
}
- width -= (long)(workend - w);
- prec -= (long)(workend - w);
+ width -= (int)(workend - w);
+ prec -= (int)(workend - w);
if(is_alt && base == 8 && prec <= 0) {
*w-- = '0';
@@ -777,29 +829,29 @@ number:
if(is_alt && base == 16)
width -= 2;
- if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
+ if(is_neg || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
--width;
- if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
+ if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_PAD_NIL))
while(width-- > 0)
OUTCHAR(' ');
if(is_neg)
OUTCHAR('-');
- else if(p->flags & FLAGS_SHOWSIGN)
+ else if(flags & FLAGS_SHOWSIGN)
OUTCHAR('+');
- else if(p->flags & FLAGS_SPACE)
+ else if(flags & FLAGS_SPACE)
OUTCHAR(' ');
if(is_alt && base == 16) {
OUTCHAR('0');
- if(p->flags & FLAGS_UPPER)
+ if(flags & FLAGS_UPPER)
OUTCHAR('X');
else
OUTCHAR('x');
}
- if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
+ if(!(flags & FLAGS_LEFT) && (flags & FLAGS_PAD_NIL))
while(width-- > 0)
OUTCHAR('0');
@@ -808,219 +860,199 @@ number:
OUTCHAR(*w);
}
- if(p->flags & FLAGS_LEFT)
+ if(flags & FLAGS_LEFT)
while(width-- > 0)
OUTCHAR(' ');
break;
- case FORMAT_STRING:
- /* String. */
- {
- static const char null[] = "(nil)";
- const char *str;
- size_t len;
-
- str = (char *) p->data.str;
- if(!str) {
- /* Write null[] if there's space. */
- if(prec == -1 || prec >= (long) sizeof(null) - 1) {
- str = null;
- len = sizeof(null) - 1;
- /* Disable quotes around (nil) */
- p->flags &= (~FLAGS_ALT);
- }
- else {
- str = "";
- len = 0;
- }
+ case FORMAT_STRING: {
+ const char *str;
+ size_t len;
+
+ str = (char *)iptr->val.str;
+ if(!str) {
+ /* Write null string if there's space. */
+ if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) {
+ str = nilstr;
+ len = sizeof(nilstr) - 1;
+ /* Disable quotes around (nil) */
+ flags &= (~FLAGS_ALT);
}
- else if(prec != -1)
- len = (size_t)prec;
- else if(*str == '\0')
+ else {
+ str = "";
len = 0;
- else
- len = strlen(str);
+ }
+ }
+ else if(prec != -1)
+ len = (size_t)prec;
+ else if(*str == '\0')
+ len = 0;
+ else
+ len = strlen(str);
- width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
+ width -= (len > INT_MAX) ? INT_MAX : (int)len;
- if(p->flags & FLAGS_ALT)
- OUTCHAR('"');
+ if(flags & FLAGS_ALT)
+ OUTCHAR('"');
- if(!(p->flags&FLAGS_LEFT))
- while(width-- > 0)
- OUTCHAR(' ');
+ if(!(flags&FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
- for(; len && *str; len--)
- OUTCHAR(*str++);
- if(p->flags&FLAGS_LEFT)
- while(width-- > 0)
- OUTCHAR(' ');
+ for(; len && *str; len--)
+ OUTCHAR(*str++);
+ if(flags&FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
- if(p->flags & FLAGS_ALT)
- OUTCHAR('"');
- }
+ if(flags & FLAGS_ALT)
+ OUTCHAR('"');
break;
+ }
case FORMAT_PTR:
/* Generic pointer. */
- {
- void *ptr;
- ptr = (void *) p->data.ptr;
- if(ptr) {
- /* If the pointer is not NULL, write it as a %#x spec. */
- base = 16;
- digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
- is_alt = 1;
- num = (size_t) ptr;
- is_neg = 0;
- goto number;
- }
- else {
- /* Write "(nil)" for a nil pointer. */
- static const char strnil[] = "(nil)";
- const char *point;
-
- width -= (long)(sizeof(strnil) - 1);
- if(p->flags & FLAGS_LEFT)
- while(width-- > 0)
- OUTCHAR(' ');
- for(point = strnil; *point != '\0'; ++point)
- OUTCHAR(*point);
- if(!(p->flags & FLAGS_LEFT))
- while(width-- > 0)
- OUTCHAR(' ');
- }
+ if(iptr->val.ptr) {
+ /* If the pointer is not NULL, write it as a %#x spec. */
+ base = 16;
+ digits = (flags & FLAGS_UPPER)? upper_digits : lower_digits;
+ is_alt = TRUE;
+ num = (size_t) iptr->val.ptr;
+ is_neg = FALSE;
+ goto number;
}
- break;
+ else {
+ /* Write "(nil)" for a nil pointer. */
+ const char *point;
- case FORMAT_DOUBLE:
- {
- char formatbuf[32]="%";
- char *fptr = &formatbuf[1];
- size_t left = sizeof(formatbuf)-strlen(formatbuf);
- int len;
-
- width = -1;
- if(p->flags & FLAGS_WIDTH)
- width = p->width;
- else if(p->flags & FLAGS_WIDTHPARAM)
- width = (long)vto[p->width].data.num.as_signed;
+ width -= (int)(sizeof(nilstr) - 1);
+ if(flags & FLAGS_LEFT)
+ while(width-- > 0)
+ OUTCHAR(' ');
+ for(point = nilstr; *point != '\0'; ++point)
+ OUTCHAR(*point);
+ if(!(flags & FLAGS_LEFT))
+ while(width-- > 0)
+ OUTCHAR(' ');
+ }
+ break;
- prec = -1;
- if(p->flags & FLAGS_PREC)
- prec = p->precision;
- else if(p->flags & FLAGS_PRECPARAM)
- prec = (long)vto[p->precision].data.num.as_signed;
-
- if(p->flags & FLAGS_LEFT)
- *fptr++ = '-';
- if(p->flags & FLAGS_SHOWSIGN)
- *fptr++ = '+';
- if(p->flags & FLAGS_SPACE)
- *fptr++ = ' ';
- if(p->flags & FLAGS_ALT)
- *fptr++ = '#';
-
- *fptr = 0;
-
- if(width >= 0) {
- if(width >= (long)sizeof(work))
- width = sizeof(work)-1;
- /* RECURSIVE USAGE */
- len = curl_msnprintf(fptr, left, "%ld", width);
- fptr += len;
- left -= len;
+ case FORMAT_DOUBLE: {
+ char formatbuf[32]="%";
+ char *fptr = &formatbuf[1];
+ size_t left = sizeof(formatbuf)-strlen(formatbuf);
+ int len;
+
+ if(flags & FLAGS_WIDTH)
+ width = optr->width;
+
+ if(flags & FLAGS_PREC)
+ prec = optr->precision;
+
+ if(flags & FLAGS_LEFT)
+ *fptr++ = '-';
+ if(flags & FLAGS_SHOWSIGN)
+ *fptr++ = '+';
+ if(flags & FLAGS_SPACE)
+ *fptr++ = ' ';
+ if(flags & FLAGS_ALT)
+ *fptr++ = '#';
+
+ *fptr = 0;
+
+ if(width >= 0) {
+ if(width >= (int)sizeof(work))
+ width = sizeof(work)-1;
+ /* RECURSIVE USAGE */
+ len = curl_msnprintf(fptr, left, "%d", width);
+ fptr += len;
+ left -= len;
+ }
+ if(prec >= 0) {
+ /* for each digit in the integer part, we can have one less
+ precision */
+ size_t maxprec = sizeof(work) - 2;
+ double val = iptr->val.dnum;
+ if(width > 0 && prec <= width)
+ maxprec -= width;
+ while(val >= 10.0) {
+ val /= 10;
+ maxprec--;
}
- if(prec >= 0) {
- /* for each digit in the integer part, we can have one less
- precision */
- size_t maxprec = sizeof(work) - 2;
- double val = p->data.dnum;
- if(width > 0 && prec <= width)
- maxprec -= width;
- while(val >= 10.0) {
- val /= 10;
- maxprec--;
- }
- if(prec > (long)maxprec)
- prec = (long)maxprec-1;
- if(prec < 0)
- prec = 0;
- /* RECURSIVE USAGE */
- len = curl_msnprintf(fptr, left, ".%ld", prec);
- fptr += len;
- }
- if(p->flags & FLAGS_LONG)
- *fptr++ = 'l';
+ if(prec > (int)maxprec)
+ prec = (int)maxprec-1;
+ if(prec < 0)
+ prec = 0;
+ /* RECURSIVE USAGE */
+ len = curl_msnprintf(fptr, left, ".%d", prec);
+ fptr += len;
+ }
+ if(flags & FLAGS_LONG)
+ *fptr++ = 'l';
- if(p->flags & FLAGS_FLOATE)
- *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
- else if(p->flags & FLAGS_FLOATG)
- *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
- else
- *fptr++ = 'f';
+ if(flags & FLAGS_FLOATE)
+ *fptr++ = (char)((flags & FLAGS_UPPER) ? 'E':'e');
+ else if(flags & FLAGS_FLOATG)
+ *fptr++ = (char)((flags & FLAGS_UPPER) ? 'G' : 'g');
+ else
+ *fptr++ = 'f';
- *fptr = 0; /* and a final null-termination */
+ *fptr = 0; /* and a final null-termination */
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-nonliteral"
#endif
- /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
- output characters */
+ /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
+ output characters */
#ifdef HAVE_SNPRINTF
- (snprintf)(work, sizeof(work), formatbuf, p->data.dnum);
+ (snprintf)(work, sizeof(work), formatbuf, iptr->val.dnum);
#else
- (sprintf)(work, formatbuf, p->data.dnum);
+ (sprintf)(work, formatbuf, iptr->val.dnum);
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
- DEBUGASSERT(strlen(work) <= sizeof(work));
- for(fptr = work; *fptr; fptr++)
- OUTCHAR(*fptr);
- }
+ DEBUGASSERT(strlen(work) <= sizeof(work));
+ for(fptr = work; *fptr; fptr++)
+ OUTCHAR(*fptr);
break;
+ }
case FORMAT_INTPTR:
/* Answer the count of characters written. */
#ifdef HAVE_LONG_LONG_TYPE
- if(p->flags & FLAGS_LONGLONG)
- *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
+ if(flags & FLAGS_LONGLONG)
+ *(LONG_LONG_TYPE *) iptr->val.ptr = (LONG_LONG_TYPE)done;
else
#endif
- if(p->flags & FLAGS_LONG)
- *(long *) p->data.ptr = (long)done;
- else if(!(p->flags & FLAGS_SHORT))
- *(int *) p->data.ptr = (int)done;
+ if(flags & FLAGS_LONG)
+ *(long *) iptr->val.ptr = (long)done;
+ else if(!(flags & FLAGS_SHORT))
+ *(int *) iptr->val.ptr = (int)done;
else
- *(short *) p->data.ptr = (short)done;
+ *(short *) iptr->val.ptr = (short)done;
break;
default:
break;
}
- f = *end++; /* goto end of %-code */
-
}
return done;
}
/* fputc() look-alike */
-static int addbyter(int output, FILE *data)
+static int addbyter(unsigned char outc, void *f)
{
- struct nsprintf *infop = (struct nsprintf *)data;
- unsigned char outc = (unsigned char)output;
-
+ struct nsprintf *infop = f;
if(infop->length < infop->max) {
/* only do this if we haven't reached max length yet */
- infop->buffer[0] = outc; /* store */
- infop->buffer++; /* increase pointer */
+ *infop->buffer++ = outc; /* store */
infop->length++; /* we are now one byte larger */
- return outc; /* fputc() returns like this on success */
+ return 0; /* fputc() returns like this on success */
}
- return -1;
+ return 1;
}
int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
@@ -1033,7 +1065,7 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
info.length = 0;
info.max = maxlength;
- retcode = dprintf_formatf(&info, addbyter, format, ap_save);
+ retcode = formatf(&info, addbyter, format, ap_save);
if(info.max) {
/* we terminate this with a zero byte */
if(info.max == info.length) {
@@ -1059,32 +1091,28 @@ int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
}
/* fputc() look-alike */
-static int alloc_addbyter(int output, FILE *data)
+static int alloc_addbyter(unsigned char outc, void *f)
{
- struct asprintf *infop = (struct asprintf *)data;
- unsigned char outc = (unsigned char)output;
-
- if(Curl_dyn_addn(infop->b, &outc, 1)) {
- infop->fail = 1;
- return -1; /* fail */
+ struct asprintf *infop = f;
+ CURLcode result = Curl_dyn_addn(infop->b, &outc, 1);
+ if(result) {
+ infop->merr = result == CURLE_TOO_LARGE ? MERR_TOO_LARGE : MERR_MEM;
+ return 1 ; /* fail */
}
- return outc; /* fputc() returns like this on success */
+ return 0;
}
-extern int Curl_dyn_vprintf(struct dynbuf *dyn,
- const char *format, va_list ap_save);
-
-/* appends the formatted string, returns 0 on success, 1 on error */
+/* appends the formatted string, returns MERR error code */
int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
{
struct asprintf info;
info.b = dyn;
- info.fail = 0;
+ info.merr = MERR_OK;
- (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- if(info.fail) {
+ (void)formatf(&info, alloc_addbyter, format, ap_save);
+ if(info.merr) {
Curl_dyn_free(info.b);
- return 1;
+ return info.merr;
}
return 0;
}
@@ -1095,10 +1123,10 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
struct dynbuf dyn;
info.b = &dyn;
Curl_dyn_init(info.b, DYN_APRINTF);
- info.fail = 0;
+ info.merr = MERR_OK;
- (void)dprintf_formatf(&info, alloc_addbyter, format, ap_save);
- if(info.fail) {
+ (void)formatf(&info, alloc_addbyter, format, ap_save);
+ if(info.merr) {
Curl_dyn_free(info.b);
return NULL;
}
@@ -1117,13 +1145,12 @@ char *curl_maprintf(const char *format, ...)
return s;
}
-static int storebuffer(int output, FILE *data)
+static int storebuffer(unsigned char outc, void *f)
{
- char **buffer = (char **)data;
- unsigned char outc = (unsigned char)output;
+ char **buffer = f;
**buffer = outc;
(*buffer)++;
- return outc; /* act like fputc() ! */
+ return 0;
}
int curl_msprintf(char *buffer, const char *format, ...)
@@ -1131,19 +1158,29 @@ int curl_msprintf(char *buffer, const char *format, ...)
va_list ap_save; /* argument pointer */
int retcode;
va_start(ap_save, format);
- retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+ retcode = formatf(&buffer, storebuffer, format, ap_save);
va_end(ap_save);
*buffer = 0; /* we terminate this with a zero byte */
return retcode;
}
+static int fputc_wrapper(unsigned char outc, void *f)
+{
+ int out = outc;
+ FILE *s = f;
+ int rc = fputc(out, s);
+ if(rc == out)
+ return 0;
+ return 1;
+}
+
int curl_mprintf(const char *format, ...)
{
int retcode;
va_list ap_save; /* argument pointer */
va_start(ap_save, format);
- retcode = dprintf_formatf(stdout, fputc, format, ap_save);
+ retcode = formatf(stdout, fputc_wrapper, format, ap_save);
va_end(ap_save);
return retcode;
}
@@ -1153,25 +1190,24 @@ int curl_mfprintf(FILE *whereto, const char *format, ...)
int retcode;
va_list ap_save; /* argument pointer */
va_start(ap_save, format);
- retcode = dprintf_formatf(whereto, fputc, format, ap_save);
+ retcode = formatf(whereto, fputc_wrapper, format, ap_save);
va_end(ap_save);
return retcode;
}
int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
{
- int retcode;
- retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
+ int retcode = formatf(&buffer, storebuffer, format, ap_save);
*buffer = 0; /* we terminate this with a zero byte */
return retcode;
}
int curl_mvprintf(const char *format, va_list ap_save)
{
- return dprintf_formatf(stdout, fputc, format, ap_save);
+ return formatf(stdout, fputc_wrapper, format, ap_save);
}
int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
{
- return dprintf_formatf(whereto, fputc, format, ap_save);
+ return formatf(whereto, fputc_wrapper, format, ap_save);
}
diff --git a/lib/mqtt.c b/lib/mqtt.c
index 54f88822c..5a9d6d0f1 100644
--- a/lib/mqtt.c
+++ b/lib/mqtt.c
@@ -88,7 +88,7 @@ const struct Curl_handler Curl_handler_mqtt = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_MQTT, /* defport */
@@ -524,8 +524,10 @@ static CURLcode mqtt_publish(struct Curl_easy *data)
char encodedbytes[4];
curl_off_t postfieldsize = data->set.postfieldsize;
- if(!payload)
+ if(!payload) {
+ DEBUGF(infof(data, "mqtt_publish without payload, return bad arg"));
return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
if(postfieldsize < 0)
payloadlen = strlen(payload);
else
@@ -616,16 +618,12 @@ static void mqstate(struct Curl_easy *data,
}
-/* for the publish packet */
-#define MQTT_HEADER_LEN 5 /* max 5 bytes */
-
static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
ssize_t nread;
- unsigned char *pkt = (unsigned char *)data->state.buffer;
size_t remlen;
struct mqtt_conn *mqtt = &conn->proto.mqtt;
struct MQTT *mq = data->req.p.mqtt;
@@ -674,14 +672,14 @@ MQTT_SUBACK_COMING:
data->req.bytecount = 0;
data->req.size = remlen;
mq->npacket = remlen; /* get this many bytes */
- /* FALLTHROUGH */
+ FALLTHROUGH();
case MQTT_PUB_REMAIN: {
/* read rest of packet, but no more. Cap to buffer size */
- struct SingleRequest *k = &data->req;
+ char buffer[4*1024];
size_t rest = mq->npacket;
- if(rest > (size_t)data->set.buffer_size)
- rest = (size_t)data->set.buffer_size;
- result = Curl_read(data, sockfd, (char *)pkt, rest, &nread);
+ if(rest > sizeof(buffer))
+ rest = sizeof(buffer);
+ result = Curl_read(data, sockfd, buffer, rest, &nread);
if(result) {
if(CURLE_AGAIN == result) {
infof(data, "EEEE AAAAGAIN");
@@ -693,20 +691,13 @@ MQTT_SUBACK_COMING:
result = CURLE_PARTIAL_FILE;
goto end;
}
- Curl_debug(data, CURLINFO_DATA_IN, (char *)pkt, (size_t)nread);
-
- mq->npacket -= nread;
- k->bytecount += nread;
- result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
- if(result)
- goto end;
/* if QoS is set, message contains packet id */
-
- result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)pkt, nread);
+ result = Curl_client_write(data, CLIENTWRITE_BODY, buffer, nread);
if(result)
goto end;
+ mq->npacket -= nread;
if(!mq->npacket)
/* no more PUBLISH payload, back to subscribe wait state */
mqstate(data, MQTT_FIRST, MQTT_PUBWAIT);
@@ -754,7 +745,6 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
struct MQTT *mq = data->req.p.mqtt;
ssize_t nread;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
- unsigned char *pkt = (unsigned char *)data->state.buffer;
unsigned char byte;
*done = FALSE;
@@ -785,14 +775,14 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
/* remember the first byte */
mq->npacket = 0;
mqstate(data, MQTT_REMAINING_LENGTH, MQTT_NOSTATE);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case MQTT_REMAINING_LENGTH:
do {
result = Curl_read(data, sockfd, (char *)&byte, 1, &nread);
if(!nread)
break;
Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
- pkt[mq->npacket++] = byte;
+ mq->pkt_hd[mq->npacket++] = byte;
} while((byte & 0x80) && (mq->npacket < 4));
if(nread && (byte & 0x80))
/* MQTT supports up to 127 * 128^0 + 127 * 128^1 + 127 * 128^2 +
@@ -800,7 +790,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
result = CURLE_WEIRD_SERVER_REPLY;
if(result)
break;
- mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);
+ mq->remaining_length = mqtt_decode_len(mq->pkt_hd, mq->npacket, NULL);
mq->npacket = 0;
if(mq->remaining_length) {
mqstate(data, mqtt->nextstate, MQTT_NOSTATE);
diff --git a/lib/mqtt.h b/lib/mqtt.h
index 84f177022..99ab12a98 100644
--- a/lib/mqtt.h
+++ b/lib/mqtt.h
@@ -57,6 +57,7 @@ struct MQTT {
unsigned char firstbyte;
size_t remaining_length;
struct dynbuf recvbuf;
+ unsigned char pkt_hd[4]; /* for decoding the arriving packet length */
};
#endif /* HEADER_CURL_MQTT_H */
diff --git a/lib/multi.c b/lib/multi.c
index ff753ac8c..0926b0d85 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -55,22 +55,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef __APPLE__
-
-#define wakeup_write write
-#define wakeup_read read
-#define wakeup_close close
-#define wakeup_create pipe
-
-#else /* __APPLE__ */
-
-#define wakeup_write swrite
-#define wakeup_read sread
-#define wakeup_close sclose
-#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
-
-#endif /* __APPLE__ */
-
/*
CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97
to 911 takes on a 32-bit machine 4 x 804 = 3211 more bytes. Still, every
@@ -231,10 +215,6 @@ struct Curl_sh_entry {
unsigned int readers; /* this many transfers want to read */
unsigned int writers; /* this many transfers want to write */
};
-/* bits for 'action' having no bits means this socket is not expecting any
- action */
-#define SH_READ 1
-#define SH_WRITE 2
/* look up a given socket in the socket hash, skip invalid sockets */
static struct Curl_sh_entry *sh_getentry(struct Curl_hash *sh,
@@ -416,9 +396,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
Curl_llist_init(&multi->msgsent, NULL);
multi->multiplexing = TRUE;
-
- /* -1 means it not set by user, use the default value */
- multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
#ifdef USE_WINSOCK
@@ -695,6 +672,7 @@ static CURLcode multi_done(struct Curl_easy *data,
many callbacks and protocols work differently, we could potentially do
this more fine-grained in the future. */
premature = TRUE;
+ FALLTHROUGH();
default:
break;
}
@@ -1016,73 +994,162 @@ void Curl_attach_connection(struct Curl_easy *data,
Curl_conn_ev_data_attach(conn, data);
}
-static int domore_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
+static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
+ struct connectdata *conn = data->conn;
+ (void)socks;
+ /* Not using `conn->sockfd` as `Curl_setup_transfer()` initializes
+ * that *after* the connect. */
+ if(conn && conn->sock[FIRSTSOCKET] != CURL_SOCKET_BAD) {
+ /* Default is to wait to something from the server */
+ socks[0] = conn->sock[FIRSTSOCKET];
+ return GETSOCK_READSOCK(0);
+ }
+ return GETSOCK_BLANK;
+}
+
+static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks)
+{
+ struct connectdata *conn = data->conn;
+ if(conn && conn->handler->proto_getsock)
+ return conn->handler->proto_getsock(data, conn, socks);
+ else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+ /* Default is to wait to something from the server */
+ socks[0] = conn->sockfd;
+ return GETSOCK_READSOCK(0);
+ }
+ return GETSOCK_BLANK;
+}
+
+static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks)
+{
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->domore_getsock)
return conn->handler->domore_getsock(data, conn, socks);
+ else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+ /* Default is that we want to send something to the server */
+ socks[0] = conn->sockfd;
+ return GETSOCK_WRITESOCK(0);
+ }
return GETSOCK_BLANK;
}
-static int doing_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
+static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
+ struct connectdata *conn = data->conn;
if(conn && conn->handler->doing_getsock)
return conn->handler->doing_getsock(data, conn, socks);
+ else if(conn && conn->sockfd != CURL_SOCKET_BAD) {
+ /* Default is that we want to send something to the server */
+ socks[0] = conn->sockfd;
+ return GETSOCK_WRITESOCK(0);
+ }
return GETSOCK_BLANK;
}
-static int protocol_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *socks)
+static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock)
{
- if(conn->handler->proto_getsock)
- return conn->handler->proto_getsock(data, conn, socks);
- return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
+ struct connectdata *conn = data->conn;
+
+ if(!conn)
+ return GETSOCK_BLANK;
+ else if(conn->handler->perform_getsock)
+ return conn->handler->perform_getsock(data, conn, sock);
+ else {
+ /* Default is to obey the data->req.keepon flags for send/recv */
+ int bitmap = GETSOCK_BLANK;
+ unsigned sockindex = 0;
+ if(CURL_WANT_RECV(data)) {
+ DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
+ bitmap |= GETSOCK_READSOCK(sockindex);
+ sock[sockindex] = conn->sockfd;
+ }
+
+ if(CURL_WANT_SEND(data)) {
+ if((conn->sockfd != conn->writesockfd) ||
+ bitmap == GETSOCK_BLANK) {
+ /* only if they are not the same socket and we have a readable
+ one, we increase index */
+ if(bitmap != GETSOCK_BLANK)
+ sockindex++; /* increase index if we need two entries */
+
+ DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
+ sock[sockindex] = conn->writesockfd;
+ }
+ bitmap |= GETSOCK_WRITESOCK(sockindex);
+ }
+ return bitmap;
+ }
}
-/* returns bitmapped flags for this handle and its sockets. The 'socks[]'
- array contains MAX_SOCKSPEREASYHANDLE entries. */
-static int multi_getsock(struct Curl_easy *data,
- curl_socket_t *socks)
+/* Initializes `poll_set` with the current socket poll actions needed
+ * for transfer `data`. */
+static void multi_getsock(struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct connectdata *conn = data->conn;
/* The no connection case can happen when this is called from
curl_multi_remove_handle() => singlesocket() => multi_getsock().
*/
- if(!conn)
- return 0;
+ Curl_pollset_reset(data, ps);
+ if(!data->conn)
+ return;
switch(data->mstate) {
- default:
- return 0;
+ case MSTATE_INIT:
+ case MSTATE_PENDING:
+ case MSTATE_CONNECT:
+ /* nothing to poll for yet */
+ break;
case MSTATE_RESOLVING:
- return Curl_resolv_getsock(data, socks);
+ Curl_pollset_add_socks(data, ps, Curl_resolv_getsock);
+ /* connection filters are not involved in this phase */
+ break;
+
+ case MSTATE_CONNECTING:
+ case MSTATE_TUNNELING:
+ Curl_pollset_add_socks(data, ps, connecting_getsock);
+ Curl_conn_adjust_pollset(data, ps);
+ break;
- case MSTATE_PROTOCONNECTING:
case MSTATE_PROTOCONNECT:
- return protocol_getsock(data, conn, socks);
+ case MSTATE_PROTOCONNECTING:
+ Curl_pollset_add_socks(data, ps, protocol_getsock);
+ Curl_conn_adjust_pollset(data, ps);
+ break;
case MSTATE_DO:
case MSTATE_DOING:
- return doing_getsock(data, conn, socks);
-
- case MSTATE_TUNNELING:
- case MSTATE_CONNECTING:
- return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
+ Curl_pollset_add_socks(data, ps, doing_getsock);
+ Curl_conn_adjust_pollset(data, ps);
+ break;
case MSTATE_DOING_MORE:
- return domore_getsock(data, conn, socks);
+ Curl_pollset_add_socks(data, ps, domore_getsock);
+ Curl_conn_adjust_pollset(data, ps);
+ break;
- case MSTATE_DID: /* since is set after DO is completed, we switch to
- waiting for the same as the PERFORMING state */
+ case MSTATE_DID: /* same as PERFORMING in regard to polling */
case MSTATE_PERFORMING:
- return Curl_single_getsock(data, conn, socks);
- }
+ Curl_pollset_add_socks(data, ps, perform_getsock);
+ Curl_conn_adjust_pollset(data, ps);
+ break;
+ case MSTATE_RATELIMITING:
+ /* we need to let time pass, ignore socket(s) */
+ break;
+
+ case MSTATE_DONE:
+ case MSTATE_COMPLETED:
+ case MSTATE_MSGSENT:
+ /* nothing more to poll for */
+ break;
+
+ default:
+ failf(data, "multi_getsock: unexpected multi state %d", data->mstate);
+ DEBUGASSERT(0);
+ break;
+ }
}
CURLMcode curl_multi_fdset(struct Curl_multi *multi,
@@ -1094,8 +1161,8 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
and then we must make sure that is done. */
struct Curl_easy *data;
int this_max_fd = -1;
- curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
- int i;
+ struct easy_pollset ps;
+ unsigned int i;
(void)exc_fd_set; /* not used */
if(!GOOD_MULTI_HANDLE(multi))
@@ -1104,29 +1171,20 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
+ memset(&ps, 0, sizeof(ps));
for(data = multi->easyp; data; data = data->next) {
- int bitmap;
-#ifdef __clang_analyzer_
- /* to prevent "The left operand of '>=' is a garbage value" warnings */
- memset(sockbunch, 0, sizeof(sockbunch));
-#endif
- bitmap = multi_getsock(data, sockbunch);
-
- for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
- if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
- if(!FDSET_SOCK(sockbunch[i]))
- /* pretend it doesn't exist */
- continue;
- if(bitmap & GETSOCK_READSOCK(i))
- FD_SET(sockbunch[i], read_fd_set);
- if(bitmap & GETSOCK_WRITESOCK(i))
- FD_SET(sockbunch[i], write_fd_set);
- if((int)sockbunch[i] > this_max_fd)
- this_max_fd = (int)sockbunch[i];
- }
- else {
- break;
- }
+ multi_getsock(data, &ps);
+
+ for(i = 0; i < ps.num; i++) {
+ if(!FDSET_SOCK(ps.sockets[i]))
+ /* pretend it doesn't exist */
+ continue;
+ if(ps.actions[i] & CURL_POLL_IN)
+ FD_SET(ps.sockets[i], read_fd_set);
+ if(ps.actions[i] & CURL_POLL_OUT)
+ FD_SET(ps.sockets[i], write_fd_set);
+ if((int)ps.sockets[i] > this_max_fd)
+ this_max_fd = (int)ps.sockets[i];
}
}
@@ -1162,9 +1220,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
bool use_wakeup)
{
struct Curl_easy *data;
- curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
- int bitmap;
- unsigned int i;
+ struct easy_pollset ps;
+ size_t i;
unsigned int nfds = 0;
unsigned int curlfds;
long timeout_internal;
@@ -1190,17 +1247,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
return CURLM_BAD_FUNCTION_ARGUMENT;
/* Count up how many fds we have from the multi handle */
+ memset(&ps, 0, sizeof(ps));
for(data = multi->easyp; data; data = data->next) {
- bitmap = multi_getsock(data, sockbunch);
-
- for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
- if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
- ++nfds;
- }
- else {
- break;
- }
- }
+ multi_getsock(data, &ps);
+ nfds += ps.num;
}
/* If the internally desired timeout is actually shorter than requested from
@@ -1241,40 +1291,35 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(curlfds) {
/* Add the curl handles to our pollfds first */
for(data = multi->easyp; data; data = data->next) {
- bitmap = multi_getsock(data, sockbunch);
+ multi_getsock(data, &ps);
- for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
- if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
- struct pollfd *ufd = &ufds[nfds++];
-#ifdef USE_WINSOCK
- long mask = 0;
-#endif
- ufd->fd = sockbunch[i];
- ufd->events = 0;
- if(bitmap & GETSOCK_READSOCK(i)) {
+ for(i = 0; i < ps.num; i++) {
+ struct pollfd *ufd = &ufds[nfds++];
#ifdef USE_WINSOCK
- mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
+ long mask = 0;
#endif
- ufd->events |= POLLIN;
- }
- if(bitmap & GETSOCK_WRITESOCK(i)) {
+ ufd->fd = ps.sockets[i];
+ ufd->events = 0;
+ if(ps.actions[i] & CURL_POLL_IN) {
#ifdef USE_WINSOCK
- mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
- reset_socket_fdwrite(sockbunch[i]);
+ mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
#endif
- ufd->events |= POLLOUT;
- }
+ ufd->events |= POLLIN;
+ }
+ if(ps.actions[i] & CURL_POLL_OUT) {
#ifdef USE_WINSOCK
- if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) {
- if(ufds_malloc)
- free(ufds);
- return CURLM_INTERNAL_ERROR;
- }
+ mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+ reset_socket_fdwrite(ps.sockets[i]);
#endif
+ ufd->events |= POLLOUT;
}
- else {
- break;
+#ifdef USE_WINSOCK
+ if(WSAEventSelect(ps.sockets[i], multi->wsa_event, mask) != 0) {
+ if(ufds_malloc)
+ free(ufds);
+ return CURLM_INTERNAL_ERROR;
}
+#endif
}
}
}
@@ -1386,21 +1431,16 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
if(curlfds) {
for(data = multi->easyp; data; data = data->next) {
- bitmap = multi_getsock(data, sockbunch);
-
- for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
- if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
- wsa_events.lNetworkEvents = 0;
- if(WSAEnumNetworkEvents(sockbunch[i], NULL, &wsa_events) == 0) {
- if(ret && !pollrc && wsa_events.lNetworkEvents)
- retcode++;
- }
- WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
- }
- else {
- /* break on entry not checked for being readable or writable */
- break;
+ multi_getsock(data, &ps);
+
+ for(i = 0; i < ps.num; i++) {
+ wsa_events.lNetworkEvents = 0;
+ if(WSAEnumNetworkEvents(ps.sockets[i], NULL,
+ &wsa_events) == 0) {
+ if(ret && !pollrc && wsa_events.lNetworkEvents)
+ retcode++;
}
+ WSAEventSelect(ps.sockets[i], multi->wsa_event, 0);
}
}
}
@@ -1980,6 +2020,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
if(!result) {
+ *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE);
if(async)
/* We're now waiting for an asynchronous name lookup */
multistate(data, MSTATE_RESOLVING);
@@ -2409,7 +2450,6 @@ 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;
@@ -2440,7 +2480,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
/* read/write data if it is ready to do so */
- result = Curl_readwrite(data->conn, data, &done, &comeback);
+ result = Curl_readwrite(data, &done);
if(done || (result == CURLE_RECV_ERROR)) {
/* If CURLE_RECV_ERROR happens early enough, we assume it was a race
@@ -2550,7 +2590,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
}
}
- else if(comeback) {
+ else if(data->state.select_bits) {
/* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
won't get stuck on this transfer at the expense of other concurrent
transfers */
@@ -2895,53 +2935,36 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
static CURLMcode singlesocket(struct Curl_multi *multi,
struct Curl_easy *data)
{
- curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
- int i;
+ struct easy_pollset cur_poll;
+ unsigned int i;
struct Curl_sh_entry *entry;
curl_socket_t s;
- int num;
- unsigned int curraction;
- unsigned char actions[MAX_SOCKSPEREASYHANDLE];
int rc;
- for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
- socks[i] = CURL_SOCKET_BAD;
-
/* Fill in the 'current' struct with the state as it is now: what sockets to
supervise and for what actions */
- curraction = multi_getsock(data, socks);
+ multi_getsock(data, &cur_poll);
/* We have 0 .. N sockets already and we get to know about the 0 .. M
sockets we should have from now on. Detect the differences, remove no
longer supervised ones and add new ones */
/* walk over the sockets we got right now */
- for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
- (curraction & GETSOCK_MASK_RW(i));
- i++) {
- unsigned char action = CURL_POLL_NONE;
- unsigned char prevaction = 0;
+ for(i = 0; i < cur_poll.num; i++) {
+ unsigned char cur_action = cur_poll.actions[i];
+ unsigned char last_action = 0;
int comboaction;
- bool sincebefore = FALSE;
- s = socks[i];
+ s = cur_poll.sockets[i];
/* get it from the hash */
entry = sh_getentry(&multi->sockhash, s);
-
- if(curraction & GETSOCK_READSOCK(i))
- action |= CURL_POLL_IN;
- if(curraction & GETSOCK_WRITESOCK(i))
- action |= CURL_POLL_OUT;
-
- actions[i] = action;
if(entry) {
/* check if new for this transfer */
- int j;
- for(j = 0; j< data->numsocks; j++) {
- if(s == data->sockets[j]) {
- prevaction = data->actions[j];
- sincebefore = TRUE;
+ unsigned int j;
+ for(j = 0; j< data->last_poll.num; j++) {
+ if(s == data->last_poll.sockets[j]) {
+ last_action = data->last_poll.actions[j];
break;
}
}
@@ -2953,23 +2976,23 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* fatal */
return CURLM_OUT_OF_MEMORY;
}
- if(sincebefore && (prevaction != action)) {
+ if(last_action && (last_action != cur_action)) {
/* Socket was used already, but different action now */
- if(prevaction & CURL_POLL_IN)
+ if(last_action & CURL_POLL_IN)
entry->readers--;
- if(prevaction & CURL_POLL_OUT)
+ if(last_action & CURL_POLL_OUT)
entry->writers--;
- if(action & CURL_POLL_IN)
+ if(cur_action & CURL_POLL_IN)
entry->readers++;
- if(action & CURL_POLL_OUT)
+ if(cur_action & CURL_POLL_OUT)
entry->writers++;
}
- else if(!sincebefore) {
- /* a new user */
+ else if(!last_action) {
+ /* a new transfer using this socket */
entry->users++;
- if(action & CURL_POLL_IN)
+ if(cur_action & CURL_POLL_IN)
entry->readers++;
- if(action & CURL_POLL_OUT)
+ if(cur_action & CURL_POLL_OUT)
entry->writers++;
/* add 'data' to the transfer hash on this socket! */
@@ -2980,11 +3003,11 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
}
}
- comboaction = (entry->writers? CURL_POLL_OUT : 0) |
+ comboaction = (entry->writers ? CURL_POLL_OUT : 0) |
(entry->readers ? CURL_POLL_IN : 0);
/* socket existed before and has the same action set as before */
- if(sincebefore && ((int)entry->action == comboaction))
+ if(last_action && ((int)entry->action == comboaction))
/* same, continue */
continue;
@@ -2992,6 +3015,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
set_in_callback(multi, TRUE);
rc = multi->socket_cb(data, s, comboaction, multi->socket_userp,
entry->socketp);
+
set_in_callback(multi, FALSE);
if(rc == -1) {
multi->dead = TRUE;
@@ -3002,16 +3026,15 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
entry->action = comboaction; /* store the current action state */
}
- num = i; /* number of sockets */
-
- /* when we've walked over all the sockets we should have right now, we must
- make sure to detect sockets that are removed */
- for(i = 0; i< data->numsocks; i++) {
- int j;
+ /* Check for last_poll.sockets that no longer appear in cur_poll.sockets.
+ * Need to remove the easy handle from the multi->sockhash->transfers and
+ * remove multi->sockhash entry when this was the last transfer */
+ for(i = 0; i< data->last_poll.num; i++) {
+ unsigned int j;
bool stillused = FALSE;
- s = data->sockets[i];
- for(j = 0; j < num; j++) {
- if(s == socks[j]) {
+ s = data->last_poll.sockets[i];
+ for(j = 0; j < cur_poll.num; j++) {
+ if(s == cur_poll.sockets[j]) {
/* this is still supervised */
stillused = TRUE;
break;
@@ -3024,7 +3047,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
/* if this is NULL here, the socket has been closed and notified so
already by Curl_multi_closed() */
if(entry) {
- unsigned char oldactions = data->actions[i];
+ unsigned char oldactions = data->last_poll.actions[i];
/* this socket has been removed. Decrease user count */
entry->users--;
if(oldactions & CURL_POLL_OUT)
@@ -3052,11 +3075,10 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
}
}
}
- } /* for loop over numsocks */
+ } /* for loop over num */
- memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
- memcpy(data->actions, actions, num*sizeof(char));
- data->numsocks = num;
+ /* Remember for next time */
+ memcpy(&data->last_poll, &cur_poll, sizeof(data->last_poll));
return CURLM_OK;
}
@@ -3220,7 +3242,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
if(data->conn && !(data->conn->handler->flags & PROTOPT_DIRLOCK))
/* set socket event bitmask if they're not locked */
- data->conn->cselect_bits = (unsigned char)ev_bitmask;
+ data->state.select_bits = (unsigned char)ev_bitmask;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
@@ -3296,6 +3318,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
{
CURLMcode res = CURLM_OK;
va_list param;
+ unsigned long uarg;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@@ -3328,7 +3351,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
multi->timer_userp = va_arg(param, void *);
break;
case CURLMOPT_MAXCONNECTS:
- multi->maxconnects = va_arg(param, long);
+ uarg = va_arg(param, unsigned long);
+ if(uarg <= UINT_MAX)
+ multi->maxconnects = (unsigned int)uarg;
break;
case CURLMOPT_MAX_HOST_CONNECTIONS:
multi->max_host_connections = va_arg(param, long);
@@ -3350,9 +3375,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
case CURLMOPT_MAX_CONCURRENT_STREAMS:
{
long streams = va_arg(param, long);
- if(streams < 1)
+ if((streams < 1) || (streams > INT_MAX))
streams = 100;
- multi->max_concurrent_streams = curlx_sltoui(streams);
+ multi->max_concurrent_streams = (unsigned int)streams;
}
break;
default:
@@ -3782,11 +3807,11 @@ struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
(multi->num_easy + 1));
if(a) {
- int i = 0;
+ unsigned int i = 0;
struct Curl_easy *e = multi->easyp;
while(e) {
DEBUGASSERT(i < multi->num_easy);
- if(!e->internal)
+ if(!e->state.internal)
a[i++] = e;
e = e->next;
}
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 5b16bb605..e03e382e2 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -93,9 +93,9 @@ struct Curl_multi {
struct Curl_easy *easyp;
struct Curl_easy *easylp; /* last node */
- int num_easy; /* amount of entries in the linked list above. */
- int num_alive; /* amount of easy handles that are added but have not yet
- reached COMPLETE state */
+ unsigned int num_easy; /* amount of entries in the linked list above. */
+ unsigned int num_alive; /* amount of easy handles that are added but have
+ not yet reached COMPLETE state */
struct Curl_llist msglist; /* a list of messages from completed transfers */
@@ -136,9 +136,6 @@ struct Curl_multi {
/* Shared connection cache (bundles)*/
struct conncache conn_cache;
- long maxconnects; /* if >0, a fixed limit of the maximum number of entries
- we're allowed to grow the connection cache to */
-
long max_host_connections; /* if >0, a fixed limit of the maximum number
of connections per host */
@@ -150,8 +147,6 @@ struct Curl_multi {
void *timer_userp;
struct curltime timer_lastcall; /* the fixed time for the timeout for the
previous callback */
- unsigned int max_concurrent_streams;
-
#ifdef USE_WINSOCK
WSAEVENT wsa_event; /* winsock event used for waits */
#else
@@ -160,6 +155,10 @@ struct Curl_multi {
0 is used for read, 1 is used for write */
#endif
#endif
+ unsigned int max_concurrent_streams;
+ unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of
+ entries we're allowed to grow the connection
+ cache to */
#define IPV6_UNKNOWN 0
#define IPV6_DEAD 1
#define IPV6_WORKS 2
diff --git a/lib/netrc.c b/lib/netrc.c
index e6a09b187..038c6dca6 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -327,7 +327,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
}
retcode = parsenetrc(host, loginp, passwordp, filealloc);
free(filealloc);
-#ifdef WIN32
+#ifdef _WIN32
if(retcode == NETRC_FILE_MISSING) {
/* fallback to the old-style "_netrc" file */
filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR);
diff --git a/lib/noproxy.c b/lib/noproxy.c
index 2b9908d89..5241640a3 100644
--- a/lib/noproxy.c
+++ b/lib/noproxy.c
@@ -216,7 +216,6 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy,
/* case C passes through, not a match */
break;
case TYPE_IPV4:
- /* FALLTHROUGH */
case TYPE_IPV6: {
const char *check = token;
char *slash;
diff --git a/lib/openldap.c b/lib/openldap.c
index 3aff3060a..1e60ff738 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -130,7 +130,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
oldap_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_LDAP, /* defport */
@@ -158,7 +158,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
oldap_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_LDAPS, /* defport */
@@ -319,31 +319,12 @@ static CURLcode oldap_setup_connection(struct Curl_easy *data,
{
CURLcode result;
LDAPURLDesc *lud;
- struct ldapconninfo *li;
+ (void)conn;
/* Early URL syntax check. */
result = oldap_url_parse(data, &lud);
ldap_free_urldesc(lud);
- if(!result) {
- li = calloc(1, sizeof(struct ldapconninfo));
- if(!li)
- result = CURLE_OUT_OF_MEMORY;
- else {
- li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
- conn->proto.ldapc = li;
- connkeep(conn, "OpenLDAP default");
-
- /* Initialize the SASL storage */
- Curl_sasl_init(&li->sasl, data, &saslldap);
-
- /* Clear the TLS upgraded flag */
- conn->bits.tls_upgraded = FALSE;
-
- result = oldap_parse_login_options(conn);
- }
- }
-
return result;
}
@@ -537,7 +518,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data)
static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct ldapconninfo *li = conn->proto.ldapc;
+ struct ldapconninfo *li;
static const int version = LDAP_VERSION3;
int rc;
char *hosturl;
@@ -547,6 +528,26 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
(void)done;
+ DEBUGASSERT(!conn->proto.ldapc);
+ li = calloc(1, sizeof(struct ldapconninfo));
+ if(!li)
+ return CURLE_OUT_OF_MEMORY;
+ else {
+ CURLcode result;
+ li->proto = ldap_pvt_url_scheme2proto(data->state.up.scheme);
+ conn->proto.ldapc = li;
+
+ /* Initialize the SASL storage */
+ Curl_sasl_init(&li->sasl, data, &saslldap);
+
+ /* Clear the TLS upgraded flag */
+ conn->bits.tls_upgraded = FALSE;
+
+ result = oldap_parse_login_options(conn);
+ if(result)
+ return result;
+ }
+
hosturl = aprintf("ldap%s://%s:%d",
conn->handler->flags & PROTOPT_SSL? "s": "",
conn->host.name, conn->remote_port);
@@ -644,7 +645,7 @@ static CURLcode oldap_state_mechs_resp(struct Curl_easy *data,
switch(code) {
case LDAP_SIZELIMIT_EXCEEDED:
infof(data, "Too many authentication mechanisms\n");
- /* FALLTHROUGH */
+ FALLTHROUGH();
case LDAP_SUCCESS:
case LDAP_NO_RESULTS_RETURNED:
if(Curl_sasl_can_authenticate(&li->sasl, data))
@@ -792,10 +793,13 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
result = oldap_perform_bind(data, OLDAP_BIND);
break;
}
- /* FALLTHROUGH */
+ result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
+ if(result)
+ break;
+ FALLTHROUGH();
case OLDAP_TLS:
result = oldap_ssl_connect(data, OLDAP_TLS);
- if(result && data->set.use_ssl != CURLUSESSL_TRY)
+ if(result)
result = oldap_map_error(code, CURLE_USE_SSL_FAILED);
else if(ssl_installed(conn)) {
conn->bits.tls_upgraded = TRUE;
@@ -886,6 +890,15 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done)
result = oldap_url_parse(data, &lud);
if(!result) {
+#ifdef USE_SSL
+ if(ssl_installed(conn)) {
+ Sockbuf *sb;
+ /* re-install the libcurl SSL handlers into the sockbuf. */
+ ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
+ ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, data);
+ }
+#endif
+
rc = ldap_search_ext(li->ld, lud->lud_dn, lud->lud_scope,
lud->lud_filter, lud->lud_attrs, 0,
NULL, NULL, NULL, 0, &msgid);
@@ -947,18 +960,12 @@ static CURLcode client_write(struct Curl_easy *data,
if(!len && plen && prefix[plen - 1] == ' ')
plen--;
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) prefix, plen);
- if(!result)
- data->req.bytecount += plen;
}
if(!result && value) {
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) value, len);
- if(!result)
- data->req.bytecount += len;
}
if(!result && suffix) {
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) suffix, slen);
- if(!result)
- data->req.bytecount += slen;
}
return result;
}
@@ -1014,7 +1021,7 @@ static ssize_t oldap_recv(struct Curl_easy *data, int sockindex, char *buf,
switch(code) {
case LDAP_SIZELIMIT_EXCEEDED:
infof(data, "There are more than %d entries", lr->nument);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case LDAP_SUCCESS:
data->req.size = data->req.bytecount;
break;
diff --git a/lib/pingpong.c b/lib/pingpong.c
index 0081c9ca6..b976ffbea 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -36,6 +36,7 @@
#include "pingpong.h"
#include "multiif.h"
#include "vtls/vtls.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -105,7 +106,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
if(Curl_conn_data_pending(data, FIRSTSOCKET))
rc = 1;
- else if(Curl_pp_moredata(pp))
+ else if(pp->overflow)
/* We are receiving and there is data in the cache so just read it */
rc = 1;
else if(!pp->sendleft && Curl_conn_data_pending(data, FIRSTSOCKET))
@@ -139,19 +140,13 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
}
/* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp)
+void Curl_pp_init(struct pingpong *pp)
{
- DEBUGASSERT(data);
pp->nread_resp = 0;
- pp->linestart_resp = data->state.buffer;
- pp->pending_resp = TRUE;
pp->response = Curl_now(); /* start response time-out now! */
-}
-
-/* setup for the coming transfer */
-void Curl_pp_setup(struct pingpong *pp)
-{
+ pp->pending_resp = TRUE;
Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
+ Curl_dyn_init(&pp->recvbuf, DYN_PINGPPONG_CMD);
}
/***********************************************************************
@@ -197,9 +192,9 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
if(result)
return result;
+ pp->pending_resp = TRUE;
write_len = Curl_dyn_len(&pp->sendbuf);
s = Curl_dyn_ptr(&pp->sendbuf);
- Curl_pp_init(data, pp);
#ifdef HAVE_GSSAPI
conn->data_prot = PROT_CMD;
@@ -255,6 +250,25 @@ CURLcode Curl_pp_sendf(struct Curl_easy *data, struct pingpong *pp,
return result;
}
+static CURLcode pingpong_read(struct Curl_easy *data,
+ curl_socket_t sockfd,
+ char *buffer,
+ size_t buflen,
+ ssize_t *nread)
+{
+ CURLcode result;
+#ifdef HAVE_GSSAPI
+ enum protection_level prot = data->conn->data_prot;
+ data->conn->data_prot = PROT_CLEAR;
+#endif
+ result = Curl_read(data, sockfd, buffer, buflen, nread);
+#ifdef HAVE_GSSAPI
+ DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
+ data->conn->data_prot = (unsigned char)prot;
+#endif
+ return result;
+}
+
/*
* Curl_pp_readresp()
*
@@ -266,181 +280,96 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
int *code, /* return the server code if done */
size_t *size) /* size of the response */
{
- ssize_t perline; /* count bytes per line */
- bool keepon = TRUE;
- ssize_t gotbytes;
- char *ptr;
struct connectdata *conn = data->conn;
- char * const buf = data->state.buffer;
CURLcode result = CURLE_OK;
*code = 0; /* 0 for errors or not done */
*size = 0;
- ptr = buf + pp->nread_resp;
+ if(pp->nfinal) {
+ /* a previous call left this many bytes in the beginning of the buffer as
+ that was the final line; now ditch that */
+ size_t full = Curl_dyn_len(&pp->recvbuf);
- /* number of bytes in the current line, so far */
- perline = (ssize_t)(ptr-pp->linestart_resp);
+ /* trim off the "final" leading part */
+ Curl_dyn_tail(&pp->recvbuf, full - pp->nfinal);
- while((pp->nread_resp < (size_t)data->set.buffer_size) &&
- (keepon && !result)) {
+ pp->nfinal = 0; /* now gone */
+ }
+ if(!pp->overflow) {
+ ssize_t gotbytes = 0;
+ char buffer[900];
- if(pp->cache) {
- /* we had data in the "cache", copy that instead of doing an actual
- * read
- *
- * pp->cache_size is cast to ssize_t here. This should be safe, because
- * it would have been populated with something of size int to begin
- * with, even though its datatype may be larger than an int.
- */
- if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) {
- failf(data, "cached response data too big to handle");
- return CURLE_WEIRD_SERVER_REPLY;
- }
- memcpy(ptr, pp->cache, pp->cache_size);
- gotbytes = (ssize_t)pp->cache_size;
- free(pp->cache); /* free the cache */
- pp->cache = NULL; /* clear the pointer */
- pp->cache_size = 0; /* zero the size just in case */
- }
- else {
-#ifdef HAVE_GSSAPI
- enum protection_level prot = conn->data_prot;
- conn->data_prot = PROT_CLEAR;
-#endif
- DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
- (buf + data->set.buffer_size + 1));
- result = Curl_read(data, sockfd, ptr,
- data->set.buffer_size - pp->nread_resp,
- &gotbytes);
-#ifdef HAVE_GSSAPI
- DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
- conn->data_prot = (unsigned char)prot;
-#endif
- if(result == CURLE_AGAIN)
- return CURLE_OK; /* return */
+ result = pingpong_read(data, sockfd, buffer, sizeof(buffer), &gotbytes);
+ if(result == CURLE_AGAIN)
+ return CURLE_OK;
- if(result)
- /* Set outer result variable to this error. */
- keepon = FALSE;
- }
+ if(result)
+ return result;
- if(!keepon)
- ;
- else if(gotbytes <= 0) {
- keepon = FALSE;
- result = CURLE_RECV_ERROR;
+ if(gotbytes <= 0) {
failf(data, "response reading failed (errno: %d)", SOCKERRNO);
+ return CURLE_RECV_ERROR;
}
- else {
- /* we got a whole chunk of data, which can be anything from one
- * byte to a set of lines and possible just a piece of the last
- * line */
- ssize_t i;
- ssize_t clipamount = 0;
- bool restart = FALSE;
-
- data->req.headerbytecount += (unsigned int)gotbytes;
-
- pp->nread_resp += gotbytes;
- for(i = 0; i < gotbytes; ptr++, i++) {
- perline++;
- if(*ptr == '\n') {
- /* a newline is CRLF in pp-talk, so the CR is ignored as
- the line isn't really terminated until the LF comes */
-
- /* output debug output if that is requested */
+
+ result = Curl_dyn_addn(&pp->recvbuf, buffer, gotbytes);
+ if(result)
+ return result;
+
+ data->req.headerbytecount += (unsigned int)gotbytes;
+
+ pp->nread_resp += gotbytes;
+ }
+
+ do {
+ char *line = Curl_dyn_ptr(&pp->recvbuf);
+ char *nl = memchr(line, '\n', Curl_dyn_len(&pp->recvbuf));
+ if(nl) {
+ /* a newline is CRLF in pp-talk, so the CR is ignored as
+ the line isn't really terminated until the LF comes */
+ size_t length = nl - line + 1;
+
+ /* output debug output if that is requested */
#ifdef HAVE_GSSAPI
- if(!conn->sec_complete)
+ if(!conn->sec_complete)
#endif
- Curl_debug(data, CURLINFO_HEADER_IN,
- pp->linestart_resp, (size_t)perline);
-
- /*
- * We pass all response-lines to the callback function registered
- * for "headers". The response lines can be seen as a kind of
- * headers.
- */
- result = Curl_client_write(data, CLIENTWRITE_INFO,
- pp->linestart_resp, perline);
- if(result)
- return result;
-
- if(pp->endofresp(data, 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 null-terminate, for old times sake */
- size_t n = ptr - pp->linestart_resp;
- memmove(buf, pp->linestart_resp, n);
- buf[n] = 0; /* null-terminate */
- keepon = FALSE;
- pp->linestart_resp = ptr + 1; /* advance pointer */
- i++; /* skip this before getting out */
-
- *size = pp->nread_resp; /* size of the response */
- pp->nread_resp = 0; /* restart */
- break;
- }
- perline = 0; /* line starts over here */
- pp->linestart_resp = ptr + 1;
- }
- }
+ Curl_debug(data, CURLINFO_HEADER_IN, line, length);
- if(!keepon && (i != gotbytes)) {
- /* We found the end of the response lines, but we didn't parse the
- full chunk of data we have read from the server. We therefore need
- to store the rest of the data to be checked on the next invoke as
- it may actually contain another end of response already! */
- clipamount = gotbytes - i;
- restart = TRUE;
- DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
- "server response left",
- (int)clipamount));
- }
- else if(keepon) {
-
- if((perline == gotbytes) &&
- (gotbytes > (ssize_t)data->set.buffer_size/2)) {
- /* We got an excessive line without newlines and we need to deal
- with it. We keep the first bytes of the line then we throw
- away the rest. */
- infof(data, "Excessive server response line length received, "
- "%zd bytes. Stripping", gotbytes);
- restart = TRUE;
-
- /* we keep 40 bytes since all our pingpong protocols are only
- interested in the first piece */
- clipamount = 40;
- }
- else if(pp->nread_resp > (size_t)data->set.buffer_size/2) {
- /* We got a large chunk of data and there's potentially still
- trailing data to take care of, so we put any such part in the
- "cache", clear the buffer to make space and restart. */
- clipamount = perline;
- restart = TRUE;
- }
- }
- else if(i == gotbytes)
- restart = TRUE;
-
- if(clipamount) {
- pp->cache_size = clipamount;
- pp->cache = malloc(pp->cache_size);
- if(pp->cache)
- memcpy(pp->cache, pp->linestart_resp, pp->cache_size);
+ /*
+ * Pass all response-lines to the callback function registered for
+ * "headers". The response lines can be seen as a kind of headers.
+ */
+ result = Curl_client_write(data, CLIENTWRITE_INFO, line, length);
+ if(result)
+ return result;
+
+ if(pp->endofresp(data, conn, line, length, code)) {
+ /* When at "end of response", keep the endofresp line first in the
+ buffer since it will be accessed outside (by pingpong
+ parsers). Store the overflow counter to inform about additional
+ data in this buffer after the endofresp line. */
+ pp->nfinal = length;
+ if(Curl_dyn_len(&pp->recvbuf) > length)
+ pp->overflow = Curl_dyn_len(&pp->recvbuf) - length;
else
- return CURLE_OUT_OF_MEMORY;
+ pp->overflow = 0;
+ *size = pp->nread_resp; /* size of the response */
+ pp->nread_resp = 0; /* restart */
+ break;
}
- if(restart) {
- /* now reset a few variables to start over nicely from the start of
- the big buffer */
- pp->nread_resp = 0; /* start over from scratch in the buffer */
- ptr = pp->linestart_resp = buf;
- perline = 0;
- }
-
- } /* there was data */
+ if(Curl_dyn_len(&pp->recvbuf) > length)
+ /* keep the remaining piece */
+ Curl_dyn_tail((&pp->recvbuf), Curl_dyn_len(&pp->recvbuf) - length);
+ else
+ Curl_dyn_reset(&pp->recvbuf);
+ }
+ else {
+ /* without a newline, there is no overflow */
+ pp->overflow = 0;
+ break;
+ }
- } /* while there's buffer left and loop is requested */
+ } while(1); /* while there's buffer left to scan */
pp->pending_resp = FALSE;
@@ -488,14 +417,13 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
CURLcode Curl_pp_disconnect(struct pingpong *pp)
{
Curl_dyn_free(&pp->sendbuf);
- Curl_safefree(pp->cache);
+ Curl_dyn_free(&pp->recvbuf);
return CURLE_OK;
}
bool Curl_pp_moredata(struct pingpong *pp)
{
- return (!pp->sendleft && pp->cache && pp->nread_resp < pp->cache_size) ?
- TRUE : FALSE;
+ return (!pp->sendleft && Curl_dyn_len(&pp->recvbuf));
}
#endif
diff --git a/lib/pingpong.h b/lib/pingpong.h
index 80d3f7718..006b9c538 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -47,16 +47,11 @@ typedef enum {
* It holds response cache and non-blocking sending data.
*/
struct pingpong {
- char *cache; /* data cache between getresponse()-calls */
- size_t cache_size; /* size of cache in bytes */
size_t nread_resp; /* number of bytes currently read of a server response */
- char *linestart_resp; /* line start pointer for the server response
- reader function */
bool pending_resp; /* set TRUE when a server response is pending or in
progress, and is cleared once the last response is
read */
- char *sendthis; /* allocated pointer to a buffer that is to be sent to the
- server */
+ char *sendthis; /* pointer to a buffer that is to be sent to the server */
size_t sendleft; /* number of bytes left to send from the sendthis buffer */
size_t sendsize; /* total size of the sendthis buffer */
struct curltime response; /* set to Curl_now() when a command has been sent
@@ -64,6 +59,10 @@ struct pingpong {
timediff_t response_time; /* When no timeout is given, this is the amount of
milliseconds we await for a server response. */
struct dynbuf sendbuf;
+ struct dynbuf recvbuf;
+ size_t overflow; /* number of bytes left after a final response line */
+ size_t nfinal; /* number of bytes in the final response line, which
+ after a match is first in the receice buffer */
/* Function pointers the protocols MUST implement and provide for the
pingpong layer to function */
@@ -90,10 +89,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp,
bool block, bool disconnecting);
/* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct Curl_easy *data, struct pingpong *pp);
-
-/* setup for the transfer */
-void Curl_pp_setup(struct pingpong *pp);
+void Curl_pp_init(struct pingpong *pp);
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
@@ -113,7 +109,7 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
*/
CURLcode Curl_pp_sendf(struct Curl_easy *data,
struct pingpong *pp,
- const char *fmt, ...);
+ const char *fmt, ...) CURL_PRINTF(3, 4);
/***********************************************************************
*
@@ -128,7 +124,7 @@ CURLcode Curl_pp_sendf(struct Curl_easy *data,
CURLcode Curl_pp_vsendf(struct Curl_easy *data,
struct pingpong *pp,
const char *fmt,
- va_list args);
+ va_list args) CURL_PRINTF(3, 0);
/*
* Curl_pp_readresp()
diff --git a/lib/pop3.c b/lib/pop3.c
index a9d5fdd69..cf2519282 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -77,6 +77,7 @@
#include "curl_sasl.h"
#include "curl_md5.h"
#include "warnless.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -124,7 +125,7 @@ const struct Curl_handler Curl_handler_pop3 = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_POP3, /* defport */
@@ -153,7 +154,7 @@ const struct Curl_handler Curl_handler_pop3s = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_POP3S, /* defport */
@@ -251,8 +252,8 @@ static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn,
*/
static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out)
{
- char *message = data->state.buffer;
- size_t len = strlen(message);
+ char *message = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
+ size_t len = data->conn->proto.pop3c.pp.nfinal;
if(len > 2) {
/* Find the start of the message */
@@ -648,8 +649,8 @@ static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
- const char *line = data->state.buffer;
- size_t len = strlen(line);
+ const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
+ size_t len = data->conn->proto.pop3c.pp.nfinal;
(void)instate; /* no use for this yet */
@@ -657,44 +658,35 @@ static CURLcode pop3_state_servergreet_resp(struct Curl_easy *data,
failf(data, "Got unexpected pop3-server response");
result = CURLE_WEIRD_SERVER_REPLY;
}
- else {
+ else if(len > 3) {
/* Does the server support APOP authentication? */
- if(len >= 4 && line[len - 2] == '>') {
- /* Look for the APOP timestamp */
- size_t i;
- for(i = 3; i < len - 2; ++i) {
- if(line[i] == '<') {
- /* Calculate the length of the timestamp */
- size_t timestamplen = len - 1 - i;
- char *at;
- if(!timestamplen)
- break;
-
- /* Allocate some memory for the timestamp */
- pop3c->apoptimestamp = (char *)calloc(1, timestamplen + 1);
-
- if(!pop3c->apoptimestamp)
- break;
-
- /* Copy the timestamp */
- memcpy(pop3c->apoptimestamp, line + i, timestamplen);
- pop3c->apoptimestamp[timestamplen] = '\0';
-
- /* If the timestamp does not contain '@' it is not (as required by
- RFC-1939) conformant to the RFC-822 message id syntax, and we
- therefore do not use APOP authentication. */
- at = strchr(pop3c->apoptimestamp, '@');
- if(!at)
- Curl_safefree(pop3c->apoptimestamp);
- else
- /* Store the APOP capability */
- pop3c->authtypes |= POP3_TYPE_APOP;
- break;
- }
+ char *lt;
+ char *gt = NULL;
+
+ /* Look for the APOP timestamp */
+ lt = memchr(line, '<', len);
+ if(lt)
+ /* search the remainder for '>' */
+ gt = memchr(lt, '>', len - (lt - line));
+ if(gt) {
+ /* the length of the timestamp, including the brackets */
+ size_t timestamplen = gt - lt + 1;
+ char *at = memchr(lt, '@', timestamplen);
+ /* If the timestamp does not contain '@' it is not (as required by
+ RFC-1939) conformant to the RFC-822 message id syntax, and we
+ therefore do not use APOP authentication. */
+ if(at) {
+ /* dupe the timestamp */
+ pop3c->apoptimestamp = Curl_memdup0(lt, timestamplen);
+ if(!pop3c->apoptimestamp)
+ return CURLE_OUT_OF_MEMORY;
+ /* Store the APOP capability */
+ pop3c->authtypes |= POP3_TYPE_APOP;
}
}
- result = pop3_perform_capa(data, conn);
+ if(!result)
+ result = pop3_perform_capa(data, conn);
}
return result;
@@ -707,8 +699,8 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
- const char *line = data->state.buffer;
- size_t len = strlen(line);
+ const char *line = Curl_dyn_ptr(&data->conn->proto.pop3c.pp.recvbuf);
+ size_t len = data->conn->proto.pop3c.pp.nfinal;
(void)instate; /* no use for this yet */
@@ -795,7 +787,7 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
/* Pipelining in response is forbidden. */
- if(data->conn->proto.pop3c.pp.cache_size)
+ if(data->conn->proto.pop3c.pp.overflow)
return CURLE_WEIRD_SERVER_REPLY;
if(pop3code != '+') {
@@ -944,24 +936,29 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
/* POP3 download */
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
- if(pp->cache) {
- /* The header "cache" contains a bunch of data that is actually body
- content so send it as such. Note that there may even be additional
- "headers" after the body */
+ if(pp->overflow) {
+ /* The recv buffer contains data that is actually body content so send
+ it as such. Note that there may even be additional "headers" after
+ the body */
+
+ /* keep only the overflow */
+ Curl_dyn_tail(&pp->recvbuf, pp->overflow);
+ pp->nfinal = 0; /* done */
if(!data->req.no_body) {
- result = Curl_pop3_write(data, pp->cache, pp->cache_size);
+ result = Curl_pop3_write(data, Curl_dyn_ptr(&pp->recvbuf),
+ Curl_dyn_len(&pp->recvbuf));
if(result)
return result;
}
- /* Free the cache */
- Curl_safefree(pp->cache);
-
- /* Reset the cache size */
- pp->cache_size = 0;
+ /* reset the buffer */
+ Curl_dyn_reset(&pp->recvbuf);
+ pp->overflow = 0;
}
}
+ else
+ pp->overflow = 0;
/* End of DO phase */
pop3_state(data, POP3_STOP);
@@ -1088,7 +1085,7 @@ static CURLcode pop3_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct POP3 *pop3;
- pop3 = data->req.p.pop3 = calloc(sizeof(struct POP3), 1);
+ pop3 = data->req.p.pop3 = calloc(1, sizeof(struct POP3));
if(!pop3)
result = CURLE_OUT_OF_MEMORY;
@@ -1131,8 +1128,7 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
Curl_sasl_init(&pop3c->sasl, data, &saslpop3);
/* Initialise the pingpong layer */
- Curl_pp_setup(pp);
- Curl_pp_init(data, pp);
+ Curl_pp_init(pp);
/* Parse the URL options */
result = pop3_parse_url_options(conn);
diff --git a/lib/progress.c b/lib/progress.c
index e783a9c86..d05fcc3eb 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -174,10 +174,18 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
data->progress.t_startop = timestamp;
break;
case TIMER_STARTSINGLE:
- /* This is set at the start of each single fetch */
+ /* This is set at the start of each single transfer */
data->progress.t_startsingle = timestamp;
data->progress.is_t_startransfer_set = false;
break;
+ case TIMER_POSTQUEUE:
+ /* Set when the transfer starts (after potentially having been brought
+ back from the waiting queue). It needs to count from t_startop and not
+ t_startsingle since the latter is reset when a connection is brought
+ back from the pending queue. */
+ data->progress.t_postqueue =
+ Curl_timediff_us(timestamp, data->progress.t_startop);
+ break;
case TIMER_STARTACCEPT:
data->progress.t_acceptdata = timestamp;
break;
@@ -304,7 +312,7 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
* 'actual' is the time in milliseconds it took to actually download the
* last 'size' bytes.
*/
- actual = Curl_timediff(now, start);
+ actual = Curl_timediff_ceil(now, start);
if(actual < minimum) {
/* if it downloaded the data faster than the limit, make it wait the
difference */
@@ -319,12 +327,6 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
*/
CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
- if(data->set.max_filesize && (size > data->set.max_filesize)) {
- failf(data, "Exceeded the maximum allowed file size "
- "(%" CURL_FORMAT_CURL_OFF_T ")",
- data->set.max_filesize);
- return CURLE_FILESIZE_EXCEEDED;
- }
data->progress.downloaded = size;
return CURLE_OK;
}
diff --git a/lib/progress.h b/lib/progress.h
index fc39e34d2..73749419a 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -30,7 +30,8 @@
typedef enum {
TIMER_NONE,
TIMER_STARTOP,
- TIMER_STARTSINGLE,
+ TIMER_STARTSINGLE, /* start of transfer, might get queued */
+ TIMER_POSTQUEUE, /* start, immediately after dequeue */
TIMER_NAMELOOKUP,
TIMER_CONNECT,
TIMER_APPCONNECT,
diff --git a/lib/rand.c b/lib/rand.c
index 6bd96136f..c62b1a403 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -32,10 +32,6 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
-#ifdef HAVE_ARC4RANDOM
-/* Some platforms might have the prototype missing (ubuntu + libressl) */
-uint32_t arc4random(void);
-#endif
#include <curl/curl.h>
#include "urldata.h"
@@ -50,7 +46,7 @@ uint32_t arc4random(void);
#include "curl_memory.h"
#include "memdebug.h"
-#ifdef WIN32
+#ifdef _WIN32
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
# define HAVE_WIN_BCRYPTGENRANDOM
@@ -105,7 +101,6 @@ CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
{
- unsigned int r;
CURLcode result = CURLE_OK;
static unsigned int randseed;
static bool seeded = FALSE;
@@ -138,7 +133,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
/* ---- non-cryptographic version following ---- */
-#ifdef WIN32
+#ifdef _WIN32
if(!seeded) {
result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd));
if(result != CURLE_NOT_BUILT_IN)
@@ -146,12 +141,14 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
}
#endif
-#ifdef HAVE_ARC4RANDOM
- *rnd = (unsigned int)arc4random();
- return CURLE_OK;
+#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL)
+ if(!seeded) {
+ *rnd = (unsigned int)arc4random();
+ return CURLE_OK;
+ }
#endif
-#if defined(RANDOM_FILE) && !defined(WIN32)
+#if defined(RANDOM_FILE) && !defined(_WIN32)
if(!seeded) {
/* if there's a random file to read a seed from, use it */
int fd = open(RANDOM_FILE, O_RDONLY);
@@ -175,9 +172,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
seeded = TRUE;
}
- /* Return an unsigned 32-bit pseudo-random number. */
- r = randseed = randseed * 1103515245 + 12345;
- *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+ {
+ unsigned int r;
+ /* Return an unsigned 32-bit pseudo-random number. */
+ r = randseed = randseed * 1103515245 + 12345;
+ *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+ }
return CURLE_OK;
}
@@ -201,7 +201,7 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
{
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
- DEBUGASSERT(num > 0);
+ DEBUGASSERT(num);
while(num) {
unsigned int r;
@@ -241,9 +241,11 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
memset(buffer, 0, sizeof(buffer));
#endif
- if((num/2 >= sizeof(buffer)) || !(num&1))
+ if((num/2 >= sizeof(buffer)) || !(num&1)) {
/* make sure it fits in the local buffer and that it is an odd number! */
+ DEBUGF(infof(data, "invalid buffer size with Curl_rand_hex"));
return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
num--; /* save one for null-termination */
diff --git a/lib/rand.h b/lib/rand.h
index 1d009f52c..bc05239e4 100644
--- a/lib/rand.h
+++ b/lib/rand.h
@@ -41,7 +41,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
size_t num);
-#ifdef WIN32
+#ifdef _WIN32
/* Random generator shared between the Schannel vtls and Curl_rand*()
functions */
CURLcode Curl_win32_random(unsigned char *entropy, size_t length);
diff --git a/lib/rename.c b/lib/rename.c
index 97a66e947..4c8869806 100644
--- a/lib/rename.c
+++ b/lib/rename.c
@@ -40,7 +40,7 @@
/* return 0 on success, 1 on error */
int Curl_rename(const char *oldpath, const char *newpath)
{
-#ifdef WIN32
+#ifdef _WIN32
/* rename() on Windows doesn't overwrite, so we can't use it here.
MoveFileEx() will overwrite and is usually atomic, however it fails
when there are open handles to the file. */
diff --git a/lib/rtsp.c b/lib/rtsp.c
index ccd7264b0..26f473534 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -45,8 +45,8 @@
#include "curl_memory.h"
#include "memdebug.h"
-#define RTP_PKT_LENGTH(p) ((((int)((unsigned char)((p)[2]))) << 8) | \
- ((int)((unsigned char)((p)[3]))))
+#define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \
+ ((unsigned int)((unsigned char)((p)[3]))))
/* protocol-specific functions set up to be called by the main engine */
static CURLcode rtsp_do(struct Curl_easy *data, bool *done);
@@ -58,16 +58,20 @@ static int rtsp_getsock_do(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
/*
- * Parse and write out any available RTP data.
- *
- * nread: amount of data left after k->str. will be modified if RTP
- * data is parsed and k->str is moved up
- * readmore: whether or not the RTP parser needs more data right away
+ * Parse and write out an RTSP response.
+ * @param data the transfer
+ * @param conn the connection
+ * @param buf data read from connection
+ * @param blen amount of data in buf
+ * @param is_eos TRUE iff this is the last write
+ * @param readmore out, TRUE iff complete buf was consumed and more data
+ * is needed
*/
-static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
- struct connectdata *conn,
- ssize_t *nread,
- bool *readmore);
+static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data,
+ const char *buf,
+ size_t blen,
+ bool is_eos,
+ bool *done);
static CURLcode rtsp_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
@@ -88,7 +92,7 @@ static int rtsp_getsock_do(struct Curl_easy *data, struct connectdata *conn,
}
static
-CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len);
+CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len);
static
CURLcode rtsp_parse_transport(struct Curl_easy *data, char *transport);
@@ -110,7 +114,7 @@ const struct Curl_handler Curl_handler_rtsp = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
rtsp_disconnect, /* disconnect */
- rtsp_rtp_readwrite, /* readwrite */
+ rtsp_rtp_write_resp, /* write_resp */
rtsp_conncheck, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_RTSP, /* defport */
@@ -585,153 +589,281 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
return result;
}
-
-static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
- struct connectdata *conn,
- ssize_t *nread,
- bool *readmore) {
- struct SingleRequest *k = &data->req;
- struct rtsp_conn *rtspc = &(conn->proto.rtspc);
- unsigned char *rtp_channel_mask = data->state.rtp_channel_mask;
-
- char *rtp; /* moving pointer to rtp data */
- ssize_t rtp_dataleft; /* how much data left to parse in this round */
- CURLcode result;
- bool interleaved = false;
- size_t skip_size = 0;
-
- if(Curl_dyn_len(&rtspc->buf)) {
- /* There was some leftover data the last time. Append new buffers */
- if(Curl_dyn_addn(&rtspc->buf, k->str, *nread))
- return CURLE_OUT_OF_MEMORY;
- rtp = Curl_dyn_ptr(&rtspc->buf);
- rtp_dataleft = Curl_dyn_len(&rtspc->buf);
+/**
+ * write any BODY bytes missing to the client, ignore the rest.
+ */
+static CURLcode rtp_write_body_junk(struct Curl_easy *data,
+ const char *buf,
+ size_t blen)
+{
+ struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
+ curl_off_t body_remain;
+ bool in_body;
+
+ in_body = (data->req.headerline && !rtspc->in_header) &&
+ (data->req.size >= 0) &&
+ (data->req.bytecount < data->req.size);
+ body_remain = in_body? (data->req.size - data->req.bytecount) : 0;
+ DEBUGASSERT(body_remain >= 0);
+ if(body_remain) {
+ if((curl_off_t)blen > body_remain)
+ blen = (size_t)body_remain;
+ return Curl_client_write(data, CLIENTWRITE_BODY, (char *)buf, blen);
}
- else {
- /* Just parse the request buffer directly */
- rtp = k->str;
- rtp_dataleft = *nread;
- }
-
- while(rtp_dataleft > 0) {
- if(rtp[0] == '$') {
- if(rtp_dataleft > 4) {
- unsigned char rtp_channel;
- int rtp_length;
- int idx;
- int off;
-
- /* Parse the header */
- /* The channel identifier immediately follows and is 1 byte */
- rtp_channel = (unsigned char)rtp[1];
- idx = rtp_channel / 8;
- off = rtp_channel % 8;
- if(!(rtp_channel_mask[idx] & (1 << off))) {
- /* invalid channel number, maybe not an RTP packet */
- rtp++;
- rtp_dataleft--;
- skip_size++;
- continue;
+ return CURLE_OK;
+}
+
+static CURLcode rtsp_filter_rtp(struct Curl_easy *data,
+ const char *buf,
+ size_t blen,
+ size_t *pconsumed)
+{
+ struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
+ CURLcode result = CURLE_OK;
+ size_t skip_len = 0;
+
+ *pconsumed = 0;
+ while(blen) {
+ bool in_body = (data->req.headerline && !rtspc->in_header) &&
+ (data->req.size >= 0) &&
+ (data->req.bytecount < data->req.size);
+ switch(rtspc->state) {
+
+ case RTP_PARSE_SKIP: {
+ DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 0);
+ while(blen && buf[0] != '$') {
+ if(!in_body && buf[0] == 'R' &&
+ data->set.rtspreq != RTSPREQ_RECEIVE) {
+ if(strncmp(buf, "RTSP/", (blen < 5) ? blen : 5) == 0) {
+ /* This could be the next response, no consume and return */
+ if(*pconsumed) {
+ DEBUGF(infof(data, "RTP rtsp_filter_rtp[SKIP] RTSP/ prefix, "
+ "skipping %zd bytes of junk", *pconsumed));
+ }
+ rtspc->state = RTP_PARSE_SKIP;
+ rtspc->in_header = TRUE;
+ goto out;
+ }
}
- if(skip_size > 0) {
- DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
- "bytes", skip_size));
+ /* junk/BODY, consume without buffering */
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ ++skip_len;
+ }
+ if(blen && buf[0] == '$') {
+ /* possible start of an RTP message, buffer */
+ if(skip_len) {
+ /* end of junk/BODY bytes, flush */
+ result = rtp_write_body_junk(data,
+ (char *)(buf - skip_len), skip_len);
+ skip_len = 0;
+ if(result)
+ goto out;
}
- skip_size = 0;
- rtspc->rtp_channel = rtp_channel;
-
- /* The length is two bytes */
- rtp_length = RTP_PKT_LENGTH(rtp);
+ if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ rtspc->state = RTP_PARSE_CHANNEL;
+ }
+ break;
+ }
- if(rtp_dataleft < rtp_length + 4) {
- /* Need more - incomplete payload */
- *readmore = TRUE;
- break;
+ case RTP_PARSE_CHANNEL: {
+ int idx = ((unsigned char)buf[0]) / 8;
+ int off = ((unsigned char)buf[0]) % 8;
+ DEBUGASSERT(Curl_dyn_len(&rtspc->buf) == 1);
+ if(!(data->state.rtp_channel_mask[idx] & (1 << off))) {
+ /* invalid channel number, junk or BODY data */
+ rtspc->state = RTP_PARSE_SKIP;
+ DEBUGASSERT(skip_len == 0);
+ /* we do not consume this byte, it is BODY data */
+ DEBUGF(infof(data, "RTSP: invalid RTP channel %d, skipping", idx));
+ if(*pconsumed == 0) {
+ /* We did not consume the initial '$' in our buffer, but had
+ * it from an earlier call. We cannot un-consume it and have
+ * to write it directly as BODY data */
+ result = rtp_write_body_junk(data, Curl_dyn_ptr(&rtspc->buf), 1);
+ if(result)
+ goto out;
}
- interleaved = true;
- /* We have the full RTP interleaved packet
- * Write out the header including the leading '$' */
- DEBUGF(infof(data, "RTP write channel %d rtp_length %d",
- rtspc->rtp_channel, rtp_length));
- result = rtp_client_write(data, &rtp[0], rtp_length + 4);
- if(result) {
- *readmore = FALSE;
- return result;
+ else {
+ /* count the '$' as skip and continue */
+ skip_len = 1;
}
+ Curl_dyn_free(&rtspc->buf);
+ break;
+ }
+ /* a valid channel, so we expect this to be a real RTP message */
+ rtspc->rtp_channel = (unsigned char)buf[0];
+ if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ rtspc->state = RTP_PARSE_LEN;
+ break;
+ }
- /* Move forward in the buffer */
- rtp_dataleft -= rtp_length + 4;
- rtp += rtp_length + 4;
+ case RTP_PARSE_LEN: {
+ size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+ const char *rtp_buf;
+ DEBUGASSERT(rtp_len >= 2 && rtp_len < 4);
+ if(Curl_dyn_addn(&rtspc->buf, buf, 1)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ *pconsumed += 1;
+ ++buf;
+ --blen;
+ if(rtp_len == 2)
+ break;
+ rtp_buf = Curl_dyn_ptr(&rtspc->buf);
+ rtspc->rtp_len = RTP_PKT_LENGTH(rtp_buf) + 4;
+ rtspc->state = RTP_PARSE_DATA;
+ break;
+ }
- if(data->set.rtspreq == RTSPREQ_RECEIVE) {
- /* If we are in a passive receive, give control back
- * to the app as often as we can.
- */
- k->keepon &= ~KEEP_RECV;
+ case RTP_PARSE_DATA: {
+ size_t rtp_len = Curl_dyn_len(&rtspc->buf);
+ size_t needed;
+ DEBUGASSERT(rtp_len < rtspc->rtp_len);
+ needed = rtspc->rtp_len - rtp_len;
+ if(needed <= blen) {
+ if(Curl_dyn_addn(&rtspc->buf, buf, needed)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
}
+ *pconsumed += needed;
+ buf += needed;
+ blen -= needed;
+ /* complete RTP message in buffer */
+ DEBUGF(infof(data, "RTP write channel %d rtp_len %zu",
+ rtspc->rtp_channel, rtspc->rtp_len));
+ result = rtp_client_write(data, Curl_dyn_ptr(&rtspc->buf),
+ rtspc->rtp_len);
+ Curl_dyn_free(&rtspc->buf);
+ rtspc->state = RTP_PARSE_SKIP;
+ if(result)
+ goto out;
}
else {
- /* Need more - incomplete header */
- *readmore = TRUE;
- break;
- }
- }
- else {
- /* If the following data begins with 'RTSP/', which might be an RTSP
- message, we should stop skipping the data. */
- /* If `k-> headerline> 0 && !interleaved` is true, we are maybe in the
- middle of an RTSP message. It is difficult to determine this, so we
- stop skipping. */
- size_t prefix_len = (rtp_dataleft < 5) ? rtp_dataleft : 5;
- if((k->headerline > 0 && !interleaved) ||
- strncmp(rtp, "RTSP/", prefix_len) == 0) {
- if(skip_size > 0) {
- DEBUGF(infof(data, "Skip the malformed interleaved data %lu "
- "bytes", skip_size));
+ if(Curl_dyn_addn(&rtspc->buf, buf, blen)) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
}
- break; /* maybe is an RTSP message */
+ *pconsumed += blen;
+ buf += blen;
+ blen = 0;
}
- /* Skip incorrect data util the next RTP packet or RTSP message */
- do {
- rtp++;
- rtp_dataleft--;
- skip_size++;
- } while(rtp_dataleft > 0 && rtp[0] != '$' && rtp[0] != 'R');
+ break;
+ }
+
+ default:
+ DEBUGASSERT(0);
+ return CURLE_RECV_ERROR;
}
}
+out:
+ if(!result && skip_len)
+ result = rtp_write_body_junk(data, (char *)(buf - skip_len), skip_len);
+ return result;
+}
- if(rtp_dataleft && rtp[0] == '$') {
- DEBUGF(infof(data, "RTP Rewinding %zd %s", rtp_dataleft,
- *readmore ? "(READMORE)" : ""));
+static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data,
+ const char *buf,
+ size_t blen,
+ bool is_eos,
+ bool *done)
+{
+ struct rtsp_conn *rtspc = &(data->conn->proto.rtspc);
+ CURLcode result = CURLE_OK;
+ size_t consumed = 0;
- /* Store the incomplete RTP packet for a "rewind" */
- if(!Curl_dyn_len(&rtspc->buf)) {
- /* nothing was stored, add this data */
- if(Curl_dyn_addn(&rtspc->buf, rtp, rtp_dataleft))
- return CURLE_OUT_OF_MEMORY;
- }
- else {
- /* keep the remainder */
- Curl_dyn_tail(&rtspc->buf, rtp_dataleft);
- }
+ if(!data->req.header)
+ rtspc->in_header = FALSE;
+ *done = FALSE;
+ if(!blen) {
+ goto out;
+ }
- /* As far as the transfer is concerned, this data is consumed */
- *nread = 0;
- return CURLE_OK;
+ DEBUGF(infof(data, "rtsp_rtp_write_resp(len=%zu, in_header=%d, eos=%d)",
+ blen, rtspc->in_header, is_eos));
+
+ /* If header parsing is not onging, extract RTP messages */
+ if(!rtspc->in_header) {
+ result = rtsp_filter_rtp(data, buf, blen, &consumed);
+ if(result)
+ goto out;
+ buf += consumed;
+ blen -= consumed;
+ /* either we consumed all or are at the start of header parsing */
+ if(blen && !data->req.header)
+ DEBUGF(infof(data, "RTSP: %zu bytes, possibly excess in response body",
+ blen));
}
- /* Fix up k->str to point just after the last RTP packet */
- k->str += *nread - rtp_dataleft;
- *nread = rtp_dataleft;
+ /* we want to parse headers, do so */
+ if(data->req.header && blen) {
+ rtspc->in_header = TRUE;
+ result = Curl_http_write_resp_hds(data, buf, blen, &consumed, done);
+ if(result)
+ goto out;
- /* If we get here, we have finished with the leftover/merge buffer */
- Curl_dyn_free(&rtspc->buf);
+ buf += consumed;
+ blen -= consumed;
- return CURLE_OK;
+ if(!data->req.header)
+ rtspc->in_header = FALSE;
+
+ if(!rtspc->in_header) {
+ /* If header parsing is done, extract interleaved RTP messages */
+ if(data->req.size <= -1) {
+ /* Respect section 4.4 of rfc2326: If the Content-Length header is
+ absent, a length 0 must be assumed. */
+ data->req.size = 0;
+ data->req.download_done = TRUE;
+ }
+ result = rtsp_filter_rtp(data, buf, blen, &consumed);
+ if(result)
+ goto out;
+ blen -= consumed;
+ }
+ }
+
+ if(rtspc->state != RTP_PARSE_SKIP)
+ *done = FALSE;
+ /* we SHOULD have consumed all bytes, unless the response is borked.
+ * In which case we write out the left over bytes, letting the client
+ * writer deal with it (it will report EXCESS and fail the transfer). */
+ DEBUGF(infof(data, "rtsp_rtp_write_resp(len=%zu, in_header=%d, done=%d "
+ " rtspc->state=%d, req.size=%" CURL_FORMAT_CURL_OFF_T ")",
+ blen, rtspc->in_header, *done, rtspc->state, data->req.size));
+ if(!result && (is_eos || blen)) {
+ result = Curl_client_write(data, CLIENTWRITE_BODY|
+ (is_eos? CLIENTWRITE_EOS:0),
+ (char *)buf, blen);
+ }
+
+out:
+ if((data->set.rtspreq == RTSPREQ_RECEIVE) &&
+ (rtspc->state == RTP_PARSE_SKIP)) {
+ /* In special mode RECEIVE, we just process one chunk of network
+ * data, so we stop the transfer here, if we have no incomplete
+ * RTP message pending. */
+ data->req.download_done = TRUE;
+ }
+ return result;
}
static
-CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
+CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len)
{
size_t wrote;
curl_write_callback writeit;
@@ -756,7 +888,7 @@ CURLcode rtp_client_write(struct Curl_easy *data, char *ptr, size_t len)
}
Curl_set_in_callback(data, true);
- wrote = writeit(ptr, 1, len, user_ptr);
+ wrote = writeit((char *)ptr, 1, len, user_ptr);
Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
@@ -821,7 +953,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
/* If the Session ID is set, then compare */
if(strlen(data->set.str[STRING_RTSP_SESSION_ID]) != idlen ||
- strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen) != 0) {
+ strncmp(start, data->set.str[STRING_RTSP_SESSION_ID], idlen)) {
failf(data, "Got RTSP Session ID Line [%s], but wanted ID [%s]",
start, data->set.str[STRING_RTSP_SESSION_ID]);
return CURLE_RTSP_SESSION_ERROR;
@@ -833,11 +965,9 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header)
*/
/* Copy the id substring into a new buffer */
- data->set.str[STRING_RTSP_SESSION_ID] = malloc(idlen + 1);
+ data->set.str[STRING_RTSP_SESSION_ID] = Curl_memdup0(start, idlen);
if(!data->set.str[STRING_RTSP_SESSION_ID])
return CURLE_OUT_OF_MEMORY;
- memcpy(data->set.str[STRING_RTSP_SESSION_ID], start, idlen);
- (data->set.str[STRING_RTSP_SESSION_ID])[idlen] = '\0';
}
}
else if(checkprefix("Transport:", header)) {
diff --git a/lib/rtsp.h b/lib/rtsp.h
index 111bac2a6..237b80f80 100644
--- a/lib/rtsp.h
+++ b/lib/rtsp.h
@@ -39,6 +39,12 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
#endif /* CURL_DISABLE_RTSP */
+typedef enum {
+ RTP_PARSE_SKIP,
+ RTP_PARSE_CHANNEL,
+ RTP_PARSE_LEN,
+ RTP_PARSE_DATA
+} rtp_parse_st;
/*
* RTSP Connection data
*
@@ -47,6 +53,9 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, char *header);
struct rtsp_conn {
struct dynbuf buf;
int rtp_channel;
+ size_t rtp_len;
+ rtp_parse_st state;
+ BIT(in_header);
};
/****************************************************************************
diff --git a/lib/select.c b/lib/select.c
index cae9beb6c..d92e745a7 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -76,7 +76,7 @@ int Curl_wait_ms(timediff_t timeout_ms)
}
#if defined(MSDOS)
delay(timeout_ms);
-#elif defined(WIN32)
+#elif defined(_WIN32)
/* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
#if TIMEDIFF_T_MAX >= ULONG_MAX
if(timeout_ms >= ULONG_MAX)
diff --git a/lib/sendf.c b/lib/sendf.c
index 0482c5da4..db3189a29 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -50,6 +50,7 @@
#include "strdup.h"
#include "http2.h"
#include "headers.h"
+#include "progress.h"
#include "ws.h"
/* The last 3 #include files should be in this order */
@@ -57,6 +58,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+
+static CURLcode do_init_stack(struct Curl_easy *data);
+
#if defined(CURL_DO_LINEEND_CONV) && !defined(CURL_DISABLE_FTP)
/*
* convert_lineends() changes CRLF (\r\n) end-of-line markers to a single LF
@@ -292,13 +296,6 @@ static CURLcode chop_write(struct Curl_easy *data,
if(!skip_body_write &&
((type & CLIENTWRITE_BODY) ||
((type & CLIENTWRITE_HEADER) && data->set.include_header))) {
-#ifdef USE_WEBSOCKETS
- if(conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) {
- writebody = Curl_ws_writecb;
- writebody_ptr = data;
- }
- else
-#endif
writebody = data->set.fwrite_func;
}
if((type & (CLIENTWRITE_HEADER|CLIENTWRITE_INFO)) &&
@@ -341,7 +338,7 @@ static CURLcode chop_write(struct Curl_easy *data,
len -= chunklen;
}
-#ifndef CURL_DISABLE_HTTP
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API)
/* HTTP header, but not status-line */
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS) ) {
@@ -385,34 +382,36 @@ static CURLcode chop_write(struct Curl_easy *data,
the future to leave the original data alone.
*/
CURLcode Curl_client_write(struct Curl_easy *data,
- int type,
- char *ptr,
- size_t len)
+ int type, char *buf, size_t blen)
{
+ CURLcode result;
+
#if !defined(CURL_DISABLE_FTP) && defined(CURL_DO_LINEEND_CONV)
/* FTP data may need conversion. */
if((type & CLIENTWRITE_BODY) &&
(data->conn->handler->protocol & PROTO_FAMILY_FTP) &&
data->conn->proto.ftpc.transfertype == 'A') {
/* convert end-of-line markers */
- len = convert_lineends(data, ptr, len);
+ blen = convert_lineends(data, buf, blen);
}
#endif
/* it is one of those, at least */
DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO));
- /* BODY is only BODY */
- DEBUGASSERT(!(type & CLIENTWRITE_BODY) || (type == CLIENTWRITE_BODY));
- /* INFO is only INFO */
- DEBUGASSERT(!(type & CLIENTWRITE_INFO) || (type == CLIENTWRITE_INFO));
-
- if(type == CLIENTWRITE_BODY) {
- if(data->req.ignorebody)
- return CURLE_OK;
+ /* BODY is only BODY (with optional EOS) */
+ DEBUGASSERT(!(type & CLIENTWRITE_BODY) ||
+ ((type & ~(CLIENTWRITE_BODY|CLIENTWRITE_EOS)) == 0));
+ /* INFO is only INFO (with optional EOS) */
+ DEBUGASSERT(!(type & CLIENTWRITE_INFO) ||
+ ((type & ~(CLIENTWRITE_INFO|CLIENTWRITE_EOS)) == 0));
- if(data->req.writer_stack && !data->set.http_ce_skip)
- return Curl_unencode_write(data, data->req.writer_stack, ptr, len);
+ if(!data->req.writer_stack) {
+ result = do_init_stack(data);
+ if(result)
+ return result;
+ DEBUGASSERT(data->req.writer_stack);
}
- return chop_write(data, type, FALSE, ptr, len);
+
+ return Curl_cwriter_write(data, data->req.writer_stack, type, buf, blen);
}
CURLcode Curl_client_unpause(struct Curl_easy *data)
@@ -449,12 +448,12 @@ CURLcode Curl_client_unpause(struct Curl_easy *data)
void Curl_client_cleanup(struct Curl_easy *data)
{
- struct contenc_writer *writer = data->req.writer_stack;
+ struct Curl_cwriter *writer = data->req.writer_stack;
size_t i;
while(writer) {
- data->req.writer_stack = writer->downstream;
- writer->handler->close_writer(data, writer);
+ data->req.writer_stack = writer->next;
+ writer->cwt->do_close(data, writer);
free(writer);
writer = data->req.writer_stack;
}
@@ -463,61 +462,231 @@ void Curl_client_cleanup(struct Curl_easy *data)
Curl_dyn_free(&data->state.tempwrite[i].b);
}
data->state.tempcount = 0;
+ data->req.bytecount = 0;
+ data->req.headerline = 0;
+}
+/* Write data using an unencoding writer stack. "nbytes" is not
+ allowed to be 0. */
+CURLcode Curl_cwriter_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ if(!writer)
+ return CURLE_WRITE_ERROR;
+ return writer->cwt->do_write(data, writer, type, buf, nbytes);
}
-/* Real client writer: no downstream. */
-static CURLcode client_cew_init(struct Curl_easy *data,
- struct contenc_writer *writer)
+CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
- (void) data;
+ (void)data;
(void)writer;
return CURLE_OK;
}
-static CURLcode client_cew_write(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes)
+CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
{
- (void)writer;
- if(!nbytes || data->req.ignorebody)
- return CURLE_OK;
- return chop_write(data, CLIENTWRITE_BODY, FALSE, (char *)buf, nbytes);
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
}
-static void client_cew_close(struct Curl_easy *data,
- struct contenc_writer *writer)
+void Curl_cwriter_def_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
(void) data;
(void) writer;
}
-static const struct content_encoding client_cew = {
+/* Real client writer to installed callbacks. */
+static CURLcode cw_client_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ (void)writer;
+ if(!nbytes)
+ return CURLE_OK;
+ return chop_write(data, type, FALSE, (char *)buf, nbytes);
+}
+
+static const struct Curl_cwtype cw_client = {
+ "client",
+ NULL,
+ Curl_cwriter_def_init,
+ cw_client_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
+};
+
+static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit)
+{
+ if(limit != -1) {
+ /* How much more are we allowed to write? */
+ curl_off_t remain_diff;
+ remain_diff = limit - data->req.bytecount;
+ if(remain_diff < 0) {
+ /* already written too much! */
+ return 0;
+ }
+#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
+ else if(remain_diff > SSIZE_T_MAX) {
+ return SIZE_T_MAX;
+ }
+#endif
+ else {
+ return (size_t)remain_diff;
+ }
+ }
+ return SIZE_T_MAX;
+}
+
+/* Download client writer in phase CURL_CW_PROTOCOL that
+ * sees the "real" download body data. */
+static CURLcode cw_download_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ CURLcode result;
+ size_t nwrite, excess_len = 0;
+
+ if(!(type & CLIENTWRITE_BODY)) {
+ if((type & CLIENTWRITE_CONNECT) && data->set.suppress_connect_headers)
+ return CURLE_OK;
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+ }
+
+ if(!data->req.bytecount) {
+ Curl_pgrsTime(data, TIMER_STARTTRANSFER);
+ if(data->req.exp100 > EXP100_SEND_DATA)
+ /* set time stamp to compare with when waiting for the 100 */
+ data->req.start100 = Curl_now();
+ }
+
+ /* Here, we deal with REAL BODY bytes. All filtering and transfer
+ * encodings have been applied and only the true content, e.g. BODY,
+ * bytes are passed here.
+ * This allows us to check sizes, update stats, etc. independent
+ * from the protocol in play. */
+
+ if(data->req.no_body && nbytes > 0) {
+ /* BODY arrives although we want none, bail out */
+ streamclose(data->conn, "ignoring body");
+ DEBUGF(infof(data, "did not want a BODY, but seeing %zu bytes",
+ nbytes));
+ data->req.download_done = TRUE;
+ return CURLE_WEIRD_SERVER_REPLY;
+ }
+
+ /* Determine if we see any bytes in excess to what is allowed.
+ * We write the allowed bytes and handle excess further below.
+ * This gives deterministic BODY writes on varying buffer receive
+ * lengths. */
+ nwrite = nbytes;
+ if(-1 != data->req.maxdownload) {
+ size_t wmax = get_max_body_write_len(data, data->req.maxdownload);
+ if(nwrite > wmax) {
+ excess_len = nbytes - wmax;
+ nwrite = wmax;
+ }
+
+ if(nwrite == wmax) {
+ data->req.download_done = TRUE;
+ }
+ }
+
+ /* Error on too large filesize is handled below, after writing
+ * the permitted bytes */
+ if(data->set.max_filesize) {
+ size_t wmax = get_max_body_write_len(data, data->set.max_filesize);
+ if(nwrite > wmax) {
+ nwrite = wmax;
+ }
+ }
+
+ /* Update stats, write and report progress */
+ data->req.bytecount += nwrite;
+ ++data->req.bodywrites;
+ if(!data->req.ignorebody && nwrite) {
+ result = Curl_cwriter_write(data, writer->next, type, buf, nwrite);
+ if(result)
+ return result;
+ }
+ result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
+ if(result)
+ return result;
+
+ if(excess_len) {
+ if(!data->req.ignorebody) {
+ infof(data,
+ "Excess found writing body:"
+ " excess = %zu"
+ ", size = %" CURL_FORMAT_CURL_OFF_T
+ ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
+ ", bytecount = %" CURL_FORMAT_CURL_OFF_T,
+ excess_len, data->req.size, data->req.maxdownload,
+ data->req.bytecount);
+ connclose(data->conn, "excess found in a read");
+ }
+ }
+ else if(nwrite < nbytes) {
+ failf(data, "Exceeded the maximum allowed file size "
+ "(%" CURL_FORMAT_CURL_OFF_T ") with %"
+ CURL_FORMAT_CURL_OFF_T " bytes",
+ data->set.max_filesize, data->req.bytecount);
+ return CURLE_FILESIZE_EXCEEDED;
+ }
+
+ return CURLE_OK;
+}
+
+static const struct Curl_cwtype cw_download = {
+ "download",
NULL,
+ Curl_cwriter_def_init,
+ cw_download_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
+};
+
+/* RAW client writer in phase CURL_CW_RAW that
+ * enabled tracing of raw data. */
+static CURLcode cw_raw_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ if(type & CLIENTWRITE_BODY && data->set.verbose && !data->req.ignorebody) {
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)buf, nbytes);
+ }
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+}
+
+static const struct Curl_cwtype cw_raw = {
+ "raw",
NULL,
- client_cew_init,
- client_cew_write,
- client_cew_close,
- sizeof(struct contenc_writer)
+ Curl_cwriter_def_init,
+ cw_raw_write,
+ Curl_cwriter_def_close,
+ sizeof(struct Curl_cwriter)
};
/* Create an unencoding writer stage using the given handler. */
-CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
+CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
struct Curl_easy *data,
- const struct content_encoding *ce_handler,
- int order)
+ const struct Curl_cwtype *cwt,
+ Curl_cwriter_phase phase)
{
- struct contenc_writer *writer;
+ struct Curl_cwriter *writer;
CURLcode result = CURLE_OUT_OF_MEMORY;
- DEBUGASSERT(ce_handler->writersize >= sizeof(struct contenc_writer));
- writer = (struct contenc_writer *) calloc(1, ce_handler->writersize);
+ DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter));
+ writer = (struct Curl_cwriter *) calloc(1, cwt->cwriter_size);
if(!writer)
goto out;
- writer->handler = ce_handler;
- writer->order = order;
- result = ce_handler->init_writer(data, writer);
+ writer->cwt = cwt;
+ writer->phase = phase;
+ result = cwt->do_init(data, writer);
out:
*pwriter = result? NULL : writer;
@@ -526,58 +695,92 @@ out:
return result;
}
-void Curl_client_free_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+void Curl_cwriter_free(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
if(writer) {
- writer->handler->close_writer(data, writer);
+ writer->cwt->do_close(data, writer);
free(writer);
}
}
-/* allow no more than 5 "chained" compression steps */
-#define MAX_ENCODE_STACK 5
+size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase)
+{
+ struct Curl_cwriter *w;
+ size_t n = 0;
+ for(w = data->req.writer_stack; w; w = w->next) {
+ if(w->phase == phase)
+ ++n;
+ }
+ return n;
+}
-static CURLcode init_writer_stack(struct Curl_easy *data)
+static CURLcode do_init_stack(struct Curl_easy *data)
{
+ struct Curl_cwriter *writer;
+ CURLcode result;
+
DEBUGASSERT(!data->req.writer_stack);
- return Curl_client_create_writer(&data->req.writer_stack,
- data, &client_cew, 0);
+ result = Curl_cwriter_create(&data->req.writer_stack,
+ data, &cw_client, CURL_CW_CLIENT);
+ if(result)
+ return result;
+
+ result = Curl_cwriter_create(&writer, data, &cw_download, CURL_CW_PROTOCOL);
+ if(result)
+ return result;
+ result = Curl_cwriter_add(data, writer);
+ if(result) {
+ Curl_cwriter_free(data, writer);
+ }
+
+ result = Curl_cwriter_create(&writer, data, &cw_raw, CURL_CW_RAW);
+ if(result)
+ return result;
+ result = Curl_cwriter_add(data, writer);
+ if(result) {
+ Curl_cwriter_free(data, writer);
+ }
+ return result;
}
-CURLcode Curl_client_add_writer(struct Curl_easy *data,
- struct contenc_writer *writer)
+CURLcode Curl_cwriter_add(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
{
CURLcode result;
+ struct Curl_cwriter **anchor = &data->req.writer_stack;
- if(!data->req.writer_stack) {
- result = init_writer_stack(data);
+ if(!*anchor) {
+ result = do_init_stack(data);
if(result)
return result;
}
- if(data->req.writer_stack_depth++ >= MAX_ENCODE_STACK) {
- failf(data, "Reject response due to more than %u content encodings",
- MAX_ENCODE_STACK);
- return CURLE_BAD_CONTENT_ENCODING;
- }
-
- /* Stack the unencoding stage. */
- if(writer->order >= data->req.writer_stack->order) {
- writer->downstream = data->req.writer_stack;
- data->req.writer_stack = writer;
- }
- else {
- struct contenc_writer *w = data->req.writer_stack;
- while(w->downstream && writer->order < w->downstream->order)
- w = w->downstream;
- writer->downstream = w->downstream;
- w->downstream = writer;
- }
+ /* Insert the writer as first in its phase.
+ * Skip existing writers of lower phases. */
+ while(*anchor && (*anchor)->phase < writer->phase)
+ anchor = &((*anchor)->next);
+ writer->next = *anchor;
+ *anchor = writer;
return CURLE_OK;
}
+void Curl_cwriter_remove_by_name(struct Curl_easy *data,
+ const char *name)
+{
+ struct Curl_cwriter **anchor = &data->req.writer_stack;
+
+ while(*anchor) {
+ if(!strcmp(name, (*anchor)->cwt->name)) {
+ struct Curl_cwriter *w = (*anchor);
+ *anchor = w->next;
+ Curl_cwriter_free(data, w);
+ continue;
+ }
+ anchor = &((*anchor)->next);
+ }
+}
/*
* Internal read-from-socket function. This is meant to deal with plain
diff --git a/lib/sendf.h b/lib/sendf.h
index 9ee00bb0d..7deae2ac3 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -49,44 +49,127 @@
#define CLIENTWRITE_CONNECT (1<<4) /* a CONNECT related HEADER */
#define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */
#define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
+#define CLIENTWRITE_EOS (1<<7) /* End Of transfer download Stream */
+/**
+ * Write `len` bytes at `prt` to the client. `type` indicates what
+ * kind of data is being written.
+ */
CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
+/**
+ * For a paused transfer, there might be buffered data held back.
+ * Attempt to flush this data to the client. This *may* trigger
+ * another pause of the transfer.
+ */
CURLcode Curl_client_unpause(struct Curl_easy *data);
+
+/**
+ * Free all resources related to client writing.
+ */
void Curl_client_cleanup(struct Curl_easy *data);
-struct contenc_writer {
- const struct content_encoding *handler; /* Encoding handler. */
- struct contenc_writer *downstream; /* Downstream writer. */
- unsigned int order; /* Ordering within writer stack. */
+/**
+ * Client Writers - a chain passing transfer BODY data to the client.
+ * Main application: HTTP and related protocols
+ * Other uses: monitoring of download progress
+ *
+ * Writers in the chain are order by their `phase`. First come all
+ * writers in CURL_CW_RAW, followed by any in CURL_CW_TRANSFER_DECODE,
+ * followed by any in CURL_CW_PROTOCOL, etc.
+ *
+ * When adding a writer, it is inserted as first in its phase. This means
+ * the order of adding writers of the same phase matters, but writers for
+ * different phases may be added in any order.
+ *
+ * Writers which do modify the BODY data written are expected to be of
+ * phases TRANSFER_DECODE or CONTENT_DECODE. The other phases are intended
+ * for monitoring writers. Which do *not* modify the data but gather
+ * statistics or update progress reporting.
+ */
+
+/* Phase a writer operates at. */
+typedef enum {
+ CURL_CW_RAW, /* raw data written, before any decoding */
+ CURL_CW_TRANSFER_DECODE, /* remove transfer-encodings */
+ CURL_CW_PROTOCOL, /* after transfer, but before content decoding */
+ CURL_CW_CONTENT_DECODE, /* remove content-encodings */
+ CURL_CW_CLIENT /* data written to client */
+} Curl_cwriter_phase;
+
+/* Client Writer Type, provides the implementation */
+struct Curl_cwtype {
+ const char *name; /* writer name. */
+ const char *alias; /* writer name alias, maybe NULL. */
+ CURLcode (*do_init)(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+ CURLcode (*do_write)(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes);
+ void (*do_close)(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+ size_t cwriter_size; /* sizeof() allocated struct Curl_cwriter */
};
-/* Content encoding writer. */
-struct content_encoding {
- const char *name; /* Encoding name. */
- const char *alias; /* Encoding name alias. */
- CURLcode (*init_writer)(struct Curl_easy *data,
- struct contenc_writer *writer);
- CURLcode (*unencode_write)(struct Curl_easy *data,
- struct contenc_writer *writer,
- const char *buf, size_t nbytes);
- void (*close_writer)(struct Curl_easy *data,
- struct contenc_writer *writer);
- size_t writersize;
+/* Client writer instance */
+struct Curl_cwriter {
+ const struct Curl_cwtype *cwt; /* type implementation */
+ struct Curl_cwriter *next; /* Downstream writer. */
+ Curl_cwriter_phase phase; /* phase at which it operates */
};
+/**
+ * Create a new cwriter instance with given type and phase. Is not
+ * inserted into the writer chain by this call.
+ * Invokes `writer->do_init()`.
+ */
+CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter,
+ struct Curl_easy *data,
+ const struct Curl_cwtype *ce_handler,
+ Curl_cwriter_phase phase);
+
+/**
+ * Free a cwriter instance.
+ * Invokes `writer->do_close()`.
+ */
+void Curl_cwriter_free(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+
+/**
+ * Count the number of writers installed of the given phase.
+ */
+size_t Curl_cwriter_count(struct Curl_easy *data, Curl_cwriter_phase phase);
+
+/**
+ * Adds a writer to the transfer's writer chain.
+ * The writers `phase` determines where in the chain it is inserted.
+ */
+CURLcode Curl_cwriter_add(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
-CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
- struct Curl_easy *data,
- const struct content_encoding *ce_handler,
- int order);
+void Curl_cwriter_remove_by_name(struct Curl_easy *data,
+ const char *name);
-void Curl_client_free_writer(struct Curl_easy *data,
- struct contenc_writer *writer);
+/**
+ * Convenience method for calling `writer->do_write()` that
+ * checks for NULL writer.
+ */
+CURLcode Curl_cwriter_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes);
-CURLcode Curl_client_add_writer(struct Curl_easy *data,
- struct contenc_writer *writer);
+/**
+ * Default implementations for do_init, do_write, do_close that
+ * do nothing and pass the data through.
+ */
+CURLcode Curl_cwriter_def_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
+CURLcode Curl_cwriter_def_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes);
+void Curl_cwriter_def_close(struct Curl_easy *data,
+ struct Curl_cwriter *writer);
/* internal read-function, does plain socket, SSL and krb4 */
diff --git a/lib/setopt.c b/lib/setopt.c
index 0d399adfe..a5270773f 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -50,7 +50,8 @@
#include "multiif.h"
#include "altsvc.h"
#include "hsts.h"
-
+#include "tftp.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -171,7 +172,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val)
str = strchr(str, ',');
tlen = str? (size_t) (str - token): strlen(token);
if(tlen) {
- const struct Curl_handler *h = Curl_builtin_scheme(token, tlen);
+ const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen);
if(!h)
return CURLE_UNSUPPORTED_PROTOCOL;
@@ -261,43 +262,43 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set the absolute number of maximum simultaneous alive connection that
* libcurl is allowed to have.
*/
- arg = va_arg(param, long);
- if(arg < 0)
+ uarg = va_arg(param, unsigned long);
+ if(uarg > UINT_MAX)
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.maxconnects = arg;
+ data->set.maxconnects = (unsigned int)uarg;
break;
case CURLOPT_FORBID_REUSE:
/*
* When this transfer is done, it must not be left to be reused by a
* subsequent transfer but shall be closed immediately.
*/
- data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.reuse_forbid = (0 != va_arg(param, long));
break;
case CURLOPT_FRESH_CONNECT:
/*
* This transfer shall not use a previously cached connection but
* should be made with a fresh new connect!
*/
- data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.reuse_fresh = (0 != va_arg(param, long));
break;
case CURLOPT_VERBOSE:
/*
* Verbose means infof() calls that give a lot of information about
* the connection and transfer procedures as well as internal choices.
*/
- data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.verbose = (0 != va_arg(param, long));
break;
case CURLOPT_HEADER:
/*
* Set to include the header in the general data output stream.
*/
- data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.include_header = (0 != va_arg(param, long));
break;
case CURLOPT_NOPROGRESS:
/*
* Shut off the internal supported progress meter
*/
- data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.hide_progress = (0 != va_arg(param, long));
if(data->set.hide_progress)
data->progress.flags |= PGRS_HIDE;
else
@@ -307,7 +308,7 @@ 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;
+ data->set.opt_no_body = (0 != va_arg(param, long));
#ifndef CURL_DISABLE_HTTP
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
@@ -321,11 +322,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Don't output the >=400 error code HTML-page, but instead only
* return error.
*/
- data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_fail_on_error = (0 != va_arg(param, long));
break;
case CURLOPT_KEEP_SENDING_ON_ERROR:
- data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.http_keep_sending_on_error = (0 != va_arg(param, long));
break;
case CURLOPT_UPLOAD:
case CURLOPT_PUT:
@@ -353,7 +353,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Try to get the file time of the remote document. The time will
* later (possibly) become available using curl_easy_getinfo().
*/
- data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.get_filetime = (0 != va_arg(param, long));
break;
case CURLOPT_SERVER_RESPONSE_TIMEOUT:
/*
@@ -366,6 +366,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
+ case CURLOPT_SERVER_RESPONSE_TIMEOUT_MS:
+ /*
+ * Option that specifies how quickly a server response must be obtained
+ * before it is considered failure. For pingpong protocols.
+ */
+ arg = va_arg(param, long);
+ if((arg >= 0) && (arg <= INT_MAX))
+ data->set.server_response_timeout = (unsigned int)arg;
+ else
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ break;
#ifndef CURL_DISABLE_TFTP
case CURLOPT_TFTP_NO_OPTIONS:
/*
@@ -379,7 +390,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* TFTP option that specifies the block size to use for data transmission.
*/
arg = va_arg(param, long);
- if(arg < 0)
+ if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN)
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.tftp_blksize = arg;
break;
@@ -409,7 +420,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*
* Transfer using ASCII (instead of BINARY).
*/
- data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.prefer_ascii = (0 != va_arg(param, long));
break;
case CURLOPT_TIMECONDITION:
/*
@@ -497,26 +508,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
(data->set.postfieldsize > (curl_off_t)((size_t)-1))))
result = CURLE_OUT_OF_MEMORY;
else {
- char *p;
-
- (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
-
/* Allocate even when size == 0. This satisfies the need of possible
- later address compare to detect the COPYPOSTFIELDS mode, and
- to mark that postfields is used rather than read function or
- form data.
+ later address compare to detect the COPYPOSTFIELDS mode, and to
+ mark that postfields is used rather than read function or form
+ data.
*/
- p = malloc((size_t)(data->set.postfieldsize?
- data->set.postfieldsize:1));
-
+ char *p = Curl_memdup0(argptr, (size_t)data->set.postfieldsize);
+ (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
if(!p)
result = CURLE_OUT_OF_MEMORY;
- else {
- if(data->set.postfieldsize)
- memcpy(p, argptr, (size_t)data->set.postfieldsize);
-
+ else
data->set.str[STRING_COPYPOSTFIELDS] = p;
- }
}
}
@@ -577,7 +579,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Switch on automatic referer that gets set if curl follows locations.
*/
- data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_auto_referer = (0 != va_arg(param, long));
break;
case CURLOPT_ACCEPT_ENCODING:
@@ -592,28 +594,23 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
argptr = va_arg(param, char *);
if(argptr && !*argptr) {
- argptr = Curl_all_content_encodings();
- if(!argptr)
- result = CURLE_OUT_OF_MEMORY;
- else {
- result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
- free(argptr);
- }
+ char all[256];
+ Curl_all_content_encodings(all, sizeof(all));
+ result = Curl_setstropt(&data->set.str[STRING_ENCODING], all);
}
else
result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
break;
case CURLOPT_TRANSFER_ENCODING:
- data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.http_transfer_encoding = (0 != va_arg(param, long));
break;
case CURLOPT_FOLLOWLOCATION:
/*
* Follow Location: header hints on an HTTP-server.
*/
- data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_follow_location = (0 != va_arg(param, long));
break;
case CURLOPT_UNRESTRICTED_AUTH:
@@ -621,8 +618,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Send authentication (user+password) when following locations, even when
* hostname changed.
*/
- data->set.allow_auth_to_other_hosts =
- (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long));
break;
case CURLOPT_MAXREDIRS:
@@ -676,6 +672,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.opt_no_body = FALSE; /* this is implied */
Curl_mime_cleanpart(data->state.formp);
Curl_safefree(data->state.formp);
+ data->state.mimepost = NULL;
break;
#endif
@@ -736,7 +733,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set header option.
*/
arg = va_arg(param, long);
- data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE);
+ data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE);
break;
#if !defined(CURL_DISABLE_COOKIES)
@@ -760,18 +757,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
return CURLE_BAD_FUNCTION_ARGUMENT;
/* append the cookie file name to the list of file names, and deal with
them later */
- cl = curl_slist_append(data->set.cookielist, argptr);
+ cl = curl_slist_append(data->state.cookielist, argptr);
if(!cl) {
- curl_slist_free_all(data->set.cookielist);
- data->set.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
return CURLE_OUT_OF_MEMORY;
}
- data->set.cookielist = cl; /* store the list for later use */
+ data->state.cookielist = cl; /* store the list for later use */
}
else {
/* clear the list of cookie files */
- curl_slist_free_all(data->set.cookielist);
- data->set.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
if(!data->share || !data->share->cookies) {
/* throw away all existing cookies if this isn't a shared cookie
@@ -811,17 +808,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* prevent the forthcoming read-cookies-from-file actions to accept
* cookies that are marked as being session cookies, as they belong to a
* previous session.
- *
- * In the original Netscape cookie spec, "session cookies" are cookies
- * with no expire date set. RFC2109 describes the same action if no
- * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
- * a 'Discard' action that can enforce the discard even for cookies that
- * have a Max-Age.
- *
- * We run mostly with the original cookie spec, as hardly anyone implements
- * anything else.
*/
- data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.cookiesession = (0 != va_arg(param, long));
break;
case CURLOPT_COOKIELIST:
@@ -956,7 +944,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
if(arg)
return CURLE_BAD_FUNCTION_ARGUMENT;
#else
- data->set.http09_allowed = arg ? TRUE : FALSE;
+ data->set.http09_allowed = !!arg;
#endif
break;
@@ -992,13 +980,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#ifndef CURL_DISABLE_FORM_API
Curl_mime_cleanpart(data->state.formp);
Curl_safefree(data->state.formp);
+ data->state.mimepost = NULL;
#endif
}
break;
case CURLOPT_MIME_OPTIONS:
- data->set.mime_options = (unsigned int)va_arg(param, long);
- break;
+ arg = va_arg(param, long);
+ data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE);
+ break;
# endif
#endif
@@ -1018,8 +1008,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
- data->state.authhost.iestyle =
- (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
+ data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1072,8 +1061,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Tunnel operations through the proxy instead of normal proxy use
*/
- data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long));
break;
case CURLOPT_PROXYPORT:
@@ -1102,8 +1090,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* the DIGEST_IE bit is only used to set a special marker, for all the
rest we need to handle it as normal DIGEST */
- data->state.authproxy.iestyle =
- (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE);
+ data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE);
if(auth & CURLAUTH_DIGEST_IE) {
auth |= CURLAUTH_DIGEST; /* set standard digest bit */
@@ -1203,7 +1190,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Set flag for NEC SOCK5 support
*/
- data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.socks5_gssapi_nec = (0 != va_arg(param, long));
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1251,7 +1238,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* An option that changes the command to one that asks for a list only, no
* file info details. Used for FTP, POP3 and SFTP.
*/
- data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.list_only = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_APPEND:
@@ -1259,7 +1246,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* We want to upload and append to an existing file. Used for FTP and
* SFTP.
*/
- data->set.remote_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.remote_append = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_FTP
@@ -1270,7 +1257,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg;
+ data->set.ftp_filemethod = (unsigned char)arg;
break;
case CURLOPT_FTPPORT:
/*
@@ -1278,26 +1265,26 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
va_arg(param, char *));
- data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
+ data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]);
break;
case CURLOPT_FTP_USE_EPRT:
- data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_use_eprt = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_USE_EPSV:
- data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_use_epsv = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_USE_PRET:
- data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_use_pret = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_SSL_CCC:
arg = va_arg(param, long);
if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
- data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg;
+ data->set.ftp_ccc = (unsigned char)arg;
break;
case CURLOPT_FTP_SKIP_PASV_IP:
@@ -1305,7 +1292,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
* bypass of the IP address in PASV responses.
*/
- data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ftp_skip_ip = (0 != va_arg(param, long));
break;
case CURLOPT_FTP_ACCOUNT:
@@ -1333,7 +1320,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
va_arg(param, char *));
- data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
+ data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]);
break;
#endif
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
@@ -1867,14 +1854,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Kludgy option to enable CRLF conversions. Subject for removal.
*/
- data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.crlf = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_HAPROXYPROTOCOL:
/*
* Set to send the HAProxy Proxy Protocol header
*/
- data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.haproxyprotocol = (0 != va_arg(param, long));
break;
case CURLOPT_HAPROXY_CLIENT_IP:
/*
@@ -1926,22 +1913,17 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Enable peer SSL verifying.
*/
- data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.ssl.primary.verifypeer = (0 != va_arg(param, long));
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifypeer =
- data->set.ssl.primary.verifypeer;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYPEER:
/*
* Enable peer SSL verifying for DoH.
*/
- data->set.doh_verifypeer = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.doh_verifypeer = (0 != va_arg(param, long));
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1953,10 +1935,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
(0 != va_arg(param, long))?TRUE:FALSE;
/* Update the current connection proxy_ssl_config. */
- if(data->conn) {
- data->conn->proxy_ssl_config.verifypeer =
- data->set.proxy_ssl.primary.verifypeer;
- }
+ Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYHOST:
@@ -1968,13 +1947,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* Obviously people are not reading documentation and too many thought
this argument took a boolean when it wasn't and misused it.
Treat 1 and 2 the same */
- data->set.ssl.primary.verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
+ data->set.ssl.primary.verifyhost = !!(arg & 3);
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifyhost =
- data->set.ssl.primary.verifyhost;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYHOST:
@@ -1984,7 +1960,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
/* Treat both 1 and 2 as TRUE */
- data->set.doh_verifyhost = (bool)((arg & 3) ? TRUE : FALSE);
+ data->set.doh_verifyhost = !!(arg & 3);
break;
#endif
#ifndef CURL_DISABLE_PROXY
@@ -1996,12 +1972,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* Treat both 1 and 2 as TRUE */
data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE);
-
/* Update the current connection proxy_ssl_config. */
- if(data->conn) {
- data->conn->proxy_ssl_config.verifyhost =
- data->set.proxy_ssl.primary.verifyhost;
- }
+ Curl_ssl_conn_config_update(data, TRUE);
break;
#endif
case CURLOPT_SSL_VERIFYSTATUS:
@@ -2013,14 +1985,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
- data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.ssl.primary.verifystatus = (0 != va_arg(param, long));
/* Update the current connection ssl_config. */
- if(data->conn) {
- data->conn->ssl_config.verifystatus =
- data->set.ssl.primary.verifystatus;
- }
+ Curl_ssl_conn_config_update(data, FALSE);
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_SSL_VERIFYSTATUS:
@@ -2032,8 +2000,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
- data->set.doh_verifystatus = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.doh_verifystatus = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_SSL_CTX_FUNCTION:
@@ -2067,12 +2034,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
- data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.falsestart = (0 != va_arg(param, long));
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
- data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl.certinfo = (0 != va_arg(param, long));
else
#endif
result = CURLE_NOT_BUILT_IN;
@@ -2118,14 +2085,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
- if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
+ if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
va_arg(param, struct curl_blob *));
+ break;
+ }
else
#endif
return CURLE_NOT_BUILT_IN;
-
- break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_CAINFO:
/*
@@ -2141,13 +2108,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
- if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
+ if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) {
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
va_arg(param, struct curl_blob *));
+ break;
+ }
else
#endif
return CURLE_NOT_BUILT_IN;
- break;
#endif
case CURLOPT_CAPATH:
/*
@@ -2278,7 +2246,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* The application asks not to set any signal() or alarm() handlers,
* even when using a timeout.
*/
- data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.no_signal = (0 != va_arg(param, long));
break;
case CURLOPT_SHARE:
@@ -2453,11 +2421,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Enable or disable TCP_NODELAY, which will disable/enable the Nagle
* algorithm
*/
- data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.tcp_nodelay = (0 != va_arg(param, long));
break;
case CURLOPT_IGNORE_CONTENT_LENGTH:
- data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ignorecl = (0 != va_arg(param, long));
break;
case CURLOPT_CONNECT_ONLY:
@@ -2532,8 +2500,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSL_SESSIONID_CACHE:
- data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
- TRUE : FALSE;
+ data->set.ssl.primary.sessionid = (0 != va_arg(param, long));
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
#endif
@@ -2622,7 +2589,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* disable libcurl transfer encoding is used
*/
#ifndef USE_HYPER
- data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_te_skip = (0 == va_arg(param, long));
break;
#else
return CURLE_NOT_BUILT_IN; /* hyper doesn't support */
@@ -2632,7 +2599,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* raw data passed to the application when content encoding is used
*/
- data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
+ data->set.http_ce_skip = (0 == va_arg(param, long));
break;
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
@@ -2733,7 +2700,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_MAIL_RCPT_ALLOWFAILS:
/* allow RCPT TO command to fail for some recipients */
- data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.mail_rcpt_allowfails = (0 != va_arg(param, long));
break;
#endif
@@ -2745,7 +2712,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SASL_IR:
/* Enable/disable SASL initial response */
- data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.sasl_ir = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_RTSP
case CURLOPT_RTSP_REQUEST:
@@ -2859,7 +2826,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
#ifndef CURL_DISABLE_FTP
case CURLOPT_WILDCARDMATCH:
- data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.wildcard_enabled = (0 != va_arg(param, long));
break;
case CURLOPT_CHUNK_BGN_FUNCTION:
data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
@@ -2942,7 +2909,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
case CURLOPT_TCP_KEEPALIVE:
- data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.tcp_keepalive = (0 != va_arg(param, long));
break;
case CURLOPT_TCP_KEEPIDLE:
arg = va_arg(param, long);
@@ -2971,7 +2938,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SSL_ENABLE_NPN:
break;
case CURLOPT_SSL_ENABLE_ALPN:
- data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.ssl_enable_alpn = (0 != va_arg(param, long));
break;
#ifdef USE_UNIX_SOCKETS
case CURLOPT_UNIX_SOCKET_PATH:
@@ -2987,10 +2954,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
case CURLOPT_PATH_AS_IS:
- data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.path_as_is = (0 != va_arg(param, long));
break;
case CURLOPT_PIPEWAIT:
- data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.pipewait = (0 != va_arg(param, long));
break;
case CURLOPT_STREAM_WEIGHT:
#if defined(USE_HTTP2) || defined(USE_HTTP3)
@@ -3025,12 +2992,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#ifndef CURL_DISABLE_SHUFFLE_DNS
case CURLOPT_DNS_SHUFFLE_ADDRESSES:
- data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
+ data->set.dns_shuffle_addresses = (0 != va_arg(param, long));
break;
#endif
case CURLOPT_DISALLOW_USERNAME_IN_URL:
- data->set.disallow_username_in_url =
- (0 != va_arg(param, long)) ? TRUE : FALSE;
+ data->set.disallow_username_in_url = (0 != va_arg(param, long));
break;
#ifndef CURL_DISABLE_DOH
case CURLOPT_DOH_URL:
@@ -3095,18 +3061,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* this needs to build a list of file names to read from, so that it can
read them later, as we might get a shared HSTS handle to load them
into */
- h = curl_slist_append(data->set.hstslist, argptr);
+ h = curl_slist_append(data->state.hstslist, argptr);
if(!h) {
- curl_slist_free_all(data->set.hstslist);
- data->set.hstslist = NULL;
+ curl_slist_free_all(data->state.hstslist);
+ data->state.hstslist = NULL;
return CURLE_OUT_OF_MEMORY;
}
- data->set.hstslist = h; /* store the list for later use */
+ data->state.hstslist = h; /* store the list for later use */
}
else {
/* clear the list of HSTS files */
- curl_slist_free_all(data->set.hstslist);
- data->set.hstslist = NULL;
+ curl_slist_free_all(data->state.hstslist);
+ data->state.hstslist = NULL;
if(!data->share || !data->share->hsts)
/* throw away the HSTS cache unless shared */
Curl_hsts_cleanup(&data->hsts);
@@ -3147,6 +3113,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
return CURLE_OUT_OF_MEMORY;
}
arg = va_arg(param, long);
+ if(!arg) {
+ DEBUGF(infof(data, "bad CURLOPT_ALTSVC_CTRL input"));
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
result = Curl_altsvc_ctrl(data->asi, arg);
if(result)
return result;
@@ -3201,5 +3171,9 @@ CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
result = Curl_vsetopt(data, tag, arg);
va_end(arg);
+#ifdef DEBUGBUILD
+ if(result == CURLE_BAD_FUNCTION_ARGUMENT)
+ infof(data, "setopt arg 0x%x returned CURLE_BAD_FUNCTION_ARGUMENT", tag);
+#endif
return result;
}
diff --git a/lib/setup-win32.h b/lib/setup-win32.h
index 13948389a..d7e2e6be1 100644
--- a/lib/setup-win32.h
+++ b/lib/setup-win32.h
@@ -24,18 +24,53 @@
*
***************************************************************************/
+#undef USE_WINSOCK
+/* ---------------------------------------------------------------- */
+/* Watt-32 TCP/IP SPECIFIC */
+/* ---------------------------------------------------------------- */
+#ifdef USE_WATT32
+# include <tcp.h>
+# undef byte
+# undef word
+# define HAVE_SYS_IOCTL_H
+# define HAVE_SYS_SOCKET_H
+# define HAVE_NETINET_IN_H
+# define HAVE_NETDB_H
+# define HAVE_ARPA_INET_H
+# define SOCKET int
+/* ---------------------------------------------------------------- */
+/* BSD-style lwIP TCP/IP stack SPECIFIC */
+/* ---------------------------------------------------------------- */
+#elif defined(USE_LWIPSOCK)
+ /* Define to use BSD-style lwIP TCP/IP stack. */
+ /* #define USE_LWIPSOCK 1 */
+# undef HAVE_GETHOSTNAME
+# undef LWIP_POSIX_SOCKETS_IO_NAMES
+# undef RECV_TYPE_ARG1
+# undef RECV_TYPE_ARG3
+# undef SEND_TYPE_ARG1
+# undef SEND_TYPE_ARG3
+# define HAVE_GETHOSTBYNAME_R
+# define HAVE_GETHOSTBYNAME_R_6
+# define LWIP_POSIX_SOCKETS_IO_NAMES 0
+# define RECV_TYPE_ARG1 int
+# define RECV_TYPE_ARG3 size_t
+# define SEND_TYPE_ARG1 int
+# define SEND_TYPE_ARG3 size_t
+#elif defined(_WIN32)
+# define USE_WINSOCK 2
+#endif
+
/*
* Include header files for windows builds before redefining anything.
* Use this preprocessor block only to include or exclude windows.h,
* winsock2.h or ws2tcpip.h. Any other windows thing belongs
* to any other further and independent block. Under Cygwin things work
* just as under linux (e.g. <sys/socket.h>) and the winsock headers should
- * never be included when __CYGWIN__ is defined. configure script takes
- * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK2_H,
- * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
+ * never be included when __CYGWIN__ is defined.
*/
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# if defined(UNICODE) && !defined(_UNICODE)
# error "UNICODE is defined but _UNICODE is not defined"
# endif
@@ -53,14 +88,10 @@
# ifndef NOGDI
# define NOGDI
# endif
-# include <winerror.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# ifdef HAVE_WS2TCPIP_H
-# include <ws2tcpip.h>
-# endif
-# endif
+# include <winerror.h>
# include <tchar.h>
# ifdef UNICODE
typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
@@ -68,17 +99,6 @@
#endif
/*
- * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
- * undefine USE_WINSOCK.
- */
-
-#undef USE_WINSOCK
-
-#ifdef HAVE_WINSOCK2_H
-# define USE_WINSOCK 2
-#endif
-
-/*
* Define _WIN32_WINNT_[OS] symbols because not all Windows build systems have
* those symbols to compare against, and even those that do may be missing
* newer symbols.
@@ -96,18 +116,12 @@
#ifndef _WIN32_WINNT_WS03
#define _WIN32_WINNT_WS03 0x0502 /* Windows Server 2003 */
#endif
-#ifndef _WIN32_WINNT_WIN6
-#define _WIN32_WINNT_WIN6 0x0600 /* Windows Vista */
-#endif
#ifndef _WIN32_WINNT_VISTA
#define _WIN32_WINNT_VISTA 0x0600 /* Windows Vista */
#endif
#ifndef _WIN32_WINNT_WS08
#define _WIN32_WINNT_WS08 0x0600 /* Windows Server 2008 */
#endif
-#ifndef _WIN32_WINNT_LONGHORN
-#define _WIN32_WINNT_LONGHORN 0x0600 /* Windows Vista */
-#endif
#ifndef _WIN32_WINNT_WIN7
#define _WIN32_WINNT_WIN7 0x0601 /* Windows 7 */
#endif
@@ -117,9 +131,6 @@
#ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0603 /* Windows 8.1 */
#endif
-#ifndef _WIN32_WINNT_WINTHRESHOLD
-#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 /* Windows 10 */
-#endif
#ifndef _WIN32_WINNT_WIN10
#define _WIN32_WINNT_WIN10 0x0A00 /* Windows 10 */
#endif
diff --git a/lib/share.c b/lib/share.c
index c0a8d806f..8fa5cda00 100644
--- a/lib/share.c
+++ b/lib/share.c
@@ -133,13 +133,13 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
res = CURLSHE_BAD_OPTION;
}
if(!res)
- share->specifier |= (1<<type);
+ share->specifier |= (unsigned int)(1<<type);
break;
case CURLSHOPT_UNSHARE:
/* this is a type this share will no longer share */
type = va_arg(param, int);
- share->specifier &= ~(1<<type);
+ share->specifier &= ~(unsigned int)(1<<type);
switch(type) {
case CURL_LOCK_DATA_DNS:
break;
@@ -264,7 +264,7 @@ Curl_share_lock(struct Curl_easy *data, curl_lock_data type,
if(!share)
return CURLSHE_INVALID;
- if(share->specifier & (1<<type)) {
+ if(share->specifier & (unsigned int)(1<<type)) {
if(share->lockfunc) /* only call this if set! */
share->lockfunc(data, type, accesstype, share->clientdata);
}
@@ -281,7 +281,7 @@ Curl_share_unlock(struct Curl_easy *data, curl_lock_data type)
if(!share)
return CURLSHE_INVALID;
- if(share->specifier & (1<<type)) {
+ if(share->specifier & (unsigned int)(1<<type)) {
if(share->unlockfunc) /* only call this if set! */
share->unlockfunc (data, type, share->clientdata);
}
diff --git a/lib/share.h b/lib/share.h
index 7f55aac85..632d9198f 100644
--- a/lib/share.h
+++ b/lib/share.h
@@ -31,14 +31,6 @@
#include "urldata.h"
#include "conncache.h"
-/* SalfordC says "A structure member may not be volatile". Hence:
- */
-#ifdef __SALFORDC__
-#define CURL_VOLATILE
-#else
-#define CURL_VOLATILE volatile
-#endif
-
#define CURL_GOOD_SHARE 0x7e117a1e
#define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE)
@@ -46,7 +38,7 @@
struct Curl_share {
unsigned int magic; /* CURL_GOOD_SHARE */
unsigned int specifier;
- CURL_VOLATILE unsigned int dirty;
+ volatile unsigned int dirty;
curl_lock_function lockfunc;
curl_unlock_function unlockfunc;
diff --git a/lib/smb.c b/lib/smb.c
index 32c5137a4..1d1867cc2 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -27,7 +27,7 @@
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
-#ifdef WIN32
+#ifdef _WIN32
#define getpid GetCurrentProcessId
#endif
@@ -272,7 +272,7 @@ const struct Curl_handler Curl_handler_smb = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
smb_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SMB, /* defport */
@@ -299,7 +299,7 @@ const struct Curl_handler Curl_handler_smbs = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
smb_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SMBS, /* defport */
@@ -1047,14 +1047,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
break;
}
}
- data->req.bytecount += len;
data->req.offset += len;
- result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
- if(result) {
- req->result = result;
- next_state = SMB_CLOSE;
- break;
- }
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
break;
diff --git a/lib/smtp.c b/lib/smtp.c
index 81a17e38d..bfe7b8f12 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -130,7 +130,7 @@ const struct Curl_handler Curl_handler_smtp = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SMTP, /* defport */
@@ -159,7 +159,7 @@ const struct Curl_handler Curl_handler_smtps = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SMTPS, /* defport */
@@ -250,8 +250,8 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn,
*/
static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out)
{
- char *message = data->state.buffer;
- size_t len = strlen(message);
+ char *message = Curl_dyn_ptr(&data->conn->proto.smtpc.pp.recvbuf);
+ size_t len = data->conn->proto.smtpc.pp.nfinal;
if(len > 4) {
/* Find the start of the message */
@@ -859,7 +859,7 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
/* Pipelining in response is forbidden. */
- if(data->conn->proto.smtpc.pp.cache_size)
+ if(data->conn->proto.smtpc.pp.overflow)
return CURLE_WEIRD_SERVER_REPLY;
if(smtpcode != 220) {
@@ -883,8 +883,8 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
- const char *line = data->state.buffer;
- size_t len = strlen(line);
+ const char *line = Curl_dyn_ptr(&smtpc->pp.recvbuf);
+ size_t len = smtpc->pp.nfinal;
(void)instate; /* no use for this yet */
@@ -1033,8 +1033,8 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
{
CURLcode result = CURLE_OK;
struct SMTP *smtp = data->req.p.smtp;
- char *line = data->state.buffer;
- size_t len = strlen(line);
+ char *line = Curl_dyn_ptr(&data->conn->proto.smtpc.pp.recvbuf);
+ size_t len = data->conn->proto.smtpc.pp.nfinal;
(void)instate; /* no use for this yet */
@@ -1044,12 +1044,8 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
result = CURLE_WEIRD_SERVER_REPLY;
}
else {
- /* Temporarily add the LF character back and send as body to the client */
- if(!data->req.no_body) {
- line[len] = '\n';
- result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
- line[len] = '\0';
- }
+ if(!data->req.no_body)
+ result = Curl_client_write(data, CLIENTWRITE_BODY, line, len);
if(smtpcode != 1) {
if(smtp->rcpt) {
@@ -1268,7 +1264,6 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
break;
case SMTP_QUIT:
- /* fallthrough, just stop! */
default:
/* internal error */
smtp_state(data, SMTP_STOP);
@@ -1320,7 +1315,7 @@ static CURLcode smtp_init(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct SMTP *smtp;
- smtp = data->req.p.smtp = calloc(sizeof(struct SMTP), 1);
+ smtp = data->req.p.smtp = calloc(1, sizeof(struct SMTP));
if(!smtp)
result = CURLE_OUT_OF_MEMORY;
@@ -1362,8 +1357,7 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
Curl_sasl_init(&smtpc->sasl, data, &saslsmtp);
/* Initialise the pingpong layer */
- Curl_pp_setup(pp);
- Curl_pp_init(data, pp);
+ Curl_pp_init(pp);
/* Parse the URL options */
result = smtp_parse_url_options(conn);
@@ -1541,6 +1535,8 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
static CURLcode smtp_do(struct Curl_easy *data, bool *done)
{
CURLcode result = CURLE_OK;
+ DEBUGASSERT(data);
+ DEBUGASSERT(data->conn);
*done = FALSE; /* default to false */
/* Parse the custom request */
diff --git a/lib/socketpair.c b/lib/socketpair.c
index 963e1406f..d01b25513 100644
--- a/lib/socketpair.c
+++ b/lib/socketpair.c
@@ -28,14 +28,11 @@
#include "rand.h"
#if !defined(HAVE_SOCKETPAIR) && !defined(CURL_DISABLE_SOCKETPAIR)
-#ifdef WIN32
+#ifdef _WIN32
/*
* This is a socketpair() implementation for Windows.
*/
#include <string.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
#include <io.h>
#else
#ifdef HAVE_NETDB_H
@@ -50,7 +47,7 @@
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif /* !INADDR_LOOPBACK */
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
#include "nonblock.h" /* for curlx_nonblock */
#include "timeval.h" /* needed before select.h */
@@ -87,7 +84,7 @@ int Curl_socketpair(int domain, int type, int protocol,
socks[0] = socks[1] = CURL_SOCKET_BAD;
-#if defined(WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32) || defined(__CYGWIN__)
/* don't set SO_REUSEADDR on Windows */
(void)reuse;
#ifdef SO_EXCLUSIVEADDRUSE
diff --git a/lib/socketpair.h b/lib/socketpair.h
index 306ab5dc4..bd499abbe 100644
--- a/lib/socketpair.h
+++ b/lib/socketpair.h
@@ -25,6 +25,23 @@
***************************************************************************/
#include "curl_setup.h"
+
+#ifdef HAVE_PIPE
+
+#define wakeup_write write
+#define wakeup_read read
+#define wakeup_close close
+#define wakeup_create pipe
+
+#else /* HAVE_PIPE */
+
+#define wakeup_write swrite
+#define wakeup_read sread
+#define wakeup_close sclose
+#define wakeup_create(p) Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, p)
+
+#endif /* HAVE_PIPE */
+
#ifndef HAVE_SOCKETPAIR
#include <curl/curl.h>
diff --git a/lib/socks.c b/lib/socks.c
index a7b5ab07e..ecd2f7eab 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -71,9 +71,18 @@ enum connect_t {
CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
};
+#define CURL_SOCKS_BUF_SIZE 600
+
+/* make sure we configure it not too low */
+#if CURL_SOCKS_BUF_SIZE < 600
+#error CURL_SOCKS_BUF_SIZE must be at least 600
+#endif
+
+
struct socks_state {
enum connect_t state;
ssize_t outstanding; /* send this many bytes more */
+ unsigned char buffer[CURL_SOCKS_BUF_SIZE];
unsigned char *outp; /* send from this pointer */
const char *hostname;
@@ -249,7 +258,7 @@ static CURLproxycode socks_state_recv(struct Curl_cfilter *cf,
failf(data, "connection to proxy closed");
return CURLPX_CLOSED;
}
- failf(data, "SOCKS4: Failed receiving %s: %s", description,
+ failf(data, "SOCKS: Failed receiving %s: %s", description,
curl_easy_strerror(result));
return failcode;
}
@@ -278,14 +287,11 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
struct connectdata *conn = cf->conn;
const bool protocol4a =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
- unsigned char *socksreq = (unsigned char *)data->state.buffer;
+ unsigned char *socksreq = sx->buffer;
CURLcode result;
CURLproxycode presult;
struct Curl_dns_entry *dns = NULL;
- /* make sure that the buffer is at least 600 bytes */
- DEBUGASSERT(READBUFFER_MIN >= 600);
-
switch(sx->state) {
case CONNECT_SOCKS_INIT:
/* SOCKS4 can only do IPv4, insist! */
@@ -353,9 +359,10 @@ static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
return CURLPX_OK;
}
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
+ case CONNECT_RESOLVED:
CONNECT_RESOLVED:
- case CONNECT_RESOLVED: {
+ {
struct Curl_addrinfo *hp = NULL;
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
@@ -393,17 +400,20 @@ CONNECT_RESOLVED:
if(!hp)
return CURLPX_RESOLVE_HOST;
}
- /* FALLTHROUGH */
-CONNECT_REQ_INIT:
+ FALLTHROUGH();
case CONNECT_REQ_INIT:
+CONNECT_REQ_INIT:
/*
* This is currently not supporting "Identification Protocol (RFC1413)".
*/
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
if(sx->proxy_user) {
size_t plen = strlen(sx->proxy_user);
- if(plen >= (size_t)data->set.buffer_size - 8) {
- failf(data, "Too long SOCKS proxy user name, can't use");
+ if(plen > 255) {
+ /* there is no real size limit to this field in the protocol, but
+ SOCKS5 limits the proxy user field to 255 bytes and it seems likely
+ that a longer field is either a mistake or malicious input */
+ failf(data, "Too long SOCKS proxy user name");
return CURLPX_LONG_USER;
}
/* copy the proxy name WITH trailing zero */
@@ -426,7 +436,8 @@ CONNECT_REQ_INIT:
socksreq[7] = 1;
/* append hostname */
hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */
- if(hostnamelen <= 255)
+ if((hostnamelen <= 255) &&
+ (packetsize + hostnamelen < sizeof(sx->buffer)))
strcpy((char *)socksreq + packetsize, sx->hostname);
else {
failf(data, "SOCKS4: too long host name");
@@ -435,10 +446,11 @@ CONNECT_REQ_INIT:
packetsize += hostnamelen;
}
sx->outp = socksreq;
+ DEBUGASSERT(packetsize <= sizeof(sx->buffer));
sx->outstanding = packetsize;
sxstate(sx, data, CONNECT_REQ_SENDING);
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_REQ_SENDING:
/* Send request */
presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
@@ -454,7 +466,7 @@ CONNECT_REQ_INIT:
sx->outp = socksreq;
sxstate(sx, data, CONNECT_SOCKS_READ);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_SOCKS_READ:
/* Receive response */
presult = socks_state_recv(cf, sx, data, CURLPX_RECV_CONNECT,
@@ -566,14 +578,14 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
o X'00' succeeded
*/
struct connectdata *conn = cf->conn;
- unsigned char *socksreq = (unsigned char *)data->state.buffer;
- int idx;
+ unsigned char *socksreq = sx->buffer;
+ size_t idx;
CURLcode result;
CURLproxycode presult;
bool socks5_resolve_local =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
const size_t hostname_len = strlen(sx->hostname);
- ssize_t len = 0;
+ size_t len = 0;
const unsigned char auth = data->set.socks5auth;
bool allow_gssapi = FALSE;
struct Curl_dns_entry *dns = NULL;
@@ -616,6 +628,7 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
socksreq[1] = (unsigned char) (idx - 2);
sx->outp = socksreq;
+ DEBUGASSERT(idx <= sizeof(sx->buffer));
sx->outstanding = idx;
presult = socks_state_send(cf, sx, data, CURLPX_SEND_CONNECT,
"initial SOCKS5 request");
@@ -636,12 +649,12 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
/* remain in sending state */
return CURLPX_OK;
}
- /* FALLTHROUGH */
-CONNECT_SOCKS_READ_INIT:
+ FALLTHROUGH();
case CONNECT_SOCKS_READ_INIT:
+CONNECT_SOCKS_READ_INIT:
sx->outstanding = 2; /* expect two bytes */
sx->outp = socksreq; /* store it here */
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_SOCKS_READ:
presult = socks_state_recv(cf, sx, data, CURLPX_RECV_CONNECT,
"initial SOCKS5 response");
@@ -742,10 +755,11 @@ CONNECT_AUTH_INIT:
}
len += proxy_password_len;
sxstate(sx, data, CONNECT_AUTH_SEND);
+ DEBUGASSERT(len <= sizeof(sx->buffer));
sx->outstanding = len;
sx->outp = socksreq;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_AUTH_SEND:
presult = socks_state_send(cf, sx, data, CURLPX_SEND_AUTH,
"SOCKS5 sub-negotiation request");
@@ -758,7 +772,7 @@ CONNECT_AUTH_INIT:
sx->outp = socksreq;
sx->outstanding = 2;
sxstate(sx, data, CONNECT_AUTH_READ);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_AUTH_READ:
presult = socks_state_recv(cf, sx, data, CURLPX_RECV_AUTH,
"SOCKS5 sub-negotiation response");
@@ -777,9 +791,9 @@ CONNECT_AUTH_INIT:
/* Everything is good so far, user was authenticated! */
sxstate(sx, data, CONNECT_REQ_INIT);
- /* FALLTHROUGH */
-CONNECT_REQ_INIT:
+ FALLTHROUGH();
case CONNECT_REQ_INIT:
+CONNECT_REQ_INIT:
if(socks5_resolve_local) {
enum resolve_t rc = Curl_resolv(data, sx->hostname, sx->remote_port,
TRUE, &dns);
@@ -816,13 +830,23 @@ CONNECT_REQ_INIT:
return CURLPX_OK;
}
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
+ case CONNECT_RESOLVED:
CONNECT_RESOLVED:
- case CONNECT_RESOLVED: {
- char dest[MAX_IPADR_LEN] = "unknown"; /* printable address */
+ {
+ char dest[MAX_IPADR_LEN]; /* printable address */
struct Curl_addrinfo *hp = NULL;
if(dns)
hp = dns->addr;
+#ifdef ENABLE_IPV6
+ if(data->set.ipver != CURL_IPRESOLVE_WHATEVER) {
+ int wanted_family = data->set.ipver == CURL_IPRESOLVE_V4 ?
+ AF_INET : AF_INET6;
+ /* scan for the first proper address */
+ while(hp && (hp->ai_family != wanted_family))
+ hp = hp->ai_next;
+ }
+#endif
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
sx->hostname);
@@ -910,10 +934,10 @@ CONNECT_RESOLVE_REMOTE:
infof(data, "SOCKS5 connect to %s:%d (remotely resolved)",
sx->hostname, sx->remote_port);
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
-CONNECT_REQ_SEND:
case CONNECT_REQ_SEND:
+CONNECT_REQ_SEND:
/* PORT MSB */
socksreq[len++] = (unsigned char)((sx->remote_port >> 8) & 0xff);
/* PORT LSB */
@@ -926,9 +950,10 @@ CONNECT_REQ_SEND:
}
#endif
sx->outp = socksreq;
+ DEBUGASSERT(len <= sizeof(sx->buffer));
sx->outstanding = len;
sxstate(sx, data, CONNECT_REQ_SENDING);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_REQ_SENDING:
presult = socks_state_send(cf, sx, data, CURLPX_SEND_REQUEST,
"SOCKS5 connect request");
@@ -947,7 +972,7 @@ CONNECT_REQ_SEND:
sx->outstanding = 10; /* minimum packet size is 10 */
sx->outp = socksreq;
sxstate(sx, data, CONNECT_REQ_READ);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_REQ_READ:
presult = socks_state_recv(cf, sx, data, CURLPX_RECV_REQACK,
"SOCKS5 connect request ack");
@@ -1025,6 +1050,7 @@ CONNECT_REQ_SEND:
/* decrypt_gssapi_blockread already read the whole packet */
#endif
if(len > 10) {
+ DEBUGASSERT(len <= sizeof(sx->buffer));
sx->outstanding = len - 10; /* get the rest */
sx->outp = &socksreq[10];
sxstate(sx, data, CONNECT_REQ_READ_MORE);
@@ -1036,7 +1062,7 @@ CONNECT_REQ_SEND:
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
}
#endif
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CONNECT_REQ_READ_MORE:
presult = socks_state_recv(cf, sx, data, CURLPX_RECV_ADDRESS,
"SOCKS5 connect request address");
@@ -1119,7 +1145,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
return result;
if(!sx) {
- sx = calloc(sizeof(*sx), 1);
+ sx = calloc(1, sizeof(*sx));
if(!sx)
return CURLE_OUT_OF_MEMORY;
cf->ctx = sx;
@@ -1157,32 +1183,29 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
return result;
}
-static int socks_cf_get_select_socks(struct Curl_cfilter *cf,
+static void socks_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct socks_state *sx = cf->ctx;
- int fds;
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- if(!fds && cf->next->connected && !cf->connected && sx) {
+ if(!cf->connected && sx) {
/* If we are not connected, the filter below is and has nothing
* to wait on, we determine what to wait for. */
- socks[0] = Curl_conn_cf_get_socket(cf, data);
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf, data);
switch(sx->state) {
case CONNECT_RESOLVING:
case CONNECT_SOCKS_READ:
case CONNECT_AUTH_READ:
case CONNECT_REQ_READ:
case CONNECT_REQ_READ_MORE:
- fds = GETSOCK_READSOCK(0);
+ Curl_pollset_set_in_only(data, ps, sock);
break;
default:
- fds = GETSOCK_WRITESOCK(0);
+ Curl_pollset_set_out_only(data, ps, sock);
break;
}
}
- return fds;
}
static void socks_proxy_cf_close(struct Curl_cfilter *cf,
@@ -1227,7 +1250,7 @@ struct Curl_cftype Curl_cft_socks_proxy = {
socks_proxy_cf_connect,
socks_proxy_cf_close,
socks_cf_get_host,
- socks_cf_get_select_socks,
+ socks_cf_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 2ede8c7c2..243715055 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -35,6 +35,7 @@
#include "timeval.h"
#include "socks.h"
#include "warnless.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -139,10 +140,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
/* prepare service name */
if(strchr(serviceptr, '/')) {
service.length = serviceptr_length;
- service.value = malloc(service.length);
+ service.value = Curl_memdup(serviceptr, service.length);
if(!service.value)
return CURLE_OUT_OF_MEMORY;
- memcpy(service.value, serviceptr, service.length);
gss_major_status = gss_import_name(&gss_minor_status, &service,
(gss_OID) GSS_C_NULL_OID, &server);
@@ -387,12 +387,11 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
}
else {
gss_send_token.length = 1;
- gss_send_token.value = malloc(1);
+ gss_send_token.value = Curl_memdup(&gss_enc, 1);
if(!gss_send_token.value) {
gss_delete_sec_context(&gss_status, &gss_context, NULL);
return CURLE_OUT_OF_MEMORY;
}
- memcpy(gss_send_token.value, &gss_enc, 1);
gss_major_status = gss_wrap(&gss_minor_status, gss_context, 0,
GSS_C_QOP_DEFAULT, &gss_send_token,
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index d1200ea03..2baae2c2b 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -331,9 +331,15 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf,
failf(data, "Failed to determine user name.");
return CURLE_COULDNT_CONNECT;
}
- infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
- names.sUserName);
- s_pSecFn->FreeContextBuffer(names.sUserName);
+ else {
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ char *user_utf8 = curlx_convert_tchar_to_UTF8(names.sUserName);
+ infof(data, "SOCKS5 server authenticated user %s with GSS-API.",
+ (user_utf8 ? user_utf8 : "(unknown)"));
+ curlx_unicodefree(user_utf8);
+#endif
+ s_pSecFn->FreeContextBuffer(names.sUserName);
+ }
/* Do encryption */
socksreq[0] = 1; /* GSS-API subnegotiation version */
diff --git a/lib/strdup.c b/lib/strdup.c
index 07a61391a..299c9cc36 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -26,7 +26,7 @@
#include <curl/curl.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <wchar.h>
#endif
@@ -56,7 +56,7 @@ char *Curl_strdup(const char *str)
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
/***************************************************************************
*
* Curl_wcsdup(source)
@@ -101,6 +101,26 @@ void *Curl_memdup(const void *src, size_t length)
/***************************************************************************
*
+ * Curl_memdup0(source, length)
+ *
+ * Copies the 'source' string to a newly allocated buffer (that is returned).
+ * Copies 'length' bytes then adds a null terminator.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *Curl_memdup0(const char *src, size_t length)
+{
+ char *buf = malloc(length + 1);
+ if(!buf)
+ return NULL;
+ memcpy(buf, src, length);
+ buf[length] = 0;
+ return buf;
+}
+
+/***************************************************************************
+ *
* Curl_saferealloc(ptr, size)
*
* Does a normal realloc(), but will free the data pointer if the realloc
diff --git a/lib/strdup.h b/lib/strdup.h
index c3430b54d..238a2611f 100644
--- a/lib/strdup.h
+++ b/lib/strdup.h
@@ -28,10 +28,11 @@
#ifndef HAVE_STRDUP
char *Curl_strdup(const char *str);
#endif
-#ifdef WIN32
+#ifdef _WIN32
wchar_t* Curl_wcsdup(const wchar_t* src);
#endif
void *Curl_memdup(const void *src, size_t buffer_length);
void *Curl_saferealloc(void *ptr, size_t size);
+void *Curl_memdup0(const char *src, size_t length);
#endif /* HEADER_CURL_STRDUP_H */
diff --git a/lib/strerror.c b/lib/strerror.c
index be4191414..a900e78d1 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -48,7 +48,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
#define PRESERVE_WINDOWS_ERROR_CODE
#endif
@@ -319,6 +319,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_UNRECOVERABLE_POLL:
return "Unrecoverable error in select/poll";
+ case CURLE_TOO_LARGE:
+ return "A value or data field grew larger than allowed";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
@@ -553,6 +556,9 @@ curl_url_strerror(CURLUcode error)
case CURLUE_LACKS_IDN:
return "libcurl lacks IDN support";
+ case CURLUE_TOO_LARGE:
+ return "A value or data field is larger than allowed";
+
case CURLUE_LAST:
break;
}
@@ -572,10 +578,11 @@ curl_url_strerror(CURLUcode error)
* Returns NULL if no error message was found for error code.
*/
static const char *
-get_winsock_error (int err, char *buf, size_t len)
+get_winsock_error(int err, char *buf, size_t len)
{
#ifndef CURL_DISABLE_VERBOSE_STRINGS
const char *p;
+ size_t alen;
#endif
if(!len)
@@ -755,14 +762,15 @@ get_winsock_error (int err, char *buf, size_t len)
default:
return NULL;
}
- strncpy(buf, p, len);
- buf [len-1] = '\0';
+ alen = strlen(p);
+ if(alen < len)
+ strcpy(buf, p);
return buf;
#endif
}
#endif /* USE_WINSOCK */
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
/* This is a helper function for Curl_strerror that converts Windows API error
* codes (GetLastError) to error messages.
* Returns NULL if no error message was found for error code.
@@ -804,7 +812,7 @@ get_winapi_error(int err, char *buf, size_t buflen)
return (*buf ? buf : NULL);
}
-#endif /* WIN32 || _WIN32_WCE */
+#endif /* _WIN32 || _WIN32_WCE */
/*
* Our thread-safe and smart strerror() replacement.
@@ -832,32 +840,30 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
#endif
int old_errno = errno;
char *p;
- size_t max;
if(!buflen)
return NULL;
-#ifndef WIN32
+#ifndef _WIN32
DEBUGASSERT(err >= 0);
#endif
- max = buflen - 1;
*buf = '\0';
-#if defined(WIN32) || defined(_WIN32_WCE)
-#if defined(WIN32)
+#if defined(_WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32)
/* 'sys_nerr' is the maximum errno number, it is not widely portable */
if(err >= 0 && err < sys_nerr)
- strncpy(buf, sys_errlist[err], max);
+ msnprintf(buf, buflen, "%s", sys_errlist[err]);
else
#endif
{
if(
#ifdef USE_WINSOCK
- !get_winsock_error(err, buf, max) &&
+ !get_winsock_error(err, buf, buflen) &&
#endif
- !get_winapi_error((DWORD)err, buf, max))
- msnprintf(buf, max, "Unknown error %d (%#x)", err, err);
+ !get_winapi_error((DWORD)err, buf, buflen))
+ msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err);
}
#else /* not Windows coming up */
@@ -867,9 +873,9 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
* storage is supplied via 'strerrbuf' and 'buflen' to hold the generated
* message string, or EINVAL if 'errnum' is not a valid error number.
*/
- if(0 != strerror_r(err, buf, max)) {
+ if(0 != strerror_r(err, buf, buflen)) {
if('\0' == buf[0])
- msnprintf(buf, max, "Unknown error %d", err);
+ msnprintf(buf, buflen, "Unknown error %d", err);
}
#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)
/*
@@ -881,25 +887,23 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
char buffer[256];
char *msg = strerror_r(err, buffer, sizeof(buffer));
if(msg)
- strncpy(buf, msg, max);
+ msnprintf(buf, buflen, "%s", msg);
else
- msnprintf(buf, max, "Unknown error %d", err);
+ msnprintf(buf, buflen, "Unknown error %d", err);
}
#else
{
/* !checksrc! disable STRERROR 1 */
const char *msg = strerror(err);
if(msg)
- strncpy(buf, msg, max);
+ msnprintf(buf, buflen, "%s", msg);
else
- msnprintf(buf, max, "Unknown error %d", err);
+ msnprintf(buf, buflen, "Unknown error %d", err);
}
#endif
#endif /* end of not Windows */
- buf[max] = '\0'; /* make sure the string is null-terminated */
-
/* strip trailing '\r\n' or '\n'. */
p = strrchr(buf, '\n');
if(p && (p - buf) >= 2)
@@ -923,7 +927,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
* Curl_winapi_strerror:
* Variant of Curl_strerror if the error code is definitely Windows API.
*/
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
{
#ifdef PRESERVE_WINDOWS_ERROR_CODE
@@ -943,8 +947,8 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
#else
{
const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error";
- strncpy(buf, txt, buflen);
- buf[buflen - 1] = '\0';
+ if(strlen(txt) < buflen)
+ strcpy(buf, txt);
}
#endif
@@ -958,7 +962,7 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
return buf;
}
-#endif /* WIN32 || _WIN32_WCE */
+#endif /* _WIN32 || _WIN32_WCE */
#ifdef USE_WINDOWS_SSPI
/*
@@ -986,6 +990,10 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
break;
#define SEC2TXT(sec) case sec: txt = #sec; break
SEC2TXT(CRYPT_E_REVOKED);
+ SEC2TXT(CRYPT_E_NO_REVOCATION_DLL);
+ SEC2TXT(CRYPT_E_NO_REVOCATION_CHECK);
+ SEC2TXT(CRYPT_E_REVOCATION_OFFLINE);
+ SEC2TXT(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
SEC2TXT(SEC_E_ALGORITHM_MISMATCH);
SEC2TXT(SEC_E_BAD_BINDINGS);
SEC2TXT(SEC_E_BAD_PKGID);
@@ -1077,17 +1085,11 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
err);
}
else {
- char txtbuf[80];
char msgbuf[256];
-
- msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err);
-
if(get_winapi_error(err, msgbuf, sizeof(msgbuf)))
- msnprintf(buf, buflen, "%s - %s", txtbuf, msgbuf);
- else {
- strncpy(buf, txtbuf, buflen);
- buf[buflen - 1] = '\0';
- }
+ msnprintf(buf, buflen, "%s (0x%08X) - %s", txt, err, msgbuf);
+ else
+ msnprintf(buf, buflen, "%s (0x%08X)", txt, err);
}
#else
@@ -1095,8 +1097,8 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen)
txt = "No error";
else
txt = "Error";
- strncpy(buf, txt, buflen);
- buf[buflen - 1] = '\0';
+ if(buflen > strlen(txt))
+ strcpy(buf, txt);
#endif
if(errno != old_errno)
diff --git a/lib/strerror.h b/lib/strerror.h
index 399712f8e..680686734 100644
--- a/lib/strerror.h
+++ b/lib/strerror.h
@@ -29,7 +29,7 @@
#define STRERROR_LEN 256 /* a suitable length */
const char *Curl_strerror(int err, char *buf, size_t buflen);
-#if defined(WIN32) || defined(_WIN32_WCE)
+#if defined(_WIN32) || defined(_WIN32_WCE)
const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen);
#endif
#ifdef USE_WINDOWS_SSPI
diff --git a/lib/system_win32.c b/lib/system_win32.c
index 0cdaf3b2f..d2862de92 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
#include <curl/curl.h>
#include "system_win32.h"
@@ -38,16 +38,23 @@
LARGE_INTEGER Curl_freq;
bool Curl_isVistaOrGreater;
+bool Curl_isWindows8OrGreater;
/* Handle of iphlpapp.dll */
static HMODULE s_hIpHlpApiDll = NULL;
-/* Pointer to the if_nametoindex function */
+/* Function pointers */
IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL;
+FREEADDRINFOEXW_FN Curl_FreeAddrInfoExW = NULL;
+GETADDRINFOEXCANCEL_FN Curl_GetAddrInfoExCancel = NULL;
+GETADDRINFOEXW_FN Curl_GetAddrInfoExW = NULL;
/* Curl_win32_init() performs win32 global initialization */
CURLcode Curl_win32_init(long flags)
{
+#ifdef USE_WINSOCK
+ HMODULE ws2_32Dll;
+#endif
/* CURL_GLOBAL_WIN32 controls the *optional* part of the initialization which
is just for Winsock at the moment. Any required win32 initialization
should take place after this block. */
@@ -104,6 +111,18 @@ CURLcode Curl_win32_init(long flags)
Curl_if_nametoindex = pIfNameToIndex;
}
+#ifdef USE_WINSOCK
+ ws2_32Dll = GetModuleHandleA("ws2_32");
+ if(ws2_32Dll) {
+ Curl_FreeAddrInfoExW = CURLX_FUNCTION_CAST(FREEADDRINFOEXW_FN,
+ GetProcAddress(ws2_32Dll, "FreeAddrInfoExW"));
+ Curl_GetAddrInfoExCancel = CURLX_FUNCTION_CAST(GETADDRINFOEXCANCEL_FN,
+ GetProcAddress(ws2_32Dll, "GetAddrInfoExCancel"));
+ Curl_GetAddrInfoExW = CURLX_FUNCTION_CAST(GETADDRINFOEXW_FN,
+ GetProcAddress(ws2_32Dll, "GetAddrInfoExW"));
+ }
+#endif
+
/* curlx_verify_windows_version must be called during init at least once
because it has its own initialization routine. */
if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
@@ -113,6 +132,13 @@ CURLcode Curl_win32_init(long flags)
else
Curl_isVistaOrGreater = FALSE;
+ if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ Curl_isWindows8OrGreater = TRUE;
+ }
+ else
+ Curl_isWindows8OrGreater = FALSE;
+
QueryPerformanceFrequency(&Curl_freq);
return CURLE_OK;
}
@@ -120,6 +146,9 @@ CURLcode Curl_win32_init(long flags)
/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */
void Curl_win32_cleanup(long init_flags)
{
+ Curl_FreeAddrInfoExW = NULL;
+ Curl_GetAddrInfoExCancel = NULL;
+ Curl_GetAddrInfoExW = NULL;
if(s_hIpHlpApiDll) {
FreeLibrary(s_hIpHlpApiDll);
s_hIpHlpApiDll = NULL;
@@ -238,4 +267,4 @@ HMODULE Curl_load_library(LPCTSTR filename)
#endif
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
diff --git a/lib/system_win32.h b/lib/system_win32.h
index 6482643fa..bd490cabc 100644
--- a/lib/system_win32.h
+++ b/lib/system_win32.h
@@ -26,10 +26,11 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#ifdef _WIN32
extern LARGE_INTEGER Curl_freq;
extern bool Curl_isVistaOrGreater;
+extern bool Curl_isWindows8OrGreater;
CURLcode Curl_win32_init(long flags);
void Curl_win32_cleanup(long init_flags);
@@ -40,10 +41,37 @@ typedef unsigned int(WINAPI *IF_NAMETOINDEX_FN)(const char *);
/* This is used instead of if_nametoindex if available on Windows */
extern IF_NAMETOINDEX_FN Curl_if_nametoindex;
+/* Identical copy of addrinfoexW/ADDRINFOEXW */
+typedef struct addrinfoexW_
+{
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ PWSTR ai_canonname;
+ struct sockaddr *ai_addr;
+ void *ai_blob;
+ size_t ai_bloblen;
+ LPGUID ai_provider;
+ struct addrinfoexW_ *ai_next;
+} ADDRINFOEXW_;
+
+typedef void (CALLBACK *LOOKUP_COMPLETION_FN)(DWORD, DWORD, LPWSAOVERLAPPED);
+typedef void (WSAAPI *FREEADDRINFOEXW_FN)(ADDRINFOEXW_*);
+typedef int (WSAAPI *GETADDRINFOEXCANCEL_FN)(LPHANDLE);
+typedef int (WSAAPI *GETADDRINFOEXW_FN)(PCWSTR, PCWSTR, DWORD, LPGUID,
+ const ADDRINFOEXW_*, ADDRINFOEXW_**, struct timeval*, LPOVERLAPPED,
+ LOOKUP_COMPLETION_FN, LPHANDLE);
+
+extern FREEADDRINFOEXW_FN Curl_FreeAddrInfoExW;
+extern GETADDRINFOEXCANCEL_FN Curl_GetAddrInfoExCancel;
+extern GETADDRINFOEXW_FN Curl_GetAddrInfoExW;
+
/* This is used to dynamically load DLLs */
HMODULE Curl_load_library(LPCTSTR filename);
-#else /* WIN32 */
+#else /* _WIN32 */
#define Curl_win32_init(x) CURLE_OK
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
#endif /* HEADER_CURL_SYSTEM_WIN32_H */
diff --git a/lib/telnet.c b/lib/telnet.c
index 836e255c9..34dc5e806 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -160,6 +160,7 @@ struct TELNET {
unsigned short subopt_wsy; /* Set with suboption NAWS */
TelnetReceive telrcv_state;
struct curl_slist *telnet_vars; /* Environment variables */
+ struct dynbuf out; /* output buffer */
/* suboptions */
unsigned char subbuffer[SUBBUFSIZE];
@@ -185,7 +186,7 @@ const struct Curl_handler Curl_handler_telnet = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_TELNET, /* defport */
@@ -204,6 +205,7 @@ CURLcode init_telnet(struct Curl_easy *data)
if(!tn)
return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&tn->out, 0xffff);
data->req.p.telnet = tn; /* make us known */
tn->telrcv_state = CURL_TS_DATA;
@@ -799,8 +801,10 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
was given on the command line */
if(data->state.aptr.user) {
char buffer[256];
- if(str_is_nonascii(data->conn->user))
+ if(str_is_nonascii(data->conn->user)) {
+ DEBUGF(infof(data, "set a non ASCII user name in telnet"));
return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
msnprintf(buffer, sizeof(buffer), "USER,%s", data->conn->user);
beg = curl_slist_append(tn->telnet_vars, buffer);
if(!beg) {
@@ -826,23 +830,27 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
case 5:
/* Terminal type */
if(strncasecompare(option, "TTYPE", 5)) {
- strncpy(tn->subopt_ttype, arg, 31);
- tn->subopt_ttype[31] = 0; /* String termination */
- tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
+ size_t l = strlen(arg);
+ if(l < sizeof(tn->subopt_ttype)) {
+ strcpy(tn->subopt_ttype, arg);
+ tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
+ break;
+ }
}
- else
- result = CURLE_UNKNOWN_OPTION;
+ result = CURLE_UNKNOWN_OPTION;
break;
case 8:
/* Display variable */
if(strncasecompare(option, "XDISPLOC", 8)) {
- strncpy(tn->subopt_xdisploc, arg, 127);
- tn->subopt_xdisploc[127] = 0; /* String termination */
- tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
+ size_t l = strlen(arg);
+ if(l < sizeof(tn->subopt_xdisploc)) {
+ strcpy(tn->subopt_xdisploc, arg);
+ tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
+ break;
+ }
}
- else
- result = CURLE_UNKNOWN_OPTION;
+ result = CURLE_UNKNOWN_OPTION;
break;
case 7:
@@ -1223,37 +1231,33 @@ process_iac:
static CURLcode send_telnet_data(struct Curl_easy *data,
char *buffer, ssize_t nread)
{
- ssize_t escapes, i, outlen;
- unsigned char *outbuf = NULL;
+ ssize_t i, outlen;
+ unsigned char *outbuf;
CURLcode result = CURLE_OK;
- ssize_t bytes_written, total_written;
+ ssize_t bytes_written, total_written = 0;
struct connectdata *conn = data->conn;
+ struct TELNET *tn = data->req.p.telnet;
- /* Determine size of new buffer after escaping */
- escapes = 0;
- for(i = 0; i < nread; i++)
- if((unsigned char)buffer[i] == CURL_IAC)
- escapes++;
- outlen = nread + escapes;
+ DEBUGASSERT(tn);
- if(outlen == nread)
- outbuf = (unsigned char *)buffer;
- else {
- ssize_t j;
- outbuf = malloc(nread + escapes + 1);
- if(!outbuf)
- return CURLE_OUT_OF_MEMORY;
+ if(memchr(buffer, CURL_IAC, nread)) {
+ /* only use the escape buffer when necessary */
+ Curl_dyn_reset(&tn->out);
- j = 0;
- for(i = 0; i < nread; i++) {
- outbuf[j++] = (unsigned char)buffer[i];
- if((unsigned char)buffer[i] == CURL_IAC)
- outbuf[j++] = CURL_IAC;
+ for(i = 0; i < nread && !result; i++) {
+ result = Curl_dyn_addn(&tn->out, &buffer[i], 1);
+ if(!result && ((unsigned char)buffer[i] == CURL_IAC))
+ /* IAC is FF in hex */
+ result = Curl_dyn_addn(&tn->out, "\xff", 1);
}
- outbuf[j] = '\0';
- }
- total_written = 0;
+ outlen = Curl_dyn_len(&tn->out);
+ outbuf = Curl_dyn_uptr(&tn->out);
+ }
+ else {
+ outlen = nread;
+ outbuf = (unsigned char *)buffer;
+ }
while(!result && total_written < outlen) {
/* Make sure socket is writable to avoid EWOULDBLOCK condition */
struct pollfd pfd[1];
@@ -1266,19 +1270,13 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
break;
default: /* write! */
bytes_written = 0;
- result = Curl_nwrite(data, FIRSTSOCKET,
- outbuf + total_written,
- outlen - total_written,
- &bytes_written);
+ result = Curl_nwrite(data, FIRSTSOCKET, outbuf + total_written,
+ outlen - total_written, &bytes_written);
total_written += bytes_written;
break;
}
}
- /* Free malloc copy if escaped */
- if(outbuf != (unsigned char *)buffer)
- free(outbuf);
-
return result;
}
@@ -1294,6 +1292,7 @@ static CURLcode telnet_done(struct Curl_easy *data,
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
+ Curl_dyn_free(&tn->out);
return CURLE_OK;
}
@@ -1321,7 +1320,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
ssize_t nread;
struct curltime now;
bool keepon = TRUE;
- char *buf = data->state.buffer;
+ char buffer[4*1024];
struct TELNET *tn;
*done = TRUE; /* unconditionally */
@@ -1378,7 +1377,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
/* Keep on listening and act on events */
while(keepon) {
- const DWORD buf_size = (DWORD)data->set.buffer_size;
+ const DWORD buf_size = (DWORD)sizeof(buffer);
DWORD waitret = WaitForMultipleObjects(obj_count, objs,
FALSE, wait_timeout);
switch(waitret) {
@@ -1389,7 +1388,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
if(data->set.is_fread_set) {
size_t n;
/* read from user-supplied method */
- n = data->state.fread_func(buf, 1, buf_size, data->state.in);
+ n = data->state.fread_func(buffer, 1, buf_size, data->state.in);
if(n == CURL_READFUNC_ABORT) {
keepon = FALSE;
result = CURLE_READ_ERROR;
@@ -1417,7 +1416,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
if(!readfile_read)
break;
- if(!ReadFile(stdin_handle, buf, buf_size,
+ if(!ReadFile(stdin_handle, buffer, buf_size,
&readfile_read, NULL)) {
keepon = FALSE;
result = CURLE_READ_ERROR;
@@ -1425,7 +1424,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
}
- result = send_telnet_data(data, buf, readfile_read);
+ result = send_telnet_data(data, buffer, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1436,14 +1435,14 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
case WAIT_OBJECT_0 + 1:
{
- if(!ReadFile(stdin_handle, buf, buf_size,
+ if(!ReadFile(stdin_handle, buffer, buf_size,
&readfile_read, NULL)) {
keepon = FALSE;
result = CURLE_READ_ERROR;
break;
}
- result = send_telnet_data(data, buf, readfile_read);
+ result = send_telnet_data(data, buffer, readfile_read);
if(result) {
keepon = FALSE;
break;
@@ -1465,7 +1464,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
if(events.lNetworkEvents & FD_READ) {
/* read data from network */
- result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
+ result = Curl_read(data, sockfd, buffer, sizeof(buffer), &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1481,7 +1480,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
break;
}
- result = telrcv(data, (unsigned char *) buf, nread);
+ result = telrcv(data, (unsigned char *) buffer, nread);
if(result) {
keepon = FALSE;
break;
@@ -1542,11 +1541,11 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
case 0: /* timeout */
pfd[0].revents = 0;
pfd[1].revents = 0;
- /* FALLTHROUGH */
+ FALLTHROUGH();
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
- result = Curl_read(data, sockfd, buf, data->set.buffer_size, &nread);
+ result = Curl_read(data, sockfd, buffer, sizeof(buffer), &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1572,7 +1571,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
total_dl += nread;
result = Curl_pgrsSetDownloadCounter(data, total_dl);
if(!result)
- result = telrcv(data, (unsigned char *)buf, nread);
+ result = telrcv(data, (unsigned char *)buffer, nread);
if(result) {
keepon = FALSE;
break;
@@ -1590,12 +1589,12 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
nread = 0;
if(poll_cnt == 2) {
if(pfd[1].revents & POLLIN) { /* read from in file */
- nread = read(pfd[1].fd, buf, data->set.buffer_size);
+ nread = read(pfd[1].fd, buffer, sizeof(buffer));
}
}
else {
/* read from user-supplied method */
- nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size,
+ nread = (int)data->state.fread_func(buffer, 1, sizeof(buffer),
data->state.in);
if(nread == CURL_READFUNC_ABORT) {
keepon = FALSE;
@@ -1606,7 +1605,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
if(nread > 0) {
- result = send_telnet_data(data, buf, nread);
+ result = send_telnet_data(data, buffer, nread);
if(result) {
keepon = FALSE;
break;
diff --git a/lib/tftp.c b/lib/tftp.c
index e78140d52..4288110da 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -70,8 +70,6 @@
/* RFC2348 allows the block size to be negotiated */
#define TFTP_BLKSIZE_DEFAULT 512
-#define TFTP_BLKSIZE_MIN 8
-#define TFTP_BLKSIZE_MAX 65464
#define TFTP_OPTION_BLKSIZE "blksize"
/* from RFC2349: */
@@ -183,7 +181,7 @@ const struct Curl_handler Curl_handler_tftp = {
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
tftp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_TFTP, /* defport */
@@ -978,11 +976,9 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
return CURLE_OUT_OF_MEMORY;
/* alloc pkt buffers based on specified blksize */
- if(data->set.tftp_blksize) {
+ if(data->set.tftp_blksize)
+ /* range checked when set */
blksize = (int)data->set.tftp_blksize;
- if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
- return CURLE_TFTP_ILLEGAL;
- }
need_blksize = blksize;
/* default size is the fallback when no OACK is received */
@@ -1107,7 +1103,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct tftp_state_data *state = conn->proto.tftpc;
- struct SingleRequest *k = &data->req;
/* Receive the packet */
fromlen = sizeof(fromaddr);
@@ -1141,11 +1136,6 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *)state->rpacket.data + 4,
state->rbytes-4);
- if(!result) {
- k->bytecount += state->rbytes-4;
- result = Curl_pgrsSetDownloadCounter(data,
- (curl_off_t) k->bytecount);
- }
if(result) {
tftp_state_machine(state, TFTP_EVENT_ERROR);
return result;
diff --git a/lib/tftp.h b/lib/tftp.h
index 5d2d5da61..12404bf6d 100644
--- a/lib/tftp.h
+++ b/lib/tftp.h
@@ -25,6 +25,9 @@
***************************************************************************/
#ifndef CURL_DISABLE_TFTP
extern const struct Curl_handler Curl_handler_tftp;
+
+#define TFTP_BLKSIZE_MIN 8
+#define TFTP_BLKSIZE_MAX 65464
#endif
#endif /* HEADER_CURL_TFTP_H */
diff --git a/lib/timediff.c b/lib/timediff.c
index 1b762bbd3..d0824d144 100644
--- a/lib/timediff.c
+++ b/lib/timediff.c
@@ -53,7 +53,7 @@ struct timeval *curlx_mstotv(struct timeval *tv, timediff_t ms)
#endif
tv->tv_sec = (time_t)tv_sec;
tv->tv_usec = (suseconds_t)tv_usec;
-#elif defined(WIN32) /* maybe also others in the future */
+#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)
diff --git a/lib/timeval.c b/lib/timeval.c
index 026d9d17c..5a6727cbc 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -24,11 +24,10 @@
#include "timeval.h"
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32)
-/* set in win32_init() */
-extern LARGE_INTEGER Curl_freq;
-extern bool Curl_isVistaOrGreater;
+#include <curl/curl.h>
+#include "system_win32.h"
/* In case of bug fix this function has a counterpart in tool_util.c */
struct curltime Curl_now(void)
diff --git a/lib/transfer.c b/lib/transfer.c
index 6886764f4..3ae4b61c0 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -163,9 +163,9 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
{
size_t buffersize = bytes;
size_t nread;
-
curl_read_callback readfunc = NULL;
void *extra_data = NULL;
+ int eof_index = 0;
#ifndef CURL_DISABLE_HTTP
if(data->state.trailers_state == TRAILERS_INITIALIZED) {
@@ -223,6 +223,7 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
*/
readfunc = trailers_read;
extra_data = (void *)data;
+ eof_index = 1;
}
else
#endif
@@ -231,10 +232,15 @@ CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
extra_data = data->state.in;
}
- Curl_set_in_callback(data, true);
- nread = readfunc(data->req.upload_fromhere, 1,
- buffersize, extra_data);
- Curl_set_in_callback(data, false);
+ if(!data->req.fread_eof[eof_index]) {
+ Curl_set_in_callback(data, true);
+ nread = readfunc(data->req.upload_fromhere, 1, buffersize, extra_data);
+ Curl_set_in_callback(data, false);
+ /* make sure the callback is not called again after EOF */
+ data->req.fread_eof[eof_index] = !nread;
+ }
+ else
+ nread = 0;
if(nread == CURL_READFUNC_ABORT) {
failf(data, "operation aborted by callback");
@@ -407,363 +413,154 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
return TRUE;
}
+/**
+ * Receive raw response data for the transfer.
+ * @param data the transfer
+ * @param buf buffer to keep response data received
+ * @param blen length of `buf`
+ * @param eos_reliable if EOS detection in underlying connection is reliable
+ * @param err error code in case of -1 return
+ * @return number of bytes read or -1 for error
+ */
+static ssize_t Curl_xfer_recv_resp(struct Curl_easy *data,
+ char *buf, size_t blen,
+ bool eos_reliable,
+ CURLcode *err)
+{
+ ssize_t nread;
+
+ DEBUGASSERT(blen > 0);
+ /* If we are reading BODY data and the connection does NOT handle EOF
+ * and we know the size of the BODY data, limit the read amount */
+ if(!eos_reliable && !data->req.header && data->req.size != -1) {
+ curl_off_t totalleft = data->req.size - data->req.bytecount;
+ if(totalleft <= 0)
+ blen = 0;
+ else if(totalleft < (curl_off_t)blen)
+ blen = (size_t)totalleft;
+ }
+
+ if(!blen) {
+ /* want nothing - continue as if read nothing. */
+ DEBUGF(infof(data, "readwrite_data: we're done"));
+ *err = CURLE_OK;
+ return 0;
+ }
+
+ *err = Curl_read(data, data->conn->sockfd, buf, blen, &nread);
+ if(*err)
+ return -1;
+ DEBUGASSERT(nread >= 0);
+ *err = CURLE_OK;
+ return nread;
+}
+
/*
* Go ahead and do a read if we have a readable socket or if
* the stream was rewound (in which case we have data in a
* buffer)
- *
- * return '*comeback' TRUE if we didn't properly drain the socket so this
- * function should get called again without select() or similar in between!
*/
static CURLcode readwrite_data(struct Curl_easy *data,
- struct connectdata *conn,
struct SingleRequest *k,
- int *didwhat, bool *done,
- bool *comeback)
+ int *didwhat, bool *done)
{
+ struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
- ssize_t nread; /* number of bytes read */
- size_t excess = 0; /* excess bytes read */
- bool readmore = FALSE; /* used by RTP to signal for more data */
- int maxloops = 100;
- curl_off_t max_recv = data->set.max_recv_speed?
- data->set.max_recv_speed : CURL_OFF_T_MAX;
- char *buf = data->state.buffer;
- bool data_eof_handled = FALSE;
- DEBUGASSERT(buf);
+ char *buf;
+ size_t blen;
+ int maxloops = 10;
+ curl_off_t total_received = 0;
+ bool is_multiplex = FALSE;
+ DEBUGASSERT(data->state.buffer);
*done = FALSE;
- *comeback = FALSE;
/* This is where we loop until we have read everything there is to
read or we get a CURLE_AGAIN */
do {
- bool is_empty_data = FALSE;
- size_t buffersize = data->set.buffer_size;
- size_t bytestoread = buffersize;
- /* For HTTP/2 and HTTP/3, read data without caring about the content
- length. This is safe because body in HTTP/2 is always segmented
- thanks to its framing layer. Meanwhile, we have to call Curl_read
- to ensure that http2_handle_stream_close is called when we read all
- incoming bytes for a particular stream. */
- bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET);
- data_eof_handled = is_http3 || Curl_conn_is_http2(data, conn, FIRSTSOCKET);
-
- if(!data_eof_handled && k->size != -1 && !k->header) {
- /* make sure we don't read too much */
- curl_off_t totalleft = k->size - k->bytecount;
- if(totalleft < (curl_off_t)bytestoread)
- bytestoread = (size_t)totalleft;
+ bool is_eos = FALSE;
+ size_t bytestoread;
+ ssize_t nread;
+
+ if(!is_multiplex) {
+ /* Multiplexed connection have inherent handling of EOF and we do not
+ * have to carefully restrict the amount we try to read.
+ * Multiplexed changes only in one direction. */
+ is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET);
}
- if(bytestoread) {
- /* receive data from the network! */
- result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
+ buf = data->state.buffer;
+ bytestoread = data->set.buffer_size;
+
+ /* Observe any imposed speed limit */
+ if(bytestoread && data->set.max_recv_speed) {
+ curl_off_t net_limit = data->set.max_recv_speed - total_received;
+ if(net_limit <= 0)
+ break;
+ if((size_t)net_limit < bytestoread)
+ bytestoread = (size_t)net_limit;
+ }
- /* read would've blocked */
+ nread = Curl_xfer_recv_resp(data, buf, bytestoread,
+ is_multiplex, &result);
+ if(nread < 0) {
if(CURLE_AGAIN == result) {
result = CURLE_OK;
break; /* get out of loop */
}
-
- if(result>0)
- goto out;
- }
- else {
- /* read nothing but since we wanted nothing we consider this an OK
- situation to proceed from */
- DEBUGF(infof(data, "readwrite_data: we're done"));
- nread = 0;
- }
-
- if(!k->bytecount) {
- Curl_pgrsTime(data, TIMER_STARTTRANSFER);
- if(k->exp100 > EXP100_SEND_DATA)
- /* set time stamp to compare with when waiting for the 100 */
- k->start100 = Curl_now();
+ goto out; /* real error */
}
+ /* We only get a 0-length read on EndOfStream */
+ blen = (size_t)nread;
+ is_eos = (blen == 0);
*didwhat |= KEEP_RECV;
- /* indicates data of zero size, i.e. empty file */
- is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
- if(0 < nread || is_empty_data) {
- buf[nread] = 0;
- }
- if(!nread) {
+ if(!blen) {
/* if we receive 0 or less here, either the data transfer is done or the
server closed the connection and we bail out from this! */
- if(data_eof_handled)
+ if(is_multiplex)
DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
else
DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
- k->keepon = 0; /* stop sending as well */
- if(!is_empty_data)
- break;
- }
-
- /* 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 = buf;
-
- if(conn->handler->readwrite) {
- result = conn->handler->readwrite(data, conn, &nread, &readmore);
- if(result)
- goto out;
- if(readmore)
- break;
- }
-
-#ifndef CURL_DISABLE_HTTP
- /* Since this is a two-state thing, we check if we are parsing
- headers at the moment or not. */
- if(k->header) {
- /* we are in parse-the-header-mode */
- bool stop_reading = FALSE;
- result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
- if(result)
- goto out;
-
- if(conn->handler->readwrite &&
- (k->maxdownload <= 0 && nread > 0)) {
- result = conn->handler->readwrite(data, conn, &nread, &readmore);
- if(result)
- goto out;
- if(readmore)
- break;
- }
-
- if(stop_reading) {
- /* We've stopped dealing with input, get out of the do-while loop */
-
- if(nread > 0) {
- infof(data,
- "Excess found:"
- " excess = %zd"
- " url = %s (zero-length body)",
- nread, data->state.up.path);
- }
-
+ if(k->eos_written) { /* already did write this to client, leave */
+ k->keepon = 0; /* stop sending as well */
break;
}
}
-#endif /* CURL_DISABLE_HTTP */
-
-
- /* 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->header && (nread > 0 || is_empty_data)) {
-
- if(data->req.no_body) {
- /* data arrives although we want none, bail out */
- streamclose(conn, "ignoring body");
- *done = TRUE;
- result = CURLE_WEIRD_SERVER_REPLY;
- goto out;
- }
-
-#ifndef CURL_DISABLE_HTTP
- if(0 == k->bodywrites && !is_empty_data) {
- /* These checks are only made the first time we are about to
- write a piece of the body */
- if(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP)) {
- /* HTTP-only checks */
- result = Curl_http_firstwrite(data, conn, done);
- if(result || *done)
- goto out;
- }
- } /* this is the first time we write a body part */
-#endif /* CURL_DISABLE_HTTP */
-
- k->bodywrites++;
-
- /* pass data to the debug function before it gets "dechunked" */
- if(data->set.verbose) {
- if(k->badheader) {
- 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);
- }
- else
- Curl_debug(data, CURLINFO_DATA_IN,
- k->str, (size_t)nread);
- }
-
-#ifndef CURL_DISABLE_HTTP
- if(k->chunk) {
- /*
- * Here comes a chunked transfer flying and we need to decode this
- * properly. While the name says read, this function both reads
- * and writes away the data. The returned 'nread' holds the number
- * of actual data it wrote to the client.
- */
- CURLcode extra;
- CHUNKcode res =
- Curl_httpchunk_read(data, k->str, nread, &nread, &extra);
-
- if(CHUNKE_OK < res) {
- if(CHUNKE_PASSTHRU_ERROR == res) {
- failf(data, "Failed reading the chunked-encoded stream");
- result = extra;
- goto out;
- }
- failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
- result = CURLE_RECV_ERROR;
- goto out;
- }
- if(CHUNKE_STOP == res) {
- /* we're done reading chunks! */
- k->keepon &= ~KEEP_RECV; /* read no more */
-
- /* N number of bytes at the end of the str buffer that weren't
- written to the client. */
- if(conn->chunk.datasize) {
- infof(data, "Leftovers after chunking: % "
- CURL_FORMAT_CURL_OFF_T "u bytes",
- conn->chunk.datasize);
- }
- }
- /* If it returned OK, we just keep going */
- }
-#endif /* CURL_DISABLE_HTTP */
-
- /* Account for body content stored in the header buffer */
- if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
- size_t headlen = Curl_dyn_len(&data->state.headerb);
- DEBUGF(infof(data, "Increasing bytecount by %zu", headlen));
- k->bytecount += headlen;
- }
-
- if((-1 != k->maxdownload) &&
- (k->bytecount + nread >= k->maxdownload)) {
-
- excess = (size_t)(k->bytecount + nread - k->maxdownload);
- if(excess > 0 && !k->ignorebody) {
- infof(data,
- "Excess found in a read:"
- " excess = %zu"
- ", size = %" CURL_FORMAT_CURL_OFF_T
- ", maxdownload = %" CURL_FORMAT_CURL_OFF_T
- ", bytecount = %" CURL_FORMAT_CURL_OFF_T,
- excess, k->size, k->maxdownload, k->bytecount);
- connclose(conn, "excess found in a read");
- }
-
- nread = (ssize_t) (k->maxdownload - k->bytecount);
- if(nread < 0) /* this should be unusual */
- nread = 0;
-
- /* HTTP/3 over QUIC should keep reading until QUIC connection
- is closed. In contrast to HTTP/2 which can stop reading
- from TCP connection, HTTP/3 over QUIC needs ACK from server
- to ensure stream closure. It should keep reading. */
- if(!is_http3) {
- k->keepon &= ~KEEP_RECV; /* we're done reading */
- }
- }
-
- k->bytecount += nread;
- max_recv -= nread;
-
- result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
- if(result)
- goto out;
-
- if(!k->chunk && (nread || k->badheader || is_empty_data)) {
- /* If this is chunky transfer, it was already written */
-
- 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)headlen <= k->maxdownload)
- result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&data->state.headerb),
- headlen);
- else
- result = Curl_client_write(data, CLIENTWRITE_BODY,
- Curl_dyn_ptr(&data->state.headerb),
- (size_t)k->maxdownload);
-
- if(result)
- goto out;
- }
- if(k->badheader < HEADER_ALLBAD) {
- /* This switch handles various content encodings. If there's an
- error here, be sure to check over the almost identical code
- in http_chunks.c.
- Make sure that ALL_CONTENT_ENCODINGS contains all the
- encodings handled here. */
- if(!k->ignorebody && nread) {
-#ifndef CURL_DISABLE_POP3
- if(conn->handler->protocol & PROTO_FAMILY_POP3)
- result = Curl_pop3_write(data, k->str, nread);
- else
-#endif /* CURL_DISABLE_POP3 */
- result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
- nread);
- }
- }
- k->badheader = HEADER_NORMAL; /* taken care of now */
-
- if(result)
- goto out;
- }
-
- } /* if(!header and data to read) */
-
- if(conn->handler->readwrite && excess) {
- /* Parse the excess data */
- k->str += nread;
+ total_received += blen;
- 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 = &buf[data->set.buffer_size] - k->str;
- }
- nread = (ssize_t)excess;
-
- result = conn->handler->readwrite(data, conn, &nread, &readmore);
- if(result)
- goto out;
-
- if(readmore)
- k->keepon |= KEEP_RECV; /* we're not done reading */
- break;
- }
+ result = Curl_xfer_write_resp(data, buf, blen, is_eos, done);
+ if(result || *done)
+ goto out;
- if(is_empty_data) {
- /* if we received nothing, the server closed the connection and we
- are done */
- k->keepon &= ~KEEP_RECV;
+ /* if we are done, we stop receiving. On multiplexed connections,
+ * we should read the EOS. Which may arrive as meta data after
+ * the bytes. Not taking it in might lead to RST of streams. */
+ if((!is_multiplex && data->req.download_done) || is_eos) {
+ data->req.keepon &= ~KEEP_RECV;
}
-
- if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV)) {
- /* this is a paused or stopped transfer */
+ /* if we are PAUSEd or stopped receiving, leave the loop */
+ if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV))
break;
- }
- } while((max_recv > 0) && data_pending(data) && maxloops--);
+ } while(maxloops-- && data_pending(data));
- if(maxloops <= 0 || max_recv <= 0) {
- /* we mark it as read-again-please */
- data->state.dselect_bits = CURL_CSELECT_IN;
- *comeback = TRUE;
+ if(maxloops <= 0) {
+ /* did not read until EAGAIN, mark read-again-please */
+ data->state.select_bits = CURL_CSELECT_IN;
+ if((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
+ data->state.select_bits |= CURL_CSELECT_OUT;
}
if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
- (conn->bits.close || data_eof_handled)) {
+ (conn->bits.close || is_multiplex)) {
/* When we've read the entire thing and the close bit is set, the server
may now close the connection. If there's now any kind of sending going
on from our side, we need to stop that immediately. */
infof(data, "we are done reading and this is set to close, stop send");
k->keepon &= ~KEEP_SEND; /* no writing anymore either */
+ k->keepon &= ~KEEP_SEND_PAUSE; /* no pausing anymore either */
}
out:
@@ -783,7 +580,7 @@ CURLcode Curl_done_sending(struct Curl_easy *data,
return CURLE_OK;
}
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
#endif
@@ -977,7 +774,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
if(result)
return result;
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
{
struct curltime n = Curl_now();
if(Curl_timediff(n, k->last_sndbuf_update) > 1000) {
@@ -1053,46 +850,41 @@ static int select_bits_paused(struct Curl_easy *data, int select_bits)
* of our state machine are handling PAUSED transfers correctly. So, we
* do not want to go there.
* NOTE: we are only interested in PAUSE, not HOLD. */
- return (((select_bits & CURL_CSELECT_IN) &&
- (data->req.keepon & KEEP_RECV_PAUSE)) ||
- ((select_bits & CURL_CSELECT_OUT) &&
- (data->req.keepon & KEEP_SEND_PAUSE)));
+
+ /* if there is data in a direction not paused, return false */
+ if(((select_bits & CURL_CSELECT_IN) &&
+ !(data->req.keepon & KEEP_RECV_PAUSE)) ||
+ ((select_bits & CURL_CSELECT_OUT) &&
+ !(data->req.keepon & KEEP_SEND_PAUSE)))
+ return FALSE;
+
+ return (data->req.keepon & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE));
}
/*
* Curl_readwrite() is the low-level function to be called when data is to
* be read and written to/from the connection.
- *
- * return '*comeback' TRUE if we didn't properly drain the socket so this
- * function should get called again without select() or similar in between!
*/
-CURLcode Curl_readwrite(struct connectdata *conn,
- struct Curl_easy *data,
- bool *done,
- bool *comeback)
+CURLcode Curl_readwrite(struct Curl_easy *data,
+ bool *done)
{
+ struct connectdata *conn = data->conn;
struct SingleRequest *k = &data->req;
CURLcode result;
struct curltime now;
int didwhat = 0;
int select_bits;
- if(data->state.dselect_bits) {
- if(select_bits_paused(data, data->state.dselect_bits)) {
+ if(data->state.select_bits) {
+ if(select_bits_paused(data, data->state.select_bits)) {
/* leave the bits unchanged, so they'll tell us what to do when
* this transfer gets unpaused. */
- DEBUGF(infof(data, "readwrite, dselect_bits, early return on PAUSED"));
+ DEBUGF(infof(data, "readwrite, select_bits, early return on PAUSED"));
result = CURLE_OK;
goto out;
}
- select_bits = data->state.dselect_bits;
- data->state.dselect_bits = 0;
- }
- else if(conn->cselect_bits) {
- /* CAVEAT: adding `select_bits_paused()` check here makes test640 hang
- * (among others). Which hints at strange state handling in FTP land... */
- select_bits = conn->cselect_bits;
- conn->cselect_bits = 0;
+ select_bits = data->state.select_bits;
+ data->state.select_bits = 0;
}
else {
curl_socket_t fd_read;
@@ -1130,7 +922,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
the stream was rewound (in which case we have data in a
buffer) */
if((k->keepon & KEEP_RECV) && (select_bits & CURL_CSELECT_IN)) {
- result = readwrite_data(data, conn, k, &didwhat, done, comeback);
+ result = readwrite_data(data, k, &didwhat, done);
if(result || *done)
goto out;
}
@@ -1226,21 +1018,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
result = CURLE_PARTIAL_FILE;
goto out;
}
- if(!(data->req.no_body) && k->chunk &&
- (conn->chunk.state != CHUNK_STOP)) {
- /*
- * In chunked mode, return an error if the connection is closed prior to
- * the empty (terminating) chunk is read.
- *
- * The condition above used to check for
- * conn->proto.http->chunk.datasize != 0 which is true after reading
- * *any* chunk, not just the empty chunk.
- *
- */
- failf(data, "transfer closed with outstanding read data remaining");
- result = CURLE_PARTIAL_FILE;
- goto out;
- }
if(Curl_pgrsUpdate(data)) {
result = CURLE_ABORTED_BY_CALLBACK;
goto out;
@@ -1255,52 +1032,6 @@ out:
return result;
}
-/*
- * Curl_single_getsock() gets called by the multi interface code when the app
- * has requested to get the sockets for the current connection. This function
- * will then be called once for every connection that the multi interface
- * keeps track of. This function will only be called for connections that are
- * in the proper state to have this information available.
- */
-int Curl_single_getsock(struct Curl_easy *data,
- struct connectdata *conn,
- curl_socket_t *sock)
-{
- int bitmap = GETSOCK_BLANK;
- unsigned sockindex = 0;
-
- if(conn->handler->perform_getsock)
- return conn->handler->perform_getsock(data, conn, sock);
-
- /* don't include HOLD and PAUSE connections */
- if((data->req.keepon & KEEP_RECVBITS) == KEEP_RECV) {
-
- DEBUGASSERT(conn->sockfd != CURL_SOCKET_BAD);
-
- bitmap |= GETSOCK_READSOCK(sockindex);
- sock[sockindex] = conn->sockfd;
- }
-
- /* don't include HOLD and PAUSE connections */
- if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
- if((conn->sockfd != conn->writesockfd) ||
- bitmap == GETSOCK_BLANK) {
- /* only if they are not the same socket and we have a readable
- one, we increase index */
- if(bitmap != GETSOCK_BLANK)
- sockindex++; /* increase index if we need two entries */
-
- DEBUGASSERT(conn->writesockfd != CURL_SOCKET_BAD);
-
- sock[sockindex] = conn->writesockfd;
- }
-
- bitmap |= GETSOCK_WRITESOCK(sockindex);
- }
-
- return bitmap;
-}
-
/* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
which means this gets called once for each subsequent redirect etc */
void Curl_init_CONNECT(struct Curl_easy *data)
@@ -1430,8 +1161,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
}
wc = data->wildcard;
- if((wc->state < CURLWC_INIT) ||
- (wc->state >= CURLWC_CLEAN)) {
+ if(wc->state < CURLWC_INIT) {
if(wc->ftpwc)
wc->dtor(wc->ftpwc);
Curl_safefree(wc->pattern);
@@ -1635,7 +1365,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
return Curl_uc_to_curlcode(uc);
}
- p = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
+ p = Curl_get_scheme_handler(scheme);
if(p && (p->protocol != data->info.conn_protocol)) {
infof(data, "Clear auth, redirects scheme from %s to %s",
data->info.conn_scheme, scheme);
@@ -1948,3 +1678,41 @@ Curl_setup_transfer(
} /* if(k->getheader || !data->req.no_body) */
}
+
+CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
+ char *buf, size_t blen,
+ bool is_eos, bool *done)
+{
+ CURLcode result = CURLE_OK;
+
+ if(data->conn->handler->write_resp) {
+ /* protocol handlers offering this function take full responsibility
+ * for writing all received download data to the client. */
+ result = data->conn->handler->write_resp(data, buf, blen, is_eos, done);
+ }
+ else {
+ /* No special handling by protocol handler, write all received data
+ * as BODY to the client. */
+ if(blen || is_eos) {
+ int cwtype = CLIENTWRITE_BODY;
+ if(is_eos)
+ cwtype |= CLIENTWRITE_EOS;
+
+#ifndef CURL_DISABLE_POP3
+ if(blen && data->conn->handler->protocol & PROTO_FAMILY_POP3) {
+ result = data->req.ignorebody? CURLE_OK :
+ Curl_pop3_write(data, buf, blen);
+ }
+ else
+#endif /* CURL_DISABLE_POP3 */
+ result = Curl_client_write(data, cwtype, buf, blen);
+ }
+ }
+
+ if(!result && is_eos) {
+ /* If we wrote the EOS, we are definitely done */
+ data->req.eos_written = TRUE;
+ data->req.download_done = TRUE;
+ }
+ return result;
+}
diff --git a/lib/transfer.h b/lib/transfer.h
index 536ac249b..0507f1a45 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -45,9 +45,7 @@ typedef enum {
CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
followtype type);
-CURLcode Curl_readwrite(struct connectdata *conn,
- struct Curl_easy *data, bool *done,
- bool *comeback);
+CURLcode Curl_readwrite(struct Curl_easy *data, bool *done);
int Curl_single_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks);
CURLcode Curl_fillreadbuffer(struct Curl_easy *data, size_t bytes,
@@ -59,6 +57,23 @@ CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
CURLcode Curl_done_sending(struct Curl_easy *data,
struct SingleRequest *k);
+/**
+ * Write the transfer raw response bytes, as received from the connection.
+ * Will handle all passed bytes or return an error. By default, this will
+ * write the bytes as BODY to the client. Protocols may provide a
+ * "write_resp" callback in their handler to add specific treatment. E.g.
+ * HTTP parses response headers and passes them differently to the client.
+ * @param data the transfer
+ * @param buf the raw response bytes
+ * @param blen the amount of bytes in `buf`
+ * @param is_eos TRUE iff the connection indicates this to be the last
+ * bytes of the response
+ * @param done on returnm, TRUE iff the response is complete
+ */
+CURLcode Curl_xfer_write_resp(struct Curl_easy *data,
+ char *buf, size_t blen,
+ bool is_eos, bool *done);
+
/* This sets up a forthcoming transfer */
void
Curl_setup_transfer (struct Curl_easy *data,
diff --git a/lib/url.c b/lib/url.c
index 61dad442d..36395a155 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -168,130 +168,6 @@ static curl_prot_t get_protocol_family(const struct Curl_handler *h)
return h->family;
}
-
-/*
- * 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[] = {
-
-#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
- &Curl_handler_https,
-#endif
-
-#ifndef CURL_DISABLE_HTTP
- &Curl_handler_http,
-#endif
-
-#ifdef USE_WEBSOCKETS
-#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
- &Curl_handler_wss,
-#endif
-
-#ifndef CURL_DISABLE_HTTP
- &Curl_handler_ws,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_FTP
- &Curl_handler_ftp,
-#endif
-
-#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
- &Curl_handler_ftps,
-#endif
-
-#if defined(USE_SSH)
- &Curl_handler_sftp,
-#endif
-
-#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
- &Curl_handler_ldap,
-#if !defined(CURL_DISABLE_LDAPS) && \
- ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
- (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
- &Curl_handler_ldaps,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_IMAP
- &Curl_handler_imap,
-#ifdef USE_SSL
- &Curl_handler_imaps,
-#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
- &Curl_handler_pop3s,
-#endif
-#endif
-
-#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
- (SIZEOF_CURL_OFF_T > 4)
- &Curl_handler_smb,
-#ifdef USE_SSL
- &Curl_handler_smbs,
-#endif
-#endif
-
-#ifndef CURL_DISABLE_RTSP
- &Curl_handler_rtsp,
-#endif
-
-#ifndef CURL_DISABLE_MQTT
- &Curl_handler_mqtt,
-#endif
-
-#ifndef CURL_DISABLE_GOPHER
- &Curl_handler_gopher,
-#ifdef USE_SSL
- &Curl_handler_gophers,
-#endif
-#endif
-
-#ifdef USE_LIBRTMP
- &Curl_handler_rtmp,
- &Curl_handler_rtmpt,
- &Curl_handler_rtmpe,
- &Curl_handler_rtmpte,
- &Curl_handler_rtmps,
- &Curl_handler_rtmpts,
-#endif
-
-#ifndef CURL_DISABLE_DICT
- &Curl_handler_dict,
-#endif
-
- (struct Curl_handler *) NULL
-};
-
void Curl_freeset(struct Curl_easy *data)
{
/* Free all dynamic strings stored in the data->set substructure. */
@@ -320,8 +196,8 @@ void Curl_freeset(struct Curl_easy *data)
Curl_mime_cleanpart(&data->set.mimepost);
#ifndef CURL_DISABLE_COOKIES
- curl_slist_free_all(data->set.cookielist);
- data->set.cookielist = NULL;
+ curl_slist_free_all(data->state.cookielist);
+ data->state.cookielist = NULL;
#endif
}
@@ -363,16 +239,18 @@ CURLcode Curl_close(struct Curl_easy **datap)
/* Detach connection if any is left. This should not be normal, but can be
the case for example with CONNECT_ONLY + recv/send (test 556) */
Curl_detach_connection(data);
- if(data->multi)
- /* This handle is still part of a multi handle, take care of this first
- and detach this handle from there. */
- curl_multi_remove_handle(data->multi, data);
+ if(!data->state.internal) {
+ if(data->multi)
+ /* This handle is still part of a multi handle, take care of this first
+ and detach this handle from there. */
+ curl_multi_remove_handle(data->multi, data);
- if(data->multi_easy) {
- /* when curl_easy_perform() is used, it creates its own multi handle to
- use and this is the one */
- curl_multi_cleanup(data->multi_easy);
- data->multi_easy = NULL;
+ if(data->multi_easy) {
+ /* when curl_easy_perform() is used, it creates its own multi handle to
+ use and this is the one */
+ curl_multi_cleanup(data->multi_easy);
+ data->multi_easy = NULL;
+ }
}
data->magic = 0; /* force a clear AFTER the possibly enforced removal from
@@ -412,7 +290,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
#ifndef CURL_DISABLE_HSTS
if(!data->share || !data->share->hsts)
Curl_hsts_cleanup(&data->hsts);
- curl_slist_free_all(data->set.hstslist); /* clean up list */
+ curl_slist_free_all(data->state.hstslist); /* clean up list */
#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
Curl_http_auth_cleanup_digest(data);
@@ -457,8 +335,8 @@ CURLcode Curl_close(struct Curl_easy **datap)
}
#endif
- Curl_mime_cleanpart(data->state.formp);
#ifndef CURL_DISABLE_HTTP
+ Curl_mime_cleanpart(data->state.formp);
Curl_safefree(data->state.formp);
#endif
@@ -530,26 +408,16 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
Curl_mime_initpart(&set->mimepost);
- /*
- * libcurl 7.10 introduced SSL verification *by default*! This needs to be
- * switched off unless wanted.
- */
+ Curl_ssl_easy_config_init(data);
#ifndef CURL_DISABLE_DOH
set->doh_verifyhost = TRUE;
set->doh_verifypeer = TRUE;
#endif
- set->ssl.primary.verifypeer = TRUE;
- set->ssl.primary.verifyhost = TRUE;
#ifdef USE_SSH
/* defaults to any auth type */
set->ssh_auth_types = CURLSSH_AUTH_DEFAULT;
set->new_directory_perms = 0755; /* Default permissions */
#endif
- 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->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
@@ -566,11 +434,13 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
/* Set the default CA cert bundle/path detected/specified at build time.
*
- * If Schannel is the selected SSL backend then these locations are
- * ignored. We allow setting CA location for schannel only when explicitly
- * specified by the user via CURLOPT_CAINFO / --cacert.
+ * If Schannel or SecureTransport is the selected SSL backend then these
+ * locations are ignored. We allow setting CA location for schannel and
+ * securetransport when explicitly specified by the user via
+ * CURLOPT_CAINFO / --cacert.
*/
- if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
+ if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL &&
+ Curl_ssl_backend() != CURLSSLBACKEND_SECURETRANSPORT) {
#if defined(CURL_CA_BUNDLE)
result = Curl_setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
if(result)
@@ -718,22 +588,18 @@ static void conn_free(struct Curl_easy *data, struct connectdata *conn)
Curl_safefree(conn->socks_proxy.passwd);
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_safefree(conn->oauth_bearer);
-#ifndef CURL_DISABLE_HTTP
- Curl_dyn_free(&conn->trailer);
-#endif
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->localdev);
- Curl_free_primary_ssl_config(&conn->ssl_config);
+ Curl_ssl_conn_config_cleanup(conn);
#ifdef USE_UNIX_SOCKETS
Curl_safefree(conn->unix_domain_socket);
@@ -1059,11 +925,11 @@ ConnectionExists(struct Curl_easy *data,
bool *force_reuse,
bool *waitpipe)
{
- struct connectdata *check;
- struct connectdata *chosen = 0;
+ struct connectdata *chosen = NULL;
bool foundPendingCandidate = FALSE;
- bool canmultiplex = IsMultiplexingPossible(data, needle);
+ bool canmultiplex = FALSE;
struct connectbundle *bundle;
+ struct Curl_llist_element *curr;
#ifdef USE_NTLM
bool wantNTLMhttp = ((data->state.authhost.want &
@@ -1082,395 +948,368 @@ ConnectionExists(struct Curl_easy *data,
bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
(needle->handler->protocol & CURLPROTO_HTTP);
+ *usethis = NULL;
*force_reuse = FALSE;
*waitpipe = FALSE;
/* Look up the bundle with all the connections to this particular host.
Locks the connection cache, beware of early returns! */
bundle = Curl_conncache_find_bundle(data, needle, data->state.conn_cache);
- if(bundle) {
- /* Max pipe length is zero (unlimited) for multiplexed connections */
- struct Curl_llist_element *curr;
-
- infof(data, "Found bundle for host: %p [%s]",
- (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
- "can multiplex" : "serially"));
-
- /* We can't multiplex if we don't know anything about the server */
- if(canmultiplex) {
- if(bundle->multiuse == BUNDLE_UNKNOWN) {
- if(data->set.pipewait) {
- infof(data, "Server doesn't support multiplex yet, wait");
- *waitpipe = TRUE;
- CONNCACHE_UNLOCK(data);
- return FALSE; /* no reuse */
- }
-
- infof(data, "Server doesn't support multiplex (yet)");
- canmultiplex = FALSE;
+ if(!bundle) {
+ CONNCACHE_UNLOCK(data);
+ return FALSE;
+ }
+ infof(data, "Found bundle for host: %p [%s]",
+ (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
+ "can multiplex" : "serially"));
+
+ /* We can only multiplex iff the transfer allows it AND we know
+ * that the server we want to talk to supports it as well. */
+ canmultiplex = FALSE;
+ if(IsMultiplexingPossible(data, needle)) {
+ if(bundle->multiuse == BUNDLE_UNKNOWN) {
+ if(data->set.pipewait) {
+ infof(data, "Server doesn't support multiplex yet, wait");
+ *waitpipe = TRUE;
+ CONNCACHE_UNLOCK(data);
+ return FALSE; /* no reuse */
}
- if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
- !Curl_multiplex_wanted(data->multi)) {
+ infof(data, "Server doesn't support multiplex (yet)");
+ }
+ else if(bundle->multiuse == BUNDLE_MULTIPLEX) {
+ if(Curl_multiplex_wanted(data->multi))
+ canmultiplex = TRUE;
+ else
infof(data, "Could multiplex, but not asked to");
- canmultiplex = FALSE;
- }
- if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
- infof(data, "Can not multiplex, even if we wanted to");
- canmultiplex = FALSE;
- }
}
+ else if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
+ infof(data, "Can not multiplex, even if we wanted to");
+ }
+ }
- curr = bundle->conn_list.head;
- while(curr) {
- bool match = FALSE;
- size_t multiplexed = 0;
+ curr = bundle->conn_list.head;
+ while(curr) {
+ struct connectdata *check = curr->ptr;
+ /* Get next node now. We might remove a dead `check` connection which
+ * would invalidate `curr` as well. */
+ curr = curr->next;
- /*
- * Note that if we use an HTTP proxy in normal mode (no tunneling), we
- * check connections to that proxy and not to the actual remote server.
- */
- check = curr->ptr;
- curr = curr->next;
+ /* Note that if we use an HTTP proxy in normal mode (no tunneling), we
+ * check connections to that proxy and not to the actual remote server.
+ */
+ if(check->connect_only || check->bits.close)
+ /* connect-only or to-be-closed connections will not be reused */
+ continue;
- if(check->connect_only || check->bits.close)
- /* connect-only or to-be-closed connections will not be reused */
- continue;
+ if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
+ && data->set.ipver != check->ip_version) {
+ /* skip because the connection is not via the requested IP version */
+ continue;
+ }
- if(extract_if_dead(check, data)) {
- /* disconnect it */
- Curl_disconnect(data, check, TRUE);
+ if(!canmultiplex) {
+ if(Curl_resolver_asynch() &&
+ /* primary_ip[0] is NUL only if the resolving of the name hasn't
+ completed yet and until then we don't reuse this connection */
+ !check->primary_ip[0])
continue;
- }
+ }
- if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
- && data->set.ipver != check->ip_version) {
- /* skip because the connection is not via the requested IP version */
+ if(CONN_INUSE(check)) {
+ if(!canmultiplex) {
+ /* transfer can't be multiplexed and check is in use */
continue;
}
-
- if(bundle->multiuse == BUNDLE_MULTIPLEX)
- multiplexed = CONN_INUSE(check);
-
- if(!canmultiplex) {
- if(multiplexed) {
- /* can only happen within multi handles, and means that another easy
- handle is using this connection */
- continue;
- }
-
- if(Curl_resolver_asynch() &&
- /* primary_ip[0] is NUL only if the resolving of the name hasn't
- completed yet and until then we don't reuse this connection */
- !check->primary_ip[0])
+ else {
+ /* Could multiplex, but not when check belongs to another multi */
+ struct Curl_llist_element *e = check->easyq.head;
+ struct Curl_easy *entry = e->ptr;
+ if(entry->multi != data->multi)
continue;
}
+ }
- if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
- foundPendingCandidate = TRUE;
- /* Don't pick a connection that hasn't connected yet */
- infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
- " isn't open enough, can't reuse", check->connection_id);
- continue;
- }
+ if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
+ foundPendingCandidate = TRUE;
+ /* Don't pick a connection that hasn't connected yet */
+ infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " isn't open enough, can't reuse", check->connection_id);
+ continue;
+ }
+
+ /* `check` is connected. if it is in use and does not support multiplex,
+ * we cannot use it. */
+ if(!check->bits.multiplex && CONN_INUSE(check))
+ continue;
#ifdef USE_UNIX_SOCKETS
- if(needle->unix_domain_socket) {
- if(!check->unix_domain_socket)
- continue;
- if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
- continue;
- if(needle->bits.abstract_unix_socket !=
- check->bits.abstract_unix_socket)
- continue;
- }
- else if(check->unix_domain_socket)
+ if(needle->unix_domain_socket) {
+ if(!check->unix_domain_socket)
continue;
-#endif
-
- if((needle->handler->flags&PROTOPT_SSL) !=
- (check->handler->flags&PROTOPT_SSL))
- /* don't do mixed SSL and non-SSL connections */
- if(get_protocol_family(check->handler) !=
- 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)
+ if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
continue;
-
- if(needle->bits.socksproxy &&
- !socks_proxy_info_matches(&needle->socks_proxy,
- &check->socks_proxy))
+ if(needle->bits.abstract_unix_socket !=
+ check->bits.abstract_unix_socket)
continue;
+ }
+ else if(check->unix_domain_socket)
+ 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 */
- continue;
- if(needle->bits.conn_to_port != check->bits.conn_to_port)
- /* don't mix connections that use the "connect to port" feature and
- * connections that don't use this feature */
+ if((needle->handler->flags&PROTOPT_SSL) !=
+ (check->handler->flags&PROTOPT_SSL))
+ /* don't do mixed SSL and non-SSL connections */
+ if(get_protocol_family(check->handler) !=
+ needle->handler->protocol || !check->bits.tls_upgraded)
+ /* except protocols that have been upgraded via TLS */
continue;
-#ifndef CURL_DISABLE_PROXY
- if(needle->bits.httpproxy) {
- if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
- continue;
+ 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 */
+ continue;
- if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
- continue;
+ if(needle->bits.conn_to_port != check->bits.conn_to_port)
+ /* don't mix connections that use the "connect to port" feature and
+ * connections that don't use this feature */
+ continue;
- if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
- /* use https proxy */
- if(needle->http_proxy.proxytype !=
- check->http_proxy.proxytype)
- continue;
- else if(needle->handler->flags&PROTOPT_SSL) {
- /* use double layer ssl */
- if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
- &check->proxy_ssl_config))
- continue;
- }
- else if(!Curl_ssl_config_matches(&needle->ssl_config,
- &check->ssl_config))
- continue;
- }
- }
-#endif
+#ifndef CURL_DISABLE_PROXY
+ if(needle->bits.httpproxy != check->bits.httpproxy ||
+ needle->bits.socksproxy != check->bits.socksproxy)
+ continue;
- if(h2upgrade && !check->httpversion && canmultiplex) {
- if(data->set.pipewait) {
- infof(data, "Server upgrade doesn't support multiplex yet, wait");
- *waitpipe = TRUE;
- CONNCACHE_UNLOCK(data);
- return FALSE; /* no reuse */
- }
- infof(data, "Server upgrade cannot be used");
- continue; /* can't be used atm */
- }
+ if(needle->bits.socksproxy &&
+ !socks_proxy_info_matches(&needle->socks_proxy,
+ &check->socks_proxy))
+ continue;
- if(!canmultiplex && CONN_INUSE(check))
- /* this request can't be multiplexed but the checked connection is
- already in use so we skip it */
+ if(needle->bits.httpproxy) {
+ if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
continue;
- if(CONN_INUSE(check)) {
- /* Subject for multiplex use if 'checks' belongs to the same multi
- handle as 'data' is. */
- struct Curl_llist_element *e = check->easyq.head;
- struct Curl_easy *entry = e->ptr;
- if(entry->multi != data->multi)
- continue;
- }
+ if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
+ continue;
- if(needle->localdev || needle->localport) {
- /* If we are bound to a specific local end (IP+port), we must not
- reuse a random other one, although if we didn't ask for a
- particular one we can reuse one that was bound.
-
- This comparison is a bit rough and too strict. Since the input
- parameters can be specified in numerous ways and still end up the
- same it would take a lot of processing to make it really accurate.
- Instead, this matching will assume that reuses of bound connections
- will most likely also reuse the exact same binding parameters and
- missing out a few edge cases shouldn't hurt anyone very much.
- */
- if((check->localport != needle->localport) ||
- (check->localportrange != needle->localportrange) ||
- (needle->localdev &&
- (!check->localdev || strcmp(check->localdev, needle->localdev))))
+ if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
+ /* https proxies come in different types, http/1.1, h2, ... */
+ if(needle->http_proxy.proxytype != check->http_proxy.proxytype)
continue;
- }
-
- if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
- /* This protocol requires credentials per connection,
- so verify that we're using the same name and password as well */
- if(Curl_timestrcmp(needle->user, check->user) ||
- Curl_timestrcmp(needle->passwd, check->passwd) ||
- Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
- Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
- /* one of them was different */
+ /* match SSL config to proxy */
+ if(!Curl_ssl_conn_config_match(data, check, TRUE)) {
+ DEBUGF(infof(data,
+ "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " has different SSL proxy parameters, can't reuse",
+ check->connection_id));
continue;
}
+ /* the SSL config to the server, which may apply here is checked
+ * further below */
}
+ }
+#endif
- /* GSS delegation differences do not actually affect every connection
- and auth method, but this check takes precaution before efficiency */
- if(needle->gssapi_delegation != check->gssapi_delegation)
+ if(h2upgrade && !check->httpversion && canmultiplex) {
+ if(data->set.pipewait) {
+ infof(data, "Server upgrade doesn't support multiplex yet, wait");
+ *waitpipe = TRUE;
+ CONNCACHE_UNLOCK(data);
+ return FALSE; /* no reuse */
+ }
+ infof(data, "Server upgrade cannot be used");
+ continue; /* can't be used atm */
+ }
+
+ if(needle->localdev || needle->localport) {
+ /* If we are bound to a specific local end (IP+port), we must not
+ reuse a random other one, although if we didn't ask for a
+ particular one we can reuse one that was bound.
+
+ This comparison is a bit rough and too strict. Since the input
+ parameters can be specified in numerous ways and still end up the
+ same it would take a lot of processing to make it really accurate.
+ Instead, this matching will assume that reuses of bound connections
+ will most likely also reuse the exact same binding parameters and
+ missing out a few edge cases shouldn't hurt anyone very much.
+ */
+ if((check->localport != needle->localport) ||
+ (check->localportrange != needle->localportrange) ||
+ (needle->localdev &&
+ (!check->localdev || strcmp(check->localdev, needle->localdev))))
continue;
+ }
- /* If multiplexing isn't enabled on the h2 connection and h1 is
- explicitly requested, handle it: */
- if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
- (((check->httpversion >= 20) &&
- (data->state.httpwant < CURL_HTTP_VERSION_2_0))
- || ((check->httpversion >= 30) &&
- (data->state.httpwant < CURL_HTTP_VERSION_3))))
+ if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
+ /* This protocol requires credentials per connection,
+ so verify that we're using the same name and password as well */
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd) ||
+ Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
+ Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
+ /* one of them was different */
continue;
-#ifdef USE_SSH
- else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
- if(!ssh_config_matches(needle, check))
- continue;
}
+ }
+
+ /* GSS delegation differences do not actually affect every connection
+ and auth method, but this check takes precaution before efficiency */
+ if(needle->gssapi_delegation != check->gssapi_delegation)
+ continue;
+
+ /* If looking for HTTP and the HTTP version we want is less
+ * than the HTTP version of the check connection, continue looking */
+ if((needle->handler->protocol & PROTO_FAMILY_HTTP) &&
+ (((check->httpversion >= 20) &&
+ (data->state.httpwant < CURL_HTTP_VERSION_2_0))
+ || ((check->httpversion >= 30) &&
+ (data->state.httpwant < CURL_HTTP_VERSION_3))))
+ continue;
+#ifdef USE_SSH
+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
+ if(!ssh_config_matches(needle, check))
+ continue;
+ }
#endif
#ifndef CURL_DISABLE_FTP
- else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
- /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
- if(Curl_timestrcmp(needle->proto.ftpc.account,
- check->proto.ftpc.account) ||
- Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
- check->proto.ftpc.alternative_to_user) ||
- (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
- (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
- continue;
- }
+ else if(get_protocol_family(needle->handler) & PROTO_FAMILY_FTP) {
+ /* Also match ACCOUNT, ALTERNATIVE-TO-USER, USE_SSL and CCC options */
+ if(Curl_timestrcmp(needle->proto.ftpc.account,
+ check->proto.ftpc.account) ||
+ Curl_timestrcmp(needle->proto.ftpc.alternative_to_user,
+ check->proto.ftpc.alternative_to_user) ||
+ (needle->proto.ftpc.use_ssl != check->proto.ftpc.use_ssl) ||
+ (needle->proto.ftpc.ccc != check->proto.ftpc.ccc))
+ continue;
+ }
#endif
- if((needle->handler->flags&PROTOPT_SSL)
+ /* Additional match requirements if talking TLS OR
+ * not talking to a HTTP proxy OR using a tunnel through a 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 an 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) ==
- 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 ||
- needle->conn_to_port == check->conn_to_port) &&
- strcasecompare(needle->host.name, check->host.name) &&
- needle->remote_port == check->remote_port) {
- /* The schemes match or the protocol family is the same and the
- previous connection was TLS upgraded, and the hostname and host
- port match */
- if(needle->handler->flags & PROTOPT_SSL) {
- /* This is a SSL connection so verify that we're using the same
- SSL options as well */
- if(!Curl_ssl_config_matches(&needle->ssl_config,
- &check->ssl_config)) {
- DEBUGF(infof(data,
- "Connection #%" CURL_FORMAT_CURL_OFF_T
- " has different SSL parameters, can't reuse",
- check->connection_id));
- continue;
- }
- }
- match = TRUE;
- }
- }
- else {
- /* The requested connection is using the same HTTP proxy in normal
- mode (no tunneling) */
- match = TRUE;
+ || !needle->bits.httpproxy || needle->bits.tunnel_proxy
+#endif
+ ) {
+ /* Talking the same protocol scheme or a TLS upgraded protocol in the
+ * same protocol family? */
+ if(!strcasecompare(needle->handler->scheme, check->handler->scheme) &&
+ (get_protocol_family(check->handler) !=
+ needle->handler->protocol || !check->bits.tls_upgraded))
+ continue;
+
+ /* If needle has "conn_to_*" set, check must match this */
+ if((needle->bits.conn_to_host && !strcasecompare(
+ needle->conn_to_host.name, check->conn_to_host.name)) ||
+ (needle->bits.conn_to_port &&
+ needle->conn_to_port != check->conn_to_port))
+ continue;
+
+ /* hostname and port must match */
+ if(!strcasecompare(needle->host.name, check->host.name) ||
+ needle->remote_port != check->remote_port)
+ continue;
+
+ /* If talking TLS, check needs to use the same SSL options. */
+ if((needle->handler->flags & PROTOPT_SSL) &&
+ !Curl_ssl_conn_config_match(data, check, FALSE)) {
+ DEBUGF(infof(data,
+ "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " has different SSL parameters, can't reuse",
+ check->connection_id));
+ continue;
}
+ }
- if(match) {
#if defined(USE_NTLM)
- /* If we are looking for an HTTP+NTLM connection, check if this is
- already authenticating with the right credentials. If not, keep
- looking so that we can reuse NTLM connections if
- possible. (Especially we must not reuse the same connection if
- partway through a handshake!) */
- if(wantNTLMhttp) {
- if(Curl_timestrcmp(needle->user, check->user) ||
- Curl_timestrcmp(needle->passwd, check->passwd)) {
-
- /* we prefer a credential match, but this is at least a connection
- that can be reused and "upgraded" to NTLM */
- if(check->http_ntlm_state == NTLMSTATE_NONE)
- chosen = check;
- continue;
- }
- }
- else if(check->http_ntlm_state != NTLMSTATE_NONE) {
- /* Connection is using NTLM auth but we don't want NTLM */
- continue;
- }
-
-#ifndef CURL_DISABLE_PROXY
- /* Same for Proxy NTLM authentication */
- if(wantProxyNTLMhttp) {
- /* Both check->http_proxy.user and check->http_proxy.passwd can be
- * NULL */
- if(!check->http_proxy.user || !check->http_proxy.passwd)
- continue;
-
- if(Curl_timestrcmp(needle->http_proxy.user,
- check->http_proxy.user) ||
- Curl_timestrcmp(needle->http_proxy.passwd,
- check->http_proxy.passwd))
- continue;
- }
- else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
- /* 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 */
+ /* If we are looking for an HTTP+NTLM connection, check if this is
+ already authenticating with the right credentials. If not, keep
+ looking so that we can reuse NTLM connections if
+ possible. (Especially we must not reuse the same connection if
+ partway through a handshake!) */
+ if(wantNTLMhttp) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd)) {
+
+ /* we prefer a credential match, but this is at least a connection
+ that can be reused and "upgraded" to NTLM */
+ if(check->http_ntlm_state == NTLMSTATE_NONE)
chosen = check;
+ continue;
+ }
+ }
+ else if(check->http_ntlm_state != NTLMSTATE_NONE) {
+ /* Connection is using NTLM auth but we don't want NTLM */
+ continue;
+ }
- if((wantNTLMhttp &&
- (check->http_ntlm_state != NTLMSTATE_NONE)) ||
- (wantProxyNTLMhttp &&
- (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
- /* We must use this connection, no other */
- *force_reuse = TRUE;
- break;
- }
+#ifndef CURL_DISABLE_PROXY
+ /* Same for Proxy NTLM authentication */
+ if(wantProxyNTLMhttp) {
+ /* Both check->http_proxy.user and check->http_proxy.passwd can be
+ * NULL */
+ if(!check->http_proxy.user || !check->http_proxy.passwd)
+ continue;
- /* Continue look up for a better connection */
- continue;
- }
+ if(Curl_timestrcmp(needle->http_proxy.user,
+ check->http_proxy.user) ||
+ Curl_timestrcmp(needle->http_proxy.passwd,
+ check->http_proxy.passwd))
+ continue;
+ }
+ else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
+ /* Proxy connection is using NTLM auth but we don't want NTLM */
+ continue;
+ }
+#endif
+ if(wantNTLMhttp || wantProxyNTLMhttp) {
+ /* Credentials are already checked, we may use this connection.
+ * With NTLM being weird as it is, we MUST use a
+ * connection where it has already been fully negotiated.
+ * If it has not, we keep on looking for a better one. */
+ chosen = check;
+
+ if((wantNTLMhttp &&
+ (check->http_ntlm_state != NTLMSTATE_NONE)) ||
+ (wantProxyNTLMhttp &&
+ (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
+ /* We must use this connection, no other */
+ *force_reuse = TRUE;
+ break;
+ }
+ /* Continue look up for a better connection */
+ continue;
+ }
#endif
- if(canmultiplex) {
- /* We can multiplex if we want to. Let's continue looking for
- the optimal connection to use. */
-
- if(!multiplexed) {
- /* We have the optimal connection. Let's stop looking. */
- chosen = check;
- break;
- }
-#ifdef USE_NGHTTP2
- /* If multiplexed, make sure we don't go over concurrency limit */
- if(check->bits.multiplex) {
- if(multiplexed >= Curl_conn_get_max_concurrent(data, check,
- FIRSTSOCKET)) {
- infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
- multiplexed);
- continue;
- }
- else if(multiplexed >=
- Curl_multi_max_concurrent_streams(data->multi)) {
- infof(data, "client side MAX_CONCURRENT_STREAMS reached"
- ", skip (%zu)",
- multiplexed);
- continue;
- }
- }
-#endif
- /* When not multiplexed, we have a match here! */
- chosen = check;
- infof(data, "Multiplexed connection found");
- break;
- }
- else {
- /* We have found a connection. Let's stop searching. */
- chosen = check;
- break;
- }
+ if(CONN_INUSE(check)) {
+ DEBUGASSERT(canmultiplex);
+ DEBUGASSERT(check->bits.multiplex);
+ /* If multiplexed, make sure we don't go over concurrency limit */
+ if(CONN_INUSE(check) >=
+ Curl_multi_max_concurrent_streams(data->multi)) {
+ infof(data, "client side MAX_CONCURRENT_STREAMS reached"
+ ", skip (%zu)", CONN_INUSE(check));
+ continue;
+ }
+ if(CONN_INUSE(check) >=
+ Curl_conn_get_max_concurrent(data, check, FIRSTSOCKET)) {
+ infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)",
+ CONN_INUSE(check));
+ continue;
}
+ /* When not multiplexed, we have a match here! */
+ infof(data, "Multiplexed connection found");
+ }
+ else if(extract_if_dead(check, data)) {
+ /* disconnect it */
+ Curl_disconnect(data, check, TRUE);
+ continue;
}
- }
+
+ /* We have found a connection. Let's stop searching. */
+ chosen = check;
+ break;
+ } /* loop over connection bundle */
if(chosen) {
/* mark it as used before releasing the lock */
@@ -1516,6 +1355,8 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
+ conn->sockfd = CURL_SOCKET_BAD;
+ conn->writesockfd = CURL_SOCKET_BAD;
conn->connection_id = -1; /* no ID */
conn->port = -1; /* unknown at this point */
conn->remote_port = -1; /* unknown at this point */
@@ -1561,17 +1402,6 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
#endif
- 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;
- conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
-#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;
- conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
-#endif
conn->ip_version = data->set.ipver;
conn->connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
@@ -1615,30 +1445,231 @@ error:
return NULL;
}
-/* returns the handler if the given scheme is built-in */
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
- size_t schemelen)
+const struct Curl_handler *Curl_get_scheme_handler(const char *scheme)
{
- const struct Curl_handler * const *pp;
- const struct Curl_handler *p;
- /* Scan protocol handler table and match against 'scheme'. The handler may
- be changed later when the protocol specific setup function is called. */
- if(schemelen == CURL_ZERO_TERMINATED)
- schemelen = strlen(scheme);
- for(pp = protocols; (p = *pp) != NULL; pp++)
- if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen])
- /* Protocol found in table. */
- return p;
- return NULL; /* not found */
+ return Curl_getn_scheme_handler(scheme, strlen(scheme));
}
+/* returns the handler if the given scheme is built-in */
+const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme,
+ size_t len)
+{
+ /* table generated by schemetable.c:
+ 1. gcc schemetable.c && ./a.out
+ 2. check how small the table gets
+ 3. tweak the hash algorithm, then rerun from 1
+ 4. when the table is good enough
+ 5. copy the table into this source code
+ 6. make sure this function uses the same hash function that worked for
+ schemetable.c
+ 7. if needed, adjust the #ifdefs in schemetable.c and rerun
+ */
+ static const struct Curl_handler * const protocols[67] = {
+#ifndef CURL_DISABLE_FILE
+ &Curl_handler_file,
+#else
+ NULL,
+#endif
+ NULL, NULL,
+#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
+ &Curl_handler_gophers,
+#else
+ NULL,
+#endif
+ NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpe,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_SMTP
+ &Curl_handler_smtp,
+#else
+ NULL,
+#endif
+#if defined(USE_SSH)
+ &Curl_handler_sftp,
+#else
+ NULL,
+#endif
+#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
+ (SIZEOF_CURL_OFF_T > 4)
+ &Curl_handler_smb,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)
+ &Curl_handler_smtps,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_TELNET
+ &Curl_handler_telnet,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_GOPHER
+ &Curl_handler_gopher,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_TFTP
+ &Curl_handler_tftp,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
+ &Curl_handler_ftps,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_http,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_IMAP
+ &Curl_handler_imap,
+#else
+ NULL,
+#endif
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmps,
+#else
+ NULL,
+#endif
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpt,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#if !defined(CURL_DISABLE_LDAP) && \
+ !defined(CURL_DISABLE_LDAPS) && \
+ ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
+ (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
+ &Curl_handler_ldaps,
+#else
+ NULL,
+#endif
+#if defined(USE_WEBSOCKETS) && \
+ defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_wss,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_https,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+#ifndef CURL_DISABLE_RTSP
+ &Curl_handler_rtsp,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \
+ defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)
+ &Curl_handler_smbs,
+#else
+ NULL,
+#endif
+#if defined(USE_SSH) && !defined(USE_WOLFSSH)
+ &Curl_handler_scp,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifndef CURL_DISABLE_POP3
+ &Curl_handler_pop3,
+#else
+ NULL,
+#endif
+ NULL, NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmp,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpte,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifndef CURL_DISABLE_DICT
+ &Curl_handler_dict,
+#else
+ NULL,
+#endif
+ NULL, NULL, NULL,
+#ifndef CURL_DISABLE_MQTT
+ &Curl_handler_mqtt,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)
+ &Curl_handler_pop3s,
+#else
+ NULL,
+#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)
+ &Curl_handler_imaps,
+#else
+ NULL,
+#endif
+ NULL,
+#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_ws,
+#else
+ NULL,
+#endif
+ NULL,
+#ifdef USE_LIBRTMP
+ &Curl_handler_rtmpts,
+#else
+ NULL,
+#endif
+#ifndef CURL_DISABLE_LDAP
+ &Curl_handler_ldap,
+#else
+ NULL,
+#endif
+ NULL, NULL,
+#ifndef CURL_DISABLE_FTP
+ &Curl_handler_ftp,
+#else
+ NULL,
+#endif
+ };
+
+ if(len && (len <= 7)) {
+ const char *s = scheme;
+ size_t l = len;
+ const struct Curl_handler *h;
+ unsigned int c = 978;
+ while(l) {
+ c <<= 5;
+ c += Curl_raw_tolower(*s);
+ s++;
+ l--;
+ }
+
+ h = protocols[c % 67];
+ if(h && strncasecompare(scheme, h->scheme, len) && !h->scheme[len])
+ return h;
+ }
+ return NULL;
+}
static CURLcode findprotocol(struct Curl_easy *data,
struct connectdata *conn,
const char *protostr)
{
- const struct Curl_handler *p = Curl_builtin_scheme(protostr,
- CURL_ZERO_TERMINATED);
+ const struct Curl_handler *p = Curl_get_scheme_handler(protostr);
if(p && /* Protocol found in table. Check if allowed */
(data->set.allowed_protocols & p->protocol)) {
@@ -1652,7 +1683,6 @@ static CURLcode findprotocol(struct Curl_easy *data,
else {
/* Perform setup complement if some. */
conn->handler = conn->given = p;
-
/* 'port' and 'remote_port' are set in setup_connection_internals() */
return CURLE_OK;
}
@@ -1661,8 +1691,9 @@ static CURLcode findprotocol(struct Curl_easy *data,
/* The protocol was not found in the table, but we don't have to assign it
to anything since it is already assigned to a dummy-struct in the
create_conn() function when the connectdata struct is allocated. */
- failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
- protostr);
+ failf(data, "Protocol \"%s\" %s%s", protostr,
+ p ? "disabled" : "not supported",
+ data->state.this_is_a_follow ? " (in redirect)":"");
return CURLE_UNSUPPORTED_PROTOCOL;
}
@@ -1705,14 +1736,14 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
conn->scope_id = (unsigned int)scope;
#if defined(HAVE_IF_NAMETOINDEX)
else {
-#elif defined(WIN32)
+#elif defined(_WIN32)
else if(Curl_if_nametoindex) {
#endif
-#if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
+#if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32)
/* Zone identifier is not numeric */
unsigned int scopeidx = 0;
-#if defined(WIN32)
+#if defined(_WIN32)
scopeidx = Curl_if_nametoindex(zoneid);
#else
scopeidx = if_nametoindex(zoneid);
@@ -1727,7 +1758,7 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
else
conn->scope_id = scopeidx;
}
-#endif /* HAVE_IF_NAMETOINDEX || WIN32 */
+#endif /* HAVE_IF_NAMETOINDEX || _WIN32 */
free(zoneid);
}
@@ -3596,85 +3627,10 @@ static CURLcode create_conn(struct Curl_easy *data,
conn->send[SECONDARYSOCKET] = Curl_conn_send;
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
- /* Get a cloned copy of the SSL config situation stored in the
- connection struct. But to get this going nicely, we must first make
- sure that the strings in the master copy are pointing to the correct
- strings in the session handle strings array!
-
- Keep in mind that the pointers in the master copy are pointing to strings
- that will be freed as part of the Curl_easy struct, but all cloned
- copies will be separately allocated.
- */
- data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
- data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
- data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
- data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
- data->set.ssl.primary.cipher_list =
- data->set.str[STRING_SSL_CIPHER_LIST];
- data->set.ssl.primary.cipher_list13 =
- data->set.str[STRING_SSL_CIPHER13_LIST];
- data->set.ssl.primary.pinned_key =
- data->set.str[STRING_SSL_PINNEDPUBLICKEY];
- data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
- data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
- data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
-
-#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.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.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
- data->set.proxy_ssl.primary.ca_info_blob =
- data->set.blobs[BLOB_CAINFO_PROXY];
- data->set.proxy_ssl.primary.issuercert =
- data->set.str[STRING_SSL_ISSUERCERT_PROXY];
- data->set.proxy_ssl.primary.issuercert_blob =
- data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
- data->set.proxy_ssl.primary.CRLfile =
- data->set.str[STRING_SSL_CRLFILE_PROXY];
- data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
- data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
- data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
- data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
- data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
- data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
-#endif
- data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
- data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
- data->set.ssl.key = data->set.str[STRING_KEY];
- data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
- data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
- data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
-#ifdef USE_TLS_SRP
- data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
- data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
-#ifndef CURL_DISABLE_PROXY
- data->set.proxy_ssl.primary.username =
- data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
- data->set.proxy_ssl.primary.password =
- data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
-#endif
-#endif
- data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
-
- if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
- &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;
+ /* Complete the easy's SSL configuration for connection cache matching */
+ result = Curl_ssl_easy_config_complete(data);
+ if(result)
goto out;
- }
-#endif
prune_dead_connections(data);
@@ -3789,6 +3745,12 @@ 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!
*/
+ result = Curl_ssl_conn_config_init(data, conn);
+ if(result) {
+ DEBUGF(fprintf(stderr, "Error: init connection ssl config\n"));
+ goto out;
+ }
+
Curl_attach_connection(data, conn);
result = Curl_conncache_add_conn(data);
if(result)
@@ -3976,6 +3938,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
k->bytecount = 0;
k->ignorebody = FALSE;
+ Curl_client_cleanup(data);
Curl_speedinit(data);
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
diff --git a/lib/url.h b/lib/url.h
index f6a5b2573..7c1a29bc3 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -46,8 +46,13 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
- size_t schemelen);
+/* Get protocol handler for a URI scheme
+ * @param scheme URI scheme, case-insensitive
+ * @return NULL of handler not found
+ */
+const struct Curl_handler *Curl_get_scheme_handler(const char *scheme);
+const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme,
+ size_t len);
#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
diff --git a/lib/urlapi.c b/lib/urlapi.c
index 4efab611c..3cd0362c5 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -126,6 +126,9 @@ static const char *find_host_sep(const char *url)
return sep < query ? sep : query;
}
+/* convert CURLcode to CURLUcode */
+#define cc2cu(x) ((x) == CURLE_TOO_LARGE ? CURLUE_TOO_LARGE : \
+ CURLUE_OUT_OF_MEMORY)
/*
* Decide whether a character in a URL must be escaped.
*/
@@ -146,6 +149,7 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
bool left = !query;
const unsigned char *iptr;
const unsigned char *host_sep = (const unsigned char *) url;
+ CURLcode result;
if(!relative)
host_sep = (const unsigned char *) find_host_sep(url);
@@ -154,20 +158,19 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
len; iptr++, len--) {
if(iptr < host_sep) {
- if(Curl_dyn_addn(o, iptr, 1))
- return CURLUE_OUT_OF_MEMORY;
+ result = Curl_dyn_addn(o, iptr, 1);
+ if(result)
+ return cc2cu(result);
continue;
}
if(*iptr == ' ') {
- if(left) {
- if(Curl_dyn_addn(o, "%20", 3))
- return CURLUE_OUT_OF_MEMORY;
- }
- else {
- if(Curl_dyn_addn(o, "+", 1))
- return CURLUE_OUT_OF_MEMORY;
- }
+ if(left)
+ result = Curl_dyn_addn(o, "%20", 3);
+ else
+ result = Curl_dyn_addn(o, "+", 1);
+ if(result)
+ return cc2cu(result);
continue;
}
@@ -178,13 +181,12 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
char out[3]={'%'};
out[1] = hexdigits[*iptr>>4];
out[2] = hexdigits[*iptr & 0xf];
- if(Curl_dyn_addn(o, out, 3))
- return CURLUE_OUT_OF_MEMORY;
- }
- else {
- if(Curl_dyn_addn(o, iptr, 1))
- return CURLUE_OUT_OF_MEMORY;
+ result = Curl_dyn_addn(o, out, 3);
}
+ else
+ result = Curl_dyn_addn(o, iptr, 1);
+ if(result)
+ return cc2cu(result);
}
return CURLUE_OK;
@@ -206,7 +208,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
(void)buflen; /* only used in debug-builds */
if(buf)
buf[0] = 0; /* always leave a defined value in buf */
-#ifdef WIN32
+#ifdef _WIN32
if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url))
return 0;
#endif
@@ -248,7 +250,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
*
* Note that this function destroys the 'base' string.
*/
-static char *concat_url(char *base, const char *relurl)
+static CURLcode concat_url(char *base, const char *relurl, char **newurl)
{
/***
TRY to append this new path to the old URL
@@ -260,6 +262,9 @@ static char *concat_url(char *base, const char *relurl)
char *pathsep;
bool host_changed = FALSE;
const char *useurl = relurl;
+ CURLcode result = CURLE_OK;
+ CURLUcode uc;
+ *newurl = NULL;
/* protsep points to the start of the host name */
protsep = strstr(base, "//");
@@ -360,21 +365,27 @@ static char *concat_url(char *base, const char *relurl)
Curl_dyn_init(&newest, CURL_MAX_INPUT_LENGTH);
/* copy over the root url part */
- if(Curl_dyn_add(&newest, base))
- return NULL;
+ result = Curl_dyn_add(&newest, base);
+ if(result)
+ return result;
/* check if we need to append a slash */
if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
;
else {
- if(Curl_dyn_addn(&newest, "/", 1))
- return NULL;
+ result = Curl_dyn_addn(&newest, "/", 1);
+ if(result)
+ return result;
}
/* then append the new piece on the right side */
- urlencode_str(&newest, useurl, strlen(useurl), !host_changed, FALSE);
+ uc = urlencode_str(&newest, useurl, strlen(useurl), !host_changed,
+ FALSE);
+ if(uc)
+ return (uc == CURLUE_TOO_LARGE) ? CURLE_TOO_LARGE : CURLE_OUT_OF_MEMORY;
- return Curl_dyn_ptr(&newest);
+ *newurl = Curl_dyn_ptr(&newest);
+ return CURLE_OK;
}
/* scan for byte values <= 31, 127 and sometimes space */
@@ -446,7 +457,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
/* if this is a known scheme, get some details */
if(u->scheme)
- h = Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+ h = Curl_get_scheme_handler(u->scheme);
/* We could use the login information in the URL so extract it. Only parse
options if the handler says we should. Note that 'h' might be NULL! */
@@ -712,24 +723,30 @@ static int ipv4_normalize(struct dynbuf *host)
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- parts[0] >> 24, (parts[0] >> 16) & 0xff,
- (parts[0] >> 8) & 0xff, parts[0] & 0xff);
+ (unsigned int)(parts[0] >> 24),
+ (unsigned int)((parts[0] >> 16) & 0xff),
+ (unsigned int)((parts[0] >> 8) & 0xff),
+ (unsigned int)(parts[0] & 0xff));
break;
case 1: /* a.b -- 8.24 bits */
if((parts[0] > 0xff) || (parts[1] > 0xffffff))
return HOST_NAME;
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- parts[0], (parts[1] >> 16) & 0xff,
- (parts[1] >> 8) & 0xff, parts[1] & 0xff);
+ (unsigned int)(parts[0]),
+ (unsigned int)((parts[1] >> 16) & 0xff),
+ (unsigned int)((parts[1] >> 8) & 0xff),
+ (unsigned int)(parts[1] & 0xff));
break;
case 2: /* a.b.c -- 8.8.16 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xffff))
return HOST_NAME;
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- parts[0], parts[1], (parts[2] >> 8) & 0xff,
- parts[2] & 0xff);
+ (unsigned int)(parts[0]),
+ (unsigned int)(parts[1]),
+ (unsigned int)((parts[2] >> 8) & 0xff),
+ (unsigned int)(parts[2] & 0xff));
break;
case 3: /* a.b.c.d -- 8.8.8.8 bits */
if((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff) ||
@@ -737,7 +754,10 @@ static int ipv4_normalize(struct dynbuf *host)
return HOST_NAME;
Curl_dyn_reset(host);
result = Curl_dyn_addf(host, "%u.%u.%u.%u",
- parts[0], parts[1], parts[2], parts[3]);
+ (unsigned int)(parts[0]),
+ (unsigned int)(parts[1]),
+ (unsigned int)(parts[2]),
+ (unsigned int)(parts[3]));
break;
}
if(result)
@@ -766,7 +786,7 @@ static CURLUcode urldecode_host(struct dynbuf *host)
result = Curl_dyn_addn(host, decoded, dlen);
free(decoded);
if(result)
- return CURLUE_OUT_OF_MEMORY;
+ return cc2cu(result);
}
return CURLUE_OK;
@@ -779,22 +799,24 @@ static CURLUcode parse_authority(struct Curl_URL *u,
bool has_scheme)
{
size_t offset;
- CURLUcode result;
+ CURLUcode uc;
+ CURLcode result;
/*
* Parse the login details and strip them out of the host name.
*/
- result = parse_hostname_login(u, auth, authlen, flags, &offset);
- if(result)
+ uc = parse_hostname_login(u, auth, authlen, flags, &offset);
+ if(uc)
goto out;
- if(Curl_dyn_addn(host, auth + offset, authlen - offset)) {
- result = CURLUE_OUT_OF_MEMORY;
+ result = Curl_dyn_addn(host, auth + offset, authlen - offset);
+ if(result) {
+ uc = cc2cu(result);
goto out;
}
- result = Curl_parse_port(u, host, has_scheme);
- if(result)
+ uc = Curl_parse_port(u, host, has_scheme);
+ if(uc)
goto out;
if(!Curl_dyn_len(host))
@@ -804,24 +826,24 @@ static CURLUcode parse_authority(struct Curl_URL *u,
case HOST_IPV4:
break;
case HOST_IPV6:
- result = ipv6_parse(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+ uc = ipv6_parse(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
break;
case HOST_NAME:
- result = urldecode_host(host);
- if(!result)
- result = hostname_check(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
+ uc = urldecode_host(host);
+ if(!uc)
+ uc = hostname_check(u, Curl_dyn_ptr(host), Curl_dyn_len(host));
break;
case HOST_ERROR:
- result = CURLUE_OUT_OF_MEMORY;
+ uc = CURLUE_OUT_OF_MEMORY;
break;
case HOST_BAD:
default:
- result = CURLUE_BAD_HOSTNAME; /* Bad IPv4 address even */
+ uc = CURLUE_BAD_HOSTNAME; /* Bad IPv4 address even */
break;
}
out:
- return result;
+ return uc;
}
CURLUcode Curl_url_set_authority(CURLU *u, const char *authority,
@@ -1056,7 +1078,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
ptr += 9; /* now points to the slash after the host */
}
else {
-#if defined(WIN32)
+#if defined(_WIN32)
size_t len;
/* the host name, NetBIOS computer name, can not contain disallowed
@@ -1070,8 +1092,9 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
len = path - ptr;
if(len) {
- if(Curl_dyn_addn(&host, ptr, len)) {
- result = CURLUE_OUT_OF_MEMORY;
+ CURLcode code = Curl_dyn_addn(&host, ptr, len);
+ if(code) {
+ result = cc2cu(code);
goto fail;
}
uncpath = TRUE;
@@ -1095,7 +1118,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
/* no host for file: URLs by default */
Curl_dyn_reset(&host);
-#if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
+#if !defined(_WIN32) && !defined(MSDOS) && !defined(__CYGWIN__)
/* Don't allow Windows drive letters when not in Windows.
* This catches both "file:/c:" and "file:c:" */
if(('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) ||
@@ -1129,7 +1152,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
}
schemep = schemebuf;
- if(!Curl_builtin_scheme(schemep, CURL_ZERO_TERMINATED) &&
+ if(!Curl_get_scheme_handler(schemep) &&
!(flags & CURLU_NON_SUPPORT_SCHEME)) {
result = CURLUE_UNSUPPORTED_SCHEME;
goto fail;
@@ -1224,14 +1247,13 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if(flags & CURLU_URLENCODE) {
struct dynbuf enc;
Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
- if(urlencode_str(&enc, fragment + 1, fraglen, TRUE, FALSE)) {
- result = CURLUE_OUT_OF_MEMORY;
+ result = urlencode_str(&enc, fragment + 1, fraglen - 1, TRUE, FALSE);
+ if(result)
goto fail;
- }
u->fragment = Curl_dyn_ptr(&enc);
}
else {
- u->fragment = Curl_memdup(fragment + 1, fraglen);
+ u->fragment = Curl_memdup0(fragment + 1, fraglen - 1);
if(!u->fragment) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
@@ -1242,7 +1264,6 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
pathlen -= fraglen;
}
- DEBUGASSERT(pathlen < urllen);
query = memchr(path, '?', pathlen);
if(query) {
size_t qlen = fragment ? (size_t)(fragment - query) :
@@ -1253,19 +1274,17 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
struct dynbuf enc;
Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
/* skip the leading question mark */
- if(urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE)) {
- result = CURLUE_OUT_OF_MEMORY;
+ result = urlencode_str(&enc, query + 1, qlen - 1, TRUE, TRUE);
+ if(result)
goto fail;
- }
u->query = Curl_dyn_ptr(&enc);
}
else {
- u->query = Curl_memdup(query + 1, qlen);
+ u->query = Curl_memdup0(query + 1, qlen - 1);
if(!u->query) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
}
- u->query[qlen - 1] = 0;
}
}
else {
@@ -1281,10 +1300,9 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if(pathlen && (flags & CURLU_URLENCODE)) {
struct dynbuf enc;
Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
- if(urlencode_str(&enc, path, pathlen, TRUE, FALSE)) {
- result = CURLUE_OUT_OF_MEMORY;
+ result = urlencode_str(&enc, path, pathlen, TRUE, FALSE);
+ if(result)
goto fail;
- }
pathlen = Curl_dyn_len(&enc);
path = u->path = Curl_dyn_ptr(&enc);
}
@@ -1295,12 +1313,11 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
}
else {
if(!u->path) {
- u->path = Curl_memdup(path, pathlen + 1);
+ u->path = Curl_memdup0(path, pathlen);
if(!u->path) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
}
- u->path[pathlen] = 0;
path = u->path;
}
else if(flags & CURLU_URLENCODE)
@@ -1352,7 +1369,7 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u,
*/
CURLU *curl_url(void)
{
- return calloc(sizeof(struct Curl_URL), 1);
+ return calloc(1, sizeof(struct Curl_URL));
}
void curl_url_cleanup(CURLU *u)
@@ -1374,7 +1391,7 @@ void curl_url_cleanup(CURLU *u)
CURLU *curl_url_dup(const CURLU *in)
{
- struct Curl_URL *u = calloc(sizeof(struct Curl_URL), 1);
+ struct Curl_URL *u = calloc(1, sizeof(struct Curl_URL));
if(u) {
DUP(u, in, scheme);
DUP(u, in, user);
@@ -1447,8 +1464,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
if(!ptr && (flags & CURLU_DEFAULT_PORT) && u->scheme) {
/* there's no stored port number, but asked to deliver
a default one for the scheme */
- const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+ const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme);
if(h) {
msnprintf(portbuf, sizeof(portbuf), "%u", h->defport);
ptr = portbuf;
@@ -1457,8 +1473,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
else if(ptr && u->scheme) {
/* there is a stored port number, but ask to inhibit if
it matches the default one for the scheme */
- const struct Curl_handler *h =
- Curl_builtin_scheme(u->scheme, CURL_ZERO_TERMINATED);
+ const struct Curl_handler *h = Curl_get_scheme_handler(u->scheme);
if(h && (h->defport == u->portnum) &&
(flags & CURLU_NO_DEFAULT_PORT))
ptr = NULL;
@@ -1503,7 +1518,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
else
return CURLUE_NO_SCHEME;
- h = Curl_builtin_scheme(scheme, CURL_ZERO_TERMINATED);
+ h = Curl_get_scheme_handler(scheme);
if(!port && (flags & CURLU_DEFAULT_PORT)) {
/* there's no stored port number, but asked to deliver
a default one for the scheme */
@@ -1596,7 +1611,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
if(ptr) {
size_t partlen = strlen(ptr);
size_t i = 0;
- *part = Curl_memdup(ptr, partlen + 1);
+ *part = Curl_memdup0(ptr, partlen);
if(!*part)
return CURLUE_OUT_OF_MEMORY;
if(plusdecode) {
@@ -1623,10 +1638,11 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
}
if(urlencode) {
struct dynbuf enc;
+ CURLUcode uc;
Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
- if(urlencode_str(&enc, *part, partlen, TRUE,
- what == CURLUPART_QUERY))
- return CURLUE_OUT_OF_MEMORY;
+ uc = urlencode_str(&enc, *part, partlen, TRUE, what == CURLUPART_QUERY);
+ if(uc)
+ return uc;
free(*part);
*part = Curl_dyn_ptr(&enc);
}
@@ -1743,9 +1759,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if((plen > MAX_SCHEME_LEN) || (plen < 1))
/* too long or too short */
return CURLUE_BAD_SCHEME;
- if(!(flags & CURLU_NON_SUPPORT_SCHEME) &&
- /* verify that it is a fine scheme */
- !Curl_builtin_scheme(part, CURL_ZERO_TERMINATED))
+ /* verify that it is a fine scheme */
+ if(!(flags & CURLU_NON_SUPPORT_SCHEME) && !Curl_get_scheme_handler(part))
return CURLUE_UNSUPPORTED_SCHEME;
storep = &u->scheme;
urlencode = FALSE; /* never */
@@ -1812,7 +1827,8 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
* If the existing contents is enough for a URL, allow a relative URL to
* replace it.
*/
- CURLUcode result;
+ CURLcode result;
+ CURLUcode uc;
char *oldurl;
char *redired_url;
@@ -1832,14 +1848,14 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
/* apply the relative part to create a new URL
* and replace the existing one with it. */
- redired_url = concat_url(oldurl, part);
+ result = concat_url(oldurl, part, &redired_url);
free(oldurl);
- if(!redired_url)
- return CURLUE_OUT_OF_MEMORY;
+ if(result)
+ return cc2cu(result);
- result = parseurl_and_replace(redired_url, u, flags);
+ uc = parseurl_and_replace(redired_url, u, flags);
free(redired_url);
- return result;
+ return uc;
}
default:
return CURLUE_UNKNOWN_PART;
@@ -1853,7 +1869,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
if(leadingslash && (part[0] != '/')) {
CURLcode result = Curl_dyn_addn(&enc, "/", 1);
if(result)
- return CURLUE_OUT_OF_MEMORY;
+ return cc2cu(result);
}
if(urlencode) {
const unsigned char *i;
@@ -1873,7 +1889,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
equalsencode = FALSE;
result = Curl_dyn_addn(&enc, i, 1);
if(result)
- return CURLUE_OUT_OF_MEMORY;
+ return cc2cu(result);
}
else {
char out[3]={'%'};
@@ -1881,7 +1897,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
out[2] = hexdigits[*i & 0xf];
result = Curl_dyn_addn(&enc, out, 3);
if(result)
- return CURLUE_OUT_OF_MEMORY;
+ return cc2cu(result);
}
}
}
@@ -1889,7 +1905,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
char *p;
CURLcode result = Curl_dyn_add(&enc, part);
if(result)
- return CURLUE_OUT_OF_MEMORY;
+ return cc2cu(result);
p = Curl_dyn_ptr(&enc);
while(*p) {
/* make sure percent encoded are lower case */
@@ -1905,7 +1921,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
newp = Curl_dyn_ptr(&enc);
- if(appendquery) {
+ if(appendquery && newp) {
/* Append the 'newp' string onto the old query. Add a '&' separator if
none is present at the end of the existing query already */
@@ -1934,8 +1950,8 @@ nomem:
}
}
- if(what == CURLUPART_HOST) {
- size_t n = strlen(newp);
+ else if(what == CURLUPART_HOST) {
+ size_t n = Curl_dyn_len(&enc);
if(!n && (flags & CURLU_NO_AUTHORITY)) {
/* Skip hostname check, it's allowed to be empty. */
}
diff --git a/lib/urldata.h b/lib/urldata.h
index dff26e6b4..9dcccc703 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -266,6 +266,13 @@ typedef enum {
/* SSL backend-specific data; declared differently by each SSL backend */
struct ssl_backend_data;
+struct ssl_peer {
+ char *hostname; /* hostname for verification */
+ char *dispname; /* display version of hostname */
+ char *sni; /* SNI version of hostname or NULL if not usable */
+ BIT(is_ip_address); /* if hostname is an IPv4|6 address */
+};
+
struct ssl_primary_config {
char *CApath; /* certificate dir (doesn't work on windows) */
char *CAfile; /* certificate to verify peer against */
@@ -571,6 +578,13 @@ struct hostname {
#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
+/* transfer wants to send is not PAUSE or HOLD */
+#define CURL_WANT_SEND(data) \
+ (((data)->req.keepon & KEEP_SENDBITS) == KEEP_SEND)
+/* transfer receive is not on PAUSE or HOLD */
+#define CURL_WANT_RECV(data) \
+ (((data)->req.keepon & KEEP_RECVBITS) == KEEP_RECV)
+
#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
#define USE_CURL_ASYNC
struct Curl_async {
@@ -589,6 +603,15 @@ struct Curl_async {
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
+/* Polling requested by an easy handle.
+ * `action` is CURL_POLL_IN, CURL_POLL_OUT or CURL_POLL_INOUT.
+ */
+struct easy_pollset {
+ curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
+ unsigned int num;
+ unsigned char actions[MAX_SOCKSPEREASYHANDLE];
+};
+
enum expect100 {
EXP100_SEND_DATA, /* enough waiting, just send the body now */
EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */
@@ -649,16 +672,8 @@ struct SingleRequest {
counter to make only a 100 reply (without
a following second response code) result
in a CURLE_GOT_NOTHING error code */
- enum {
- HEADER_NORMAL, /* no bad header at all */
- HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
- is normal data */
- HEADER_ALLBAD /* all was believed to be header */
- } badheader; /* the header was deemed bad and will be
- written as body */
int headerline; /* counts header lines to better track the
first one */
- char *str; /* within buf */
curl_off_t offset; /* possible resume offset read from the
Content-Range: header */
int httpcode; /* error code from the 'HTTP/1.? XXX' or
@@ -668,8 +683,9 @@ struct SingleRequest {
enum expect100 exp100; /* expect 100 continue state */
enum upgrade101 upgr101; /* 101 upgrade state */
- /* Content unencoding stack. See sec 3.5, RFC2616. */
- struct contenc_writer *writer_stack;
+ /* Client Writer stack, handles trasnfer- and content-encodings, protocol
+ * checks, pausing by client callbacks. */
+ struct Curl_cwriter *writer_stack;
time_t timeofdoc;
long bodywrites;
char *location; /* This points to an allocated version of the Location:
@@ -706,16 +722,19 @@ struct SingleRequest {
#ifndef CURL_DISABLE_DOH
struct dohdata *doh; /* DoH specific data for this request */
#endif
-#if defined(WIN32) && defined(USE_WINSOCK)
+#if defined(_WIN32) && defined(USE_WINSOCK)
struct curltime last_sndbuf_update; /* last time readwrite_upload called
win_update_buffer_size */
#endif
+ char fread_eof[2]; /* the body read callback (index 0) returned EOF or
+ the trailer read callback (index 1) returned EOF */
#ifndef CURL_DISABLE_COOKIES
unsigned char setcookies;
#endif
- unsigned char writer_stack_depth; /* Unencoding stack depth. */
BIT(header); /* incoming data has HTTP header */
BIT(content_range); /* set TRUE if Content-Range: was found */
+ BIT(download_done); /* set to TRUE when download is complete */
+ BIT(eos_written); /* iff EOS has been written to client */
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
upload and we're uploading the last chunk */
BIT(ignorebody); /* we read a response-body but we ignore it! */
@@ -797,9 +816,10 @@ struct Curl_handler {
bool dead_connection);
/* If used, this function gets called from transfer.c:readwrite_data() to
- allow the protocol to do extra reads/writes */
- CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn,
- ssize_t *nread, bool *readmore);
+ allow the protocol to do extra handling in writing response to
+ the client. */
+ CURLcode (*write_resp)(struct Curl_easy *data, const char *buf, size_t blen,
+ bool is_eos, bool *done);
/* This function can perform various checks on the connection. See
CONNCHECK_* for more information about the checks that can be performed,
@@ -878,11 +898,6 @@ struct ldapconninfo;
struct connectdata {
struct Curl_llist_element bundle_node; /* conncache */
- /* chunk is for HTTP chunked encoding, but is in the general connectdata
- struct only because we can do just about any protocol through an HTTP
- proxy and an HTTP proxy may in fact respond using chunked encoding */
- struct Curl_chunker chunk;
-
curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
void *closesocket_client;
@@ -1005,11 +1020,6 @@ struct connectdata {
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif
-#ifndef CURL_DISABLE_HTTP
- /* for chunked-encoded trailer */
- struct dynbuf trailer;
-#endif
-
union {
#ifndef CURL_DISABLE_FTP
struct ftp_conn ftpc;
@@ -1080,7 +1090,6 @@ struct connectdata {
unsigned short localport;
unsigned short secondary_port; /* secondary socket remote port to connect to
(ftp) */
- unsigned char cselect_bits; /* bitmask of socket events */
unsigned char alpn; /* APLN TLS negotiated protocol, a CURL_HTTP_VERSION*
value */
#ifndef CURL_DISABLE_PROXY
@@ -1170,6 +1179,7 @@ struct Progress {
curl_off_t dlspeed;
curl_off_t ulspeed;
+ timediff_t t_postqueue;
timediff_t t_nslookup;
timediff_t t_connect;
timediff_t t_appconnect;
@@ -1325,7 +1335,8 @@ struct UrlState {
curl_off_t recent_conn_id; /* The most recent connection used, might no
* longer exist */
struct dynbuf headerb; /* buffer to store headers in */
-
+ struct curl_slist *hstslist; /* list of HSTS files set by
+ curl_easy_setopt(HSTS) calls */
char *buffer; /* download buffer */
char *ulbuf; /* allocated upload buffer or NULL */
curl_off_t current_speed; /* the ProgressShow() function sets this,
@@ -1373,7 +1384,7 @@ struct UrlState {
/* a place to store the most recently set (S)FTP entrypath */
char *most_recent_ftp_entrypath;
-#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__)
+#if !defined(_WIN32) && !defined(MSDOS) && !defined(__EMX__)
/* do FTP line-end conversions on most platforms */
#define CURL_DO_LINEEND_CONV
/* for FTP downloads: track CRLF sequences that span blocks */
@@ -1411,7 +1422,7 @@ struct UrlState {
this should be dealt with in pretransfer */
#ifndef CURL_DISABLE_HTTP
curl_mimepart *mimepost;
- curl_mimepart *formp; /* storage for old API form-posting, alloced on
+ curl_mimepart *formp; /* storage for old API form-posting, allocated on
demand */
size_t trailers_bytes_sent;
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
@@ -1422,6 +1433,10 @@ struct UrlState {
trailers_state trailers_state; /* whether we are sending trailers
and what stage are we at */
#endif
+#ifndef CURL_DISABLE_COOKIES
+ struct curl_slist *cookielist; /* list of cookie files set by
+ curl_easy_setopt(COOKIEFILE) calls */
+#endif
#ifdef USE_HYPER
bool hconnect; /* set if a CONNECT request */
CURLcode hresult; /* used to pass return codes back from hyper callbacks */
@@ -1454,7 +1469,7 @@ struct UrlState {
server involved in this request */
unsigned char httpreq; /* Curl_HttpReq; what kind of HTTP request (if any)
is this */
- unsigned char dselect_bits; /* != 0 -> bitmask of socket events for this
+ unsigned char select_bits; /* != 0 -> bitmask of socket events for this
transfer overriding anything the socket may
report */
#ifdef CURLDEBUG
@@ -1498,6 +1513,9 @@ struct UrlState {
though it will be discarded. We must call the data
rewind callback before trying to send again. */
BIT(upload); /* upload request */
+ BIT(internal); /* internal: true if this easy handle was created for
+ internal use and the user does not have ownership of the
+ handle. */
};
/*
@@ -1674,13 +1692,7 @@ struct UserDefined {
void *prereq_userp; /* pre-initial request user data */
void *seek_client; /* pointer to pass to the seek callback */
-#ifndef CURL_DISABLE_COOKIES
- struct curl_slist *cookielist; /* list of cookie files set by
- curl_easy_setopt(COOKIEFILE) calls */
-#endif
#ifndef CURL_DISABLE_HSTS
- struct curl_slist *hstslist; /* list of HSTS files set by
- curl_easy_setopt(HSTS) calls */
curl_hstsread_callback hsts_read;
void *hsts_read_userp;
curl_hstswrite_callback hsts_write;
@@ -1780,9 +1792,6 @@ struct UserDefined {
#endif
curl_prot_t allowed_protocols;
curl_prot_t redir_protocols;
-#ifndef CURL_DISABLE_MIME
- unsigned int mime_options; /* Mime option flags. */
-#endif
#ifndef CURL_DISABLE_RTSP
void *rtp_out; /* write RTP to this if non-NULL */
/* Common RTSP header options */
@@ -1805,8 +1814,6 @@ struct UserDefined {
int tcp_keepidle; /* seconds in idle before sending keepalive probe */
int tcp_keepintvl; /* seconds between TCP keepalive probes */
- size_t maxconnects; /* Max idle connections in the connection cache */
-
long expect_100_timeout; /* in milliseconds */
#if defined(USE_HTTP2) || defined(USE_HTTP3)
struct Curl_data_priority priority;
@@ -1831,10 +1838,14 @@ struct UserDefined {
BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
recipients */
#endif
+ unsigned int maxconnects; /* Max idle connections in the connection cache */
unsigned char use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or
IMAP or POP3 or others! (type: curl_usessl)*/
unsigned char connect_only; /* make connection/request, then let
application use the socket */
+#ifndef CURL_DISABLE_MIME
+ BIT(mime_formescape);
+#endif
BIT(is_fread_set); /* has read callback been set to non-NULL? */
#ifndef CURL_DISABLE_TFTP
BIT(tftp_no_options); /* do not send TFTP options requests */
@@ -1971,10 +1982,7 @@ struct Curl_easy {
particular order. Note that all sockets are added to the sockhash, where
the state etc are also kept. This array is mostly used to detect when a
socket is to be removed from the hash. See singlesocket(). */
- curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE];
- unsigned char actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in
- sockets[] */
- int numsocks;
+ struct easy_pollset last_poll;
struct Names dns;
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
@@ -2013,10 +2021,6 @@ struct Curl_easy {
#ifdef USE_HYPER
struct hyptransfer hyp;
#endif
-
- /* internal: true if this easy handle was created for internal use and the
- user does not have ownership of the handle. */
- bool internal;
};
#define LIBCURL_NAME "libcurl"
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index 12c6f7dd5..416da0fcc 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -125,7 +125,6 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content,
}
else
return FALSE;
- break;
}
}
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index 02e36ea5e..4696f29ad 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -211,8 +211,10 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
infof(data, "schannel: InitializeSecurityContext failed: %s",
Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+#endif
return CURLE_AUTH_ERROR;
}
@@ -603,8 +605,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
if(status == SEC_E_INSUFFICIENT_MEMORY)
return CURLE_OUT_OF_MEMORY;
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
infof(data, "schannel: InitializeSecurityContext failed: %s",
Curl_sspi_strerror(status, buffer, sizeof(buffer)));
+#endif
return CURLE_AUTH_ERROR;
}
diff --git a/lib/vauth/krb5_gssapi.c b/lib/vauth/krb5_gssapi.c
index 65eb3e1b5..16b6e4037 100644
--- a/lib/vauth/krb5_gssapi.c
+++ b/lib/vauth/krb5_gssapi.c
@@ -226,7 +226,8 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
/* Extract the security layer and the maximum message size */
indata = output_token.value;
sec_layer = indata[0];
- max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3];
+ max_size = ((unsigned int)indata[1] << 16) |
+ ((unsigned int)indata[2] << 8) | indata[3];
/* Free the challenge as it is not required anymore */
gss_release_buffer(&unused_status, &output_token);
diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c
index c487149b9..17a517a97 100644
--- a/lib/vauth/krb5_sspi.c
+++ b/lib/vauth/krb5_sspi.c
@@ -319,7 +319,8 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
/* Extract the security layer and the maximum message size */
indata = input_buf[1].pvBuffer;
sec_layer = indata[0];
- max_size = (indata[1] << 16) | (indata[2] << 8) | indata[3];
+ max_size = ((unsigned long)indata[1] << 16) |
+ ((unsigned long)indata[2] << 8) | indata[3];
/* Free the challenge as it is not required anymore */
s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index ed7cee8de..018e6a67e 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -44,6 +44,7 @@
#include "warnless.h"
#include "rand.h"
#include "vtls/vtls.h"
+#include "strdup.h"
#define BUILDING_CURL_NTLM_MSGS_C
#include "vauth/vauth.h"
@@ -184,11 +185,10 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
}
free(ntlm->target_info); /* replace any previous data */
- ntlm->target_info = malloc(target_info_len);
+ ntlm->target_info = Curl_memdup(&type2[target_info_offset],
+ target_info_len);
if(!ntlm->target_info)
return CURLE_OUT_OF_MEMORY;
-
- memcpy(ntlm->target_info, &type2[target_info_offset], target_info_len);
}
}
diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c
index 5118963f4..92054316d 100644
--- a/lib/vauth/ntlm_sspi.c
+++ b/lib/vauth/ntlm_sspi.c
@@ -34,6 +34,7 @@
#include "warnless.h"
#include "curl_multibyte.h"
#include "sendf.h"
+#include "strdup.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -213,11 +214,10 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
}
/* Store the challenge for later use */
- ntlm->input_token = malloc(Curl_bufref_len(type2) + 1);
+ ntlm->input_token = Curl_memdup0((const char *)Curl_bufref_ptr(type2),
+ Curl_bufref_len(type2));
if(!ntlm->input_token)
return CURLE_OUT_OF_MEMORY;
- memcpy(ntlm->input_token, Curl_bufref_ptr(type2), Curl_bufref_len(type2));
- ntlm->input_token[Curl_bufref_len(type2)] = '\0';
ntlm->input_token_len = Curl_bufref_len(type2);
return CURLE_OK;
@@ -314,7 +314,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
&type_3_desc,
&attrs, &expiry);
if(status != SEC_E_OK) {
- infof(data, "NTLM handshake failure (type-3 message): Status=%x",
+ infof(data, "NTLM handshake failure (type-3 message): Status=%lx",
status);
if(status == SEC_E_INSUFFICIENT_MEMORY)
diff --git a/lib/version.c b/lib/version.c
index 47304259e..01c2a315e 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -39,7 +39,7 @@
#ifdef USE_ARES
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- defined(WIN32)
+ defined(_WIN32)
# define CARES_STATICLIB
# endif
# include <ares.h>
@@ -211,8 +211,12 @@ char *curl_version(void)
#endif
#ifdef USE_LIBPSL
- msnprintf(psl_version, sizeof(psl_version), "libpsl/%s", psl_get_version());
- src[i++] = psl_version;
+ {
+ int num = psl_check_version_number(0);
+ msnprintf(psl_version, sizeof(psl_version), "libpsl/%d.%d.%d",
+ num >> 16, (num >> 8) & 0xff, num & 0xff);
+ src[i++] = psl_version;
+ }
#endif
#ifdef USE_SSH
@@ -409,7 +413,8 @@ static int idn_present(curl_version_info_data *info)
#define idn_present NULL
#endif
-#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
+ !defined(CURL_DISABLE_HTTP)
static int https_proxy_present(curl_version_info_data *info)
{
(void) info;
@@ -454,13 +459,14 @@ static const struct feat features_table[] = {
#ifndef CURL_DISABLE_HSTS
FEATURE("HSTS", NULL, CURL_VERSION_HSTS),
#endif
-#if defined(USE_NGHTTP2) || defined(USE_HYPER)
+#if defined(USE_NGHTTP2)
FEATURE("HTTP2", NULL, CURL_VERSION_HTTP2),
#endif
#if defined(ENABLE_QUIC)
FEATURE("HTTP3", NULL, CURL_VERSION_HTTP3),
#endif
-#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
+#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) && \
+ !defined(CURL_DISABLE_HTTP)
FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
#endif
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
@@ -510,7 +516,7 @@ static const struct feat features_table[] = {
#ifdef CURLDEBUG
FEATURE("TrackMemory", NULL, CURL_VERSION_CURLDEBUG),
#endif
-#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
+#if defined(_WIN32) && defined(UNICODE) && defined(_UNICODE)
FEATURE("Unicode", NULL, CURL_VERSION_UNICODE),
#endif
#ifdef USE_UNIX_SOCKETS
diff --git a/lib/version_win32.c b/lib/version_win32.c
index 872d5b4f3..e0f239e15 100644
--- a/lib/version_win32.c
+++ b/lib/version_win32.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
#include <curl/curl.h>
#include "version_win32.h"
@@ -316,4 +316,4 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
return matched;
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
diff --git a/lib/version_win32.h b/lib/version_win32.h
index 3899174a3..95c066112 100644
--- a/lib/version_win32.h
+++ b/lib/version_win32.h
@@ -26,7 +26,7 @@
#include "curl_setup.h"
-#if defined(WIN32)
+#if defined(_WIN32)
/* Version condition */
typedef enum {
@@ -51,6 +51,6 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
const PlatformIdentifier platform,
const VersionCondition condition);
-#endif /* WIN32 */
+#endif /* _WIN32 */
#endif /* HEADER_CURL_VERSION_WIN32_H */
diff --git a/lib/vquic/curl_msh3.c b/lib/vquic/curl_msh3.c
index 6bd0d2331..7674bc1fc 100644
--- a/lib/vquic/curl_msh3.c
+++ b/lib/vquic/curl_msh3.c
@@ -38,6 +38,7 @@
#include "http1.h"
#include "curl_msh3.h"
#include "socketpair.h"
+#include "vtls/vtls.h"
#include "vquic/vquic.h"
/* The last 3 #include files should be in this order */
@@ -45,6 +46,10 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifdef CURL_DISABLE_SOCKETPAIR
+#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set"
+#endif
+
#define H3_STREAM_WINDOW_SIZE (128 * 1024)
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
#define H3_STREAM_RECV_CHUNKS \
@@ -199,8 +204,8 @@ static void drain_stream_from_other_thread(struct Curl_easy *data,
bits = CURL_CSELECT_IN;
if(stream && !stream->upload_done)
bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- data->state.dselect_bits = bits;
+ if(data->state.select_bits != bits) {
+ data->state.select_bits = bits;
/* cannot expire from other thread */
}
}
@@ -215,8 +220,8 @@ static void drain_stream(struct Curl_cfilter *cf,
bits = CURL_CSELECT_IN;
if(stream && !stream->upload_done)
bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- data->state.dselect_bits = bits;
+ if(data->state.select_bits != bits) {
+ data->state.select_bits = bits;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
@@ -672,31 +677,25 @@ out:
return nwritten;
}
-static int cf_msh3_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_msh3_ctx *ctx = cf->ctx;
struct stream_ctx *stream = H3_STREAM_CTX(data);
- int bitmap = GETSOCK_BLANK;
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
if(stream && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) {
- socks[0] = ctx->sock[SP_LOCAL];
-
if(stream->recv_error) {
- bitmap |= GETSOCK_READSOCK(0);
+ Curl_pollset_add_in(data, ps, ctx->sock[SP_LOCAL]);
drain_stream(cf, data);
}
else if(stream->req) {
- bitmap |= GETSOCK_READSOCK(0);
+ Curl_pollset_add_out(data, ps, ctx->sock[SP_LOCAL]);
drain_stream(cf, data);
}
}
- CURL_TRC_CF(data, cf, "select_sock -> %d", bitmap);
- CF_DATA_RESTORE(cf, save);
- return bitmap;
}
static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
@@ -802,14 +801,20 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- bool verify = !!cf->conn->ssl_config.verifypeer;
+ struct ssl_primary_config *conn_config;
MSH3_ADDR addr = {0};
CURLcode result;
+ bool verify;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+ verify = !!conn_config->verifypeer;
memcpy(&addr, &ctx->addr.sa_addr, ctx->addr.addrlen);
MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
- if(verify && (cf->conn->ssl_config.CAfile || cf->conn->ssl_config.CApath)) {
+ if(verify && (conn_config->CAfile || conn_config->CApath)) {
/* TODO: need a way to provide trust anchors to MSH3 */
#ifdef DEBUGBUILD
/* we need this for our test cases to run */
@@ -1025,7 +1030,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_msh3_connect,
cf_msh3_close,
Curl_cf_def_get_host,
- cf_msh3_get_select_socks,
+ cf_msh3_adjust_pollset,
cf_msh3_data_pending,
cf_msh3_send,
cf_msh3_recv,
@@ -1047,7 +1052,7 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
(void)ai; /* TODO: msh3 resolves itself? */
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c
index 7d681e585..a26b3e429 100644
--- a/lib/vquic/curl_ngtcp2.c
+++ b/lib/vquic/curl_ngtcp2.c
@@ -41,7 +41,6 @@
#include "vtls/gtls.h"
#elif defined(USE_WOLFSSL)
#include <ngtcp2/ngtcp2_crypto_wolfssl.h>
-#include "vtls/wolfssl.h"
#endif
#include "urldata.h"
@@ -61,6 +60,7 @@
#include "inet_pton.h"
#include "vquic.h"
#include "vquic_int.h"
+#include "vquic-tls.h"
#include "vtls/keylog.h"
#include "vtls/vtls.h"
#include "curl_ngtcp2.h"
@@ -73,12 +73,8 @@
#include "memdebug.h"
-#define H3_ALPN_H3_29 "\x5h3-29"
-#define H3_ALPN_H3 "\x2h3"
-
#define QUIC_MAX_STREAMS (256*1024)
#define QUIC_MAX_DATA (1*1024*1024)
-#define QUIC_IDLE_TIMEOUT (60*NGTCP2_SECONDS)
#define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS)
/* A stream window is the maximum amount we need to buffer for
@@ -102,25 +98,6 @@
(H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
-#ifdef USE_OPENSSL
-#define QUIC_CIPHERS \
- "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
- "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
-#define QUIC_GROUPS "P-256:X25519:P-384:P-521"
-#elif defined(USE_GNUTLS)
-#define QUIC_PRIORITY \
- "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
- "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
- "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
- "%DISABLE_TLS13_COMPAT_MODE"
-#elif defined(USE_WOLFSSL)
-#define QUIC_CIPHERS \
- "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
- "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
-#define QUIC_GROUPS "P-256:P-384:P-521"
-#endif
-
-
/*
* Store ngtcp2 version info in this buffer.
*/
@@ -134,6 +111,8 @@ void Curl_ngtcp2_ver(char *p, size_t len)
struct cf_ngtcp2_ctx {
struct cf_quic_ctx q;
+ struct ssl_peer peer;
+ struct quic_tls_ctx tls;
ngtcp2_path connected_path;
ngtcp2_conn *qconn;
ngtcp2_cid dcid;
@@ -143,29 +122,16 @@ struct cf_ngtcp2_ctx {
ngtcp2_transport_params transport_params;
ngtcp2_ccerr last_error;
ngtcp2_crypto_conn_ref conn_ref;
-#ifdef USE_OPENSSL
- SSL_CTX *sslctx;
- SSL *ssl;
-#elif defined(USE_GNUTLS)
- struct gtls_instance *gtls;
-#elif defined(USE_WOLFSSL)
- WOLFSSL_CTX *sslctx;
- WOLFSSL *ssl;
-#endif
struct cf_call_data call_data;
nghttp3_conn *h3conn;
nghttp3_settings h3settings;
struct curltime started_at; /* time the current attempt started */
struct curltime handshake_at; /* time connect handshake finished */
- struct curltime first_byte_at; /* when first byte was recvd */
struct curltime reconnect_at; /* time the next attempt should start */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
size_t max_stream_window; /* max flow window for one stream */
+ uint64_t max_idle_ms; /* max idle time for QUIC connection */
int qlogfd;
- BIT(got_first_byte); /* if first byte was received */
-#ifdef USE_OPENSSL
- BIT(x509_store_setup); /* if x509 store has been set up */
-#endif
};
/* How to access `call_data` from a cf_ngtcp2 filter */
@@ -191,6 +157,7 @@ struct h3_stream_ctx {
bool closed; /* TRUE on stream close */
bool reset; /* TRUE on stream reset */
bool send_closed; /* stream is local closed */
+ BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
};
#define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \
@@ -236,11 +203,21 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
(void)cf;
if(stream) {
CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
+ if(ctx->h3conn && !stream->closed) {
+ nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream->id);
+ nghttp3_conn_close_stream(ctx->h3conn, stream->id,
+ NGHTTP3_H3_REQUEST_CANCELLED);
+ nghttp3_conn_set_stream_user_data(ctx->h3conn, stream->id, NULL);
+ ngtcp2_conn_set_stream_user_data(ctx->qconn, stream->id, NULL);
+ stream->closed = TRUE;
+ }
+
Curl_bufq_free(&stream->sendbuf);
Curl_bufq_free(&stream->recvbuf);
Curl_h1_req_parse_free(&stream->h1);
@@ -249,6 +226,43 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
+static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int64_t stream_id)
+{
+ struct Curl_easy *sdata;
+
+ (void)cf;
+ if(H3_STREAM_ID(data) == stream_id) {
+ return data;
+ }
+ else {
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream_id) {
+ return sdata;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void h3_drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(stream && stream->upload_left && !stream->send_closed)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.select_bits != bits) {
+ data->state.select_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
/* ngtcp2 default congestion controller does not perform pacing. Limit
the maximum packet burst to MAX_PKT_BURST packets. */
#define MAX_PKT_BURST 10
@@ -261,10 +275,14 @@ struct pkt_io_ctx {
ngtcp2_path_storage ps;
};
-static ngtcp2_tstamp timestamp(void)
+static void pktx_update_time(struct pkt_io_ctx *pktx,
+ struct Curl_cfilter *cf)
{
- struct curltime ct = Curl_now();
- return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+
+ vquic_ctx_update_time(&ctx->q);
+ pktx->ts = ctx->q.last_op.tv_sec * NGTCP2_SECONDS +
+ ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS;
}
static void pktx_init(struct pkt_io_ctx *pktx,
@@ -273,9 +291,9 @@ static void pktx_init(struct pkt_io_ctx *pktx,
{
pktx->cf = cf;
pktx->data = data;
- pktx->ts = timestamp();
pktx->pkt_count = 0;
ngtcp2_path_storage_zero(&pktx->ps);
+ pktx_update_time(pktx, cf);
}
static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
@@ -354,383 +372,14 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx,
t->initial_max_stream_data_uni = ctx->max_stream_window;
t->initial_max_streams_bidi = QUIC_MAX_STREAMS;
t->initial_max_streams_uni = QUIC_MAX_STREAMS;
- t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
+ t->max_idle_timeout = (ctx->max_idle_ms * NGTCP2_MILLISECONDS);
if(ctx->qlogfd != -1) {
s->qlog_write = qlog_callback;
}
}
-#ifdef USE_OPENSSL
-static void keylog_callback(const SSL *ssl, const char *line)
-{
- (void)ssl;
- Curl_tls_keylog_write_line(line);
-}
-#elif defined(USE_GNUTLS)
-static int keylog_callback(gnutls_session_t session, const char *label,
- const gnutls_datum_t *secret)
-{
- gnutls_datum_t crandom;
- gnutls_datum_t srandom;
-
- gnutls_session_get_random(session, &crandom, &srandom);
- if(crandom.size != 32) {
- return -1;
- }
-
- Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
- return 0;
-}
-#elif defined(USE_WOLFSSL)
-#if defined(HAVE_SECRET_CALLBACK)
-static void keylog_callback(const WOLFSSL *ssl, const char *line)
-{
- (void)ssl;
- Curl_tls_keylog_write_line(line);
-}
-#endif
-#endif
-
static int init_ngh3_conn(struct Curl_cfilter *cf);
-#ifdef USE_OPENSSL
-static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
- struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct connectdata *conn = cf->conn;
- CURLcode result = CURLE_FAILED_INIT;
- SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
-
- if(!ssl_ctx) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
-#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
- if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
- failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
- goto out;
- }
-#else
- if(ngtcp2_crypto_quictls_configure_client_context(ssl_ctx) != 0) {
- failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
- goto out;
- }
-#endif
-
- SSL_CTX_set_default_verify_paths(ssl_ctx);
-
- {
- const char *curves = conn->ssl_config.curves ?
- conn->ssl_config.curves : QUIC_GROUPS;
- if(!SSL_CTX_set1_curves_list(ssl_ctx, curves)) {
- failf(data, "failed setting curves list for QUIC: '%s'", curves);
- return CURLE_SSL_CIPHER;
- }
- }
-
-#ifndef OPENSSL_IS_BORINGSSL
- {
- const char *ciphers13 = conn->ssl_config.cipher_list13 ?
- conn->ssl_config.cipher_list13 : QUIC_CIPHERS;
- if(SSL_CTX_set_ciphersuites(ssl_ctx, ciphers13) != 1) {
- failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
- return CURLE_SSL_CIPHER;
- }
- infof(data, "QUIC cipher selection: %s", ciphers13);
- }
-#endif
-
- /* 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);
- }
-
- /* OpenSSL always tries to verify the peer, this only says whether it should
- * fail to connect if the verification fails, or if it should continue
- * anyway. In the latter case the result of the verification is checked with
- * SSL_get_verify_result() below. */
- SSL_CTX_set_verify(ssl_ctx, conn->ssl_config.verifypeer ?
- SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
-
- /* give application a chance to interfere with SSL set up. */
- if(data->set.ssl.fsslctx) {
- /* When a user callback is installed to modify the SSL_CTX,
- * we need to do the full initialization before calling it.
- * See: #11800 */
- if(!ctx->x509_store_setup) {
- result = Curl_ssl_setup_x509_store(cf, data, ssl_ctx);
- if(result)
- goto out;
- ctx->x509_store_setup = TRUE;
- }
- Curl_set_in_callback(data, true);
- result = (*data->set.ssl.fsslctx)(data, ssl_ctx,
- data->set.ssl.fsslctxp);
- Curl_set_in_callback(data, false);
- if(result) {
- failf(data, "error signaled by ssl ctx callback");
- goto out;
- }
- }
- result = CURLE_OK;
-
-out:
- *pssl_ctx = result? NULL : ssl_ctx;
- if(result && ssl_ctx)
- SSL_CTX_free(ssl_ctx);
- return result;
-}
-
-static CURLcode quic_set_client_cert(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_ngtcp2_ctx *ctx = cf->ctx;
- SSL_CTX *ssl_ctx = ctx->sslctx;
- const struct ssl_config_data *ssl_config;
-
- ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET);
- DEBUGASSERT(ssl_config);
-
- if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob
- || ssl_config->cert_type) {
- return Curl_ossl_set_client_cert(
- data, ssl_ctx, ssl_config->primary.clientcert,
- ssl_config->primary.cert_blob, ssl_config->cert_type,
- ssl_config->key, ssl_config->key_blob,
- ssl_config->key_type, ssl_config->key_passwd);
- }
-
- return CURLE_OK;
-}
-
-/** SSL callbacks ***/
-
-static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_ngtcp2_ctx *ctx = cf->ctx;
- const uint8_t *alpn = NULL;
- size_t alpnlen = 0;
- unsigned char checkip[16];
-
- DEBUGASSERT(!ctx->ssl);
- ctx->ssl = SSL_new(ctx->sslctx);
-
- SSL_set_app_data(ctx->ssl, &ctx->conn_ref);
- SSL_set_connect_state(ctx->ssl);
- SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
-
- alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
- alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
- if(alpn)
- SSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
-
- /* set SNI */
- if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
-#ifdef ENABLE_IPV6
- && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
-#endif
- ) {
- char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
- if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
- failf(data, "Failed set SNI");
- SSL_free(ctx->ssl);
- ctx->ssl = NULL;
- return CURLE_QUIC_CONNECT_ERROR;
- }
- }
- return CURLE_OK;
-}
-#elif defined(USE_GNUTLS)
-static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_ngtcp2_ctx *ctx = cf->ctx;
- CURLcode result;
- gnutls_datum_t alpn[2];
- /* this will need some attention when HTTPS proxy over QUIC get fixed */
- const char * const hostname = cf->conn->host.name;
- long * const pverifyresult = &data->set.ssl.certverifyresult;
- int rc;
-
- DEBUGASSERT(ctx->gtls == NULL);
- ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
- if(!ctx->gtls)
- return CURLE_OUT_OF_MEMORY;
-
- result = gtls_client_init(data, &cf->conn->ssl_config, &data->set.ssl,
- hostname, ctx->gtls, pverifyresult);
- if(result)
- return result;
-
- gnutls_session_set_ptr(ctx->gtls->session, &ctx->conn_ref);
-
- if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
- CURL_TRC_CF(data, cf,
- "ngtcp2_crypto_gnutls_configure_client_session failed\n");
- return CURLE_QUIC_CONNECT_ERROR;
- }
-
- rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
- if(rc < 0) {
- CURL_TRC_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
- gnutls_strerror(rc));
- return CURLE_QUIC_CONNECT_ERROR;
- }
-
- /* 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(ctx->gtls->session, keylog_callback);
- }
-
- /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
- alpn[0].data = (unsigned char *)H3_ALPN_H3_29 + 1;
- alpn[0].size = sizeof(H3_ALPN_H3_29) - 2;
- alpn[1].data = (unsigned char *)H3_ALPN_H3 + 1;
- alpn[1].size = sizeof(H3_ALPN_H3) - 2;
-
- gnutls_alpn_set_protocols(ctx->gtls->session,
- alpn, 2, GNUTLS_ALPN_MANDATORY);
- return CURLE_OK;
-}
-#elif defined(USE_WOLFSSL)
-
-static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
- struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- struct connectdata *conn = cf->conn;
- CURLcode result = CURLE_FAILED_INIT;
- WOLFSSL_CTX *ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
-
- if(!ssl_ctx) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- if(ngtcp2_crypto_wolfssl_configure_client_context(ssl_ctx) != 0) {
- failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
- goto out;
- }
-
- wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
-
- if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn->ssl_config.cipher_list13 ?
- conn->ssl_config.cipher_list13 :
- QUIC_CIPHERS) != 1) {
- char error_buffer[256];
- ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
- failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
- goto out;
- }
-
- if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn->ssl_config.curves ?
- conn->ssl_config.curves :
- (char *)QUIC_GROUPS) != 1) {
- failf(data, "wolfSSL failed to set curves");
- goto out;
- }
-
- /* Open the file if a TLS or QUIC backend has not done this before. */
- Curl_tls_keylog_open();
- if(Curl_tls_keylog_enabled()) {
-#if defined(HAVE_SECRET_CALLBACK)
- wolfSSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
-#else
- failf(data, "wolfSSL was built without keylog callback");
- goto out;
-#endif
- }
-
- if(conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = conn->ssl_config.CAfile;
- const char * const ssl_capath = conn->ssl_config.CApath;
-
- wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
- if(ssl_cafile || ssl_capath) {
- /* tell wolfSSL where to find CA certificates that are used to verify
- the server's certificate. */
- int rc =
- wolfSSL_CTX_load_verify_locations_ex(ssl_ctx, ssl_cafile, ssl_capath,
- WOLFSSL_LOAD_FLAG_IGNORE_ERR);
- if(SSL_SUCCESS != rc) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- goto out;
- }
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
- }
-#ifdef CURL_CA_FALLBACK
- else {
- /* verifying the peer without any CA certificates won't work so
- use wolfssl's built-in default as fallback */
- wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
- }
-#endif
- }
- else {
- wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
- }
-
- /* give application a chance to interfere with SSL set up. */
- if(data->set.ssl.fsslctx) {
- Curl_set_in_callback(data, true);
- result = (*data->set.ssl.fsslctx)(data, ssl_ctx,
- data->set.ssl.fsslctxp);
- Curl_set_in_callback(data, false);
- if(result) {
- failf(data, "error signaled by ssl ctx callback");
- goto out;
- }
- }
- result = CURLE_OK;
-
-out:
- *pssl_ctx = result? NULL : ssl_ctx;
- if(result && ssl_ctx)
- SSL_CTX_free(ssl_ctx);
- return result;
-}
-
-/** SSL callbacks ***/
-
-static CURLcode quic_init_ssl(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_ngtcp2_ctx *ctx = cf->ctx;
- const uint8_t *alpn = NULL;
- size_t alpnlen = 0;
- /* this will need some attention when HTTPS proxy over QUIC get fixed */
- const char * const hostname = cf->conn->host.name;
-
- (void)data;
- DEBUGASSERT(!ctx->ssl);
- ctx->ssl = wolfSSL_new(ctx->sslctx);
-
- wolfSSL_set_app_data(ctx->ssl, &ctx->conn_ref);
- wolfSSL_set_connect_state(ctx->ssl);
- wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
-
- alpn = (const uint8_t *)H3_ALPN_H3_29 H3_ALPN_H3;
- alpnlen = sizeof(H3_ALPN_H3_29) - 1 + sizeof(H3_ALPN_H3) - 1;
- if(alpn)
- wolfSSL_set_alpn_protos(ctx->ssl, alpn, (int)alpnlen);
-
- /* set SNI */
- wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
- hostname, (unsigned short)strlen(hostname));
-
- return CURLE_OK;
-}
-#endif /* defined(USE_WOLFSSL) */
-
static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
(void)user_data;
@@ -786,6 +435,12 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
CURL_TRC_CF(data, cf, "[%" PRId64 "] read_stream(len=%zu) -> %zd",
stream_id, buflen, nconsumed);
if(nconsumed < 0) {
+ if(!data) {
+ struct Curl_easy *cdata = CF_DATA_CURRENT(cf);
+ CURL_TRC_CF(cdata, cf, "[%" PRId64 "] nghttp3 error on stream not "
+ "used by us, ignored", stream_id);
+ return 0;
+ }
ngtcp2_ccerr_set_application_error(
&ctx->last_error,
nghttp3_err_infer_quic_app_error_code((int)nconsumed), NULL, 0);
@@ -816,7 +471,7 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
rv = nghttp3_conn_add_ack_offset(ctx->h3conn, stream_id, datalen);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -844,7 +499,7 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
app_error_code);
CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(err=%"
PRIu64 ") -> %d", stream3_id, app_error_code, rv);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
ngtcp2_ccerr_set_application_error(
&ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
return NGTCP2_ERR_CALLBACK_FAILURE;
@@ -868,7 +523,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -887,7 +542,7 @@ static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -911,16 +566,25 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
{
struct Curl_cfilter *cf = user_data;
struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ struct Curl_easy *s_data;
+ struct h3_stream_ctx *stream;
int rv;
(void)tconn;
(void)max_data;
(void)stream_user_data;
rv = nghttp3_conn_unblock_stream(ctx->h3conn, stream_id);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
-
+ s_data = get_stream_easy(cf, data, stream_id);
+ stream = H3_STREAM_CTX(s_data);
+ if(stream && stream->quic_flow_blocked) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] unblock quic flow", stream_id);
+ stream->quic_flow_blocked = FALSE;
+ h3_drain_stream(cf, data);
+ }
return 0;
}
@@ -1038,7 +702,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
pktx = &local_pktx;
}
else {
- pktx->ts = timestamp();
+ pktx_update_time(pktx, cf);
}
expiry = ngtcp2_conn_get_expiry(ctx->qconn);
@@ -1073,46 +737,33 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
+static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct SingleRequest *k = &data->req;
- int rv = GETSOCK_BLANK;
- struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
- struct cf_call_data save;
-
- CF_DATA_SAVE(save, cf, data);
- socks[0] = ctx->q.sockfd;
-
- /* in HTTP/3 we can always get a frame, so check read */
- rv |= GETSOCK_READSOCK(0);
+ bool want_recv, want_send;
- /* we're still uploading or the HTTP/2 layer wants to send data */
- if((k->keepon & KEEP_SENDBITS) == KEEP_SEND &&
- ngtcp2_conn_get_cwnd_left(ctx->qconn) &&
- ngtcp2_conn_get_max_data_left(ctx->qconn) &&
- stream && nghttp3_conn_is_stream_writable(ctx->h3conn, stream->id))
- rv |= GETSOCK_WRITESOCK(0);
-
- CF_DATA_RESTORE(cf, save);
- return rv;
-}
+ if(!ctx->qconn)
+ return;
-static void h3_drain_stream(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
- unsigned char bits;
+ Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+ if(want_recv || want_send) {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cf_call_data save;
+ bool c_exhaust, s_exhaust;
- (void)cf;
- bits = CURL_CSELECT_IN;
- if(stream && stream->upload_left && !stream->send_closed)
- bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- data->state.dselect_bits = bits;
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ CF_DATA_SAVE(save, cf, data);
+ c_exhaust = want_send && (!ngtcp2_conn_get_cwnd_left(ctx->qconn) ||
+ !ngtcp2_conn_get_max_data_left(ctx->qconn));
+ s_exhaust = want_send && stream && stream->id >= 0 &&
+ stream->quic_flow_blocked;
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ !Curl_bufq_is_empty(&ctx->q.sendbuf);
+
+ Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+ CF_DATA_RESTORE(cf, save);
}
}
@@ -1141,7 +792,6 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
else {
CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id);
}
- data->req.keepon &= ~KEEP_SEND_HOLD;
h3_drain_stream(cf, data);
return 0;
}
@@ -1570,15 +1220,9 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
/* Everything ACKed, we resume upload processing */
if(!stream->sendbuf_len_in_flight) {
int rv = nghttp3_conn_resume_stream(conn, stream_id);
- if(rv) {
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
- if((data->req.keepon & KEEP_SEND_HOLD) &&
- (data->req.keepon & KEEP_SEND)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- h3_drain_stream(cf, data);
- CURL_TRC_CF(data, cf, "[%" PRId64 "] unpausing acks", stream_id);
- }
}
return 0;
}
@@ -1676,6 +1320,10 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
goto out;
stream = H3_STREAM_CTX(data);
DEBUGASSERT(stream);
+ if(!stream) {
+ *err = CURLE_FAILED_INIT;
+ goto out;
+ }
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
if(nwritten < 0)
@@ -1711,7 +1359,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
nva[i].flags = NGHTTP3_NV_FLAG_NONE;
}
- rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL);
+ rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, data);
if(rc) {
failf(data, "can get bidi streams");
*err = CURLE_SEND_ERROR;
@@ -1835,6 +1483,8 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
sent = (ssize_t)len;
goto out;
}
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+ "-> stream closed", stream->id, len);
*err = CURLE_HTTP3;
sent = -1;
goto out;
@@ -1860,15 +1510,13 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
if(stream && sent > 0 && stream->sendbuf_len_in_flight) {
/* We have unacknowledged DATA and cannot report success to our
* caller. Instead we EAGAIN and remember how much we have already
- * "written" into our various internal connection buffers.
- * We put the stream upload on HOLD, until this gets ACKed. */
+ * "written" into our various internal connection buffers. */
stream->upload_blocked_len = sent;
CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), "
"%zu bytes in flight -> EGAIN", stream->id, len,
stream->sendbuf_len_in_flight);
*err = CURLE_AGAIN;
sent = -1;
- data->req.keepon |= KEEP_SEND_HOLD;
}
out:
@@ -1887,52 +1535,12 @@ static CURLcode qng_verify_peer(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- CURLcode result = CURLE_OK;
- const char *hostname, *disp_hostname;
- int port;
- char *snihost;
-
- Curl_conn_get_host(data, cf->sockindex, &hostname, &disp_hostname, &port);
- snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost)
- return CURLE_PEER_FAILED_VERIFICATION;
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
cf->conn->httpversion = 30;
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
- if(cf->conn->ssl_config.verifyhost) {
-#ifdef USE_OPENSSL
- X509 *server_cert;
- server_cert = SSL_get_peer_certificate(ctx->ssl);
- if(!server_cert) {
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
- X509_free(server_cert);
- if(result)
- return result;
-#elif defined(USE_GNUTLS)
- result = Curl_gtls_verifyserver(data, ctx->gtls->session,
- &cf->conn->ssl_config, &data->set.ssl,
- hostname, disp_hostname,
- data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
- if(result)
- return result;
-#elif defined(USE_WOLFSSL)
- if(wolfSSL_check_domain_name(ctx->ssl, snihost) == SSL_FAILURE)
- return CURLE_PEER_FAILED_VERIFICATION;
-#endif
- infof(data, "Verified certificate just fine");
- }
- else
- infof(data, "Skipped certificate verification");
-#ifdef USE_OPENSSL
- if(data->set.ssl.certinfo)
- /* asked to gather certificate info */
- (void)Curl_ossl_certchain(data, ctx->ssl);
-#endif
- return result;
+ return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
}
static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
@@ -1955,8 +1563,8 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts);
if(rv) {
- CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s",
- ngtcp2_strerror(rv));
+ CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s (%d)",
+ ngtcp2_strerror(rv), rv);
if(!ctx->last_error.error_code) {
if(rv == NGTCP2_ERR_CRYPTO) {
ngtcp2_ccerr_set_tls_alert(&ctx->last_error,
@@ -1993,17 +1601,12 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
pktx = &local_pktx;
}
else {
- pktx->ts = timestamp();
+ pktx_update_time(pktx, cf);
}
-#ifdef USE_OPENSSL
- if(!ctx->x509_store_setup) {
- result = Curl_ssl_setup_x509_store(cf, data, ctx->sslctx);
- if(result)
- return result;
- ctx->x509_store_setup = TRUE;
- }
-#endif
+ result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
+ if(result)
+ return result;
for(i = 0; i < pkts_max; i += pkts_chunk) {
pktx->pkt_count = 0;
@@ -2081,11 +1684,18 @@ static ssize_t read_pkt_to_send(void *userp,
}
else if(n < 0) {
switch(n) {
- case NGTCP2_ERR_STREAM_DATA_BLOCKED:
+ case NGTCP2_ERR_STREAM_DATA_BLOCKED: {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(x->data);
DEBUGASSERT(ndatalen == -1);
nghttp3_conn_block_stream(ctx->h3conn, stream_id);
+ CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] block quic flow",
+ stream_id);
+ DEBUGASSERT(stream);
+ if(stream)
+ stream->quic_flow_blocked = TRUE;
n = 0;
break;
+ }
case NGTCP2_ERR_STREAM_SHUT_WR:
DEBUGASSERT(ndatalen == -1);
nghttp3_conn_shutdown_stream_write(ctx->h3conn, stream_id);
@@ -2145,7 +1755,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
pktx = &local_pktx;
}
else {
- pktx->ts = timestamp();
+ pktx_update_time(pktx, cf);
ngtcp2_path_storage_zero(&pktx->ps);
}
@@ -2282,10 +1892,12 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DONE: {
+ case CF_CTRL_DATA_DETACH:
+ h3_data_done(cf, data);
+ break;
+ case CF_CTRL_DATA_DONE:
h3_data_done(cf, data);
break;
- }
case CF_CTRL_DATA_DONE_SEND: {
struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
if(stream && !stream->send_closed) {
@@ -2319,31 +1931,14 @@ static void cf_ngtcp2_ctx_clear(struct cf_ngtcp2_ctx *ctx)
if(ctx->qlogfd != -1) {
close(ctx->qlogfd);
}
-#ifdef USE_OPENSSL
- if(ctx->ssl)
- SSL_free(ctx->ssl);
- if(ctx->sslctx)
- SSL_CTX_free(ctx->sslctx);
-#elif defined(USE_GNUTLS)
- if(ctx->gtls) {
- if(ctx->gtls->cred)
- gnutls_certificate_free_credentials(ctx->gtls->cred);
- if(ctx->gtls->session)
- gnutls_deinit(ctx->gtls->session);
- free(ctx->gtls);
- }
-#elif defined(USE_WOLFSSL)
- if(ctx->ssl)
- wolfSSL_free(ctx->ssl);
- if(ctx->sslctx)
- wolfSSL_CTX_free(ctx->sslctx);
-#endif
+ Curl_vquic_tls_cleanup(&ctx->tls);
vquic_ctx_free(&ctx->q);
if(ctx->h3conn)
nghttp3_conn_del(ctx->h3conn);
if(ctx->qconn)
ngtcp2_conn_del(ctx->qconn);
Curl_bufcp_free(&ctx->stream_bufcp);
+ Curl_ssl_peer_cleanup(&ctx->peer);
memset(ctx, 0, sizeof(*ctx));
ctx->qlogfd = -1;
@@ -2358,15 +1953,15 @@ static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
CF_DATA_SAVE(save, cf, data);
if(ctx && ctx->qconn) {
char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
- ngtcp2_tstamp ts;
+ struct pkt_io_ctx pktx;
ngtcp2_ssize rc;
CURL_TRC_CF(data, cf, "close");
- ts = timestamp();
+ pktx_init(&pktx, cf, data);
rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */
NULL, /* pkt_info */
(uint8_t *)buffer, sizeof(buffer),
- &ctx->last_error, ts);
+ &ctx->last_error, pktx.ts);
if(rc > 0) {
while((send(ctx->q.sockfd, buffer, (SEND_TYPE_ARG3)rc, 0) == -1) &&
SOCKERRNO == EINTR);
@@ -2395,6 +1990,37 @@ static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
(void)save;
}
+static CURLcode tls_ctx_setup(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ (void)cf;
+#ifdef USE_OPENSSL
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+ if(ngtcp2_crypto_boringssl_configure_client_context(ctx->ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
+ return CURLE_FAILED_INIT;
+ }
+#else
+ if(ngtcp2_crypto_quictls_configure_client_context(ctx->ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
+ return CURLE_FAILED_INIT;
+ }
+#endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
+#elif defined(USE_GNUTLS)
+ if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
+ failf(data, "ngtcp2_crypto_gnutls_configure_client_session failed");
+ return CURLE_FAILED_INIT;
+ }
+#elif defined(USE_WOLFSSL)
+ if(ngtcp2_crypto_wolfssl_configure_client_context(ctx->ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
+ return CURLE_FAILED_INIT;
+ }
+#endif
+ return CURLE_OK;
+}
+
/*
* Might be called twice for happy eyeballs.
*/
@@ -2411,24 +2037,18 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
ctx->version = NGTCP2_PROTO_VER_MAX;
ctx->max_stream_window = H3_STREAM_WINDOW_SIZE;
+ ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
-#ifdef USE_OPENSSL
- result = quic_ssl_ctx(&ctx->sslctx, cf, data);
+ result = Curl_ssl_peer_init(&ctx->peer, cf);
if(result)
return result;
- result = quic_set_client_cert(cf, data);
- if(result)
- return result;
-#elif defined(USE_WOLFSSL)
- result = quic_ssl_ctx(&ctx->sslctx, cf, data);
- if(result)
- return result;
-#endif
-
- result = quic_init_ssl(cf, data);
+#define H3_ALPN "\x2h3\x5h3-29"
+ result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
+ H3_ALPN, sizeof(H3_ALPN) - 1,
+ tls_ctx_setup, &ctx->conn_ref);
if(result)
return result;
@@ -2475,9 +2095,9 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
return CURLE_QUIC_CONNECT_ERROR;
#ifdef USE_GNUTLS
- ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->gtls->session);
+ ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls->session);
#else
- ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->ssl);
+ ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ssl);
#endif
ngtcp2_ccerr_default(&ctx->last_error);
@@ -2559,27 +2179,9 @@ out:
ngtcp2_conn_in_draining_period(ctx->qconn)) {
/* When a QUIC server instance is shutting down, it may send us a
* CONNECTION_CLOSE right away. Our connection then enters the DRAINING
- * state.
- * This may be a stopping of the service or it may be that the server
- * is reloading and a new instance will start serving soon.
- * In any case, we tear down our socket and start over with a new one.
- * We re-open the underlying UDP cf right now, but do not start
- * connecting until called again.
- */
- int reconn_delay_ms = 200;
-
- CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
- reconn_delay_ms);
- Curl_conn_cf_close(cf->next, data);
- cf_ngtcp2_ctx_clear(ctx);
- result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
- if(!result && *done) {
- *done = FALSE;
- ctx->reconnect_at = now;
- ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
- Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
- result = CURLE_OK;
- }
+ * state. The CONNECT may work in the near future again. Indicate
+ * that as a "weird" reply. */
+ result = CURLE_WEIRD_SERVER_REPLY;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -2626,8 +2228,8 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
return CURLE_OK;
}
case CF_QUERY_CONNECT_REPLY_MS:
- if(ctx->got_first_byte) {
- timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ if(ctx->q.got_first_byte) {
+ timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
*pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
}
else
@@ -2635,8 +2237,8 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
return CURLE_OK;
case CF_QUERY_TIMER_CONNECT: {
struct curltime *when = pres2;
- if(ctx->got_first_byte)
- *when = ctx->first_byte_at;
+ if(ctx->q.got_first_byte)
+ *when = ctx->q.first_byte_at;
return CURLE_OK;
}
case CF_QUERY_TIMER_APPCONNECT: {
@@ -2657,24 +2259,51 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending)
{
- bool alive = TRUE;
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ bool alive = FALSE;
+ const ngtcp2_transport_params *rp;
+ struct cf_call_data save;
+ CF_DATA_SAVE(save, cf, data);
*input_pending = FALSE;
+ if(!ctx->qconn)
+ goto out;
+
+ /* Both sides of the QUIC connection announce they max idle times in
+ * the transport parameters. Look at the minimum of both and if
+ * we exceed this, regard the connection as dead. The other side
+ * may have completely purged it and will no longer respond
+ * to any packets from us. */
+ rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
+ if(rp) {
+ timediff_t idletime;
+ uint64_t idle_ms = ctx->max_idle_ms;
+
+ if(rp->max_idle_timeout &&
+ (rp->max_idle_timeout / NGTCP2_MILLISECONDS) < idle_ms)
+ idle_ms = (rp->max_idle_timeout / NGTCP2_MILLISECONDS);
+ idletime = Curl_timediff(Curl_now(), ctx->q.last_io);
+ if(idletime > 0 && (uint64_t)idletime > idle_ms)
+ goto out;
+ }
+
if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
- return FALSE;
+ goto out;
+ alive = TRUE;
if(*input_pending) {
+ CURLcode result;
/* This happens before we've sent off a request and the connection is
not in use by any other transfer, there shouldn't be any data here,
only "protocol frames" */
*input_pending = FALSE;
- if(cf_progress_ingress(cf, data, NULL))
- alive = FALSE;
- else {
- alive = TRUE;
- }
+ result = cf_progress_ingress(cf, data, NULL);
+ CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result);
+ alive = result? FALSE : TRUE;
}
+out:
+ CF_DATA_RESTORE(cf, save);
return alive;
}
@@ -2686,7 +2315,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_ngtcp2_connect,
cf_ngtcp2_close,
Curl_cf_def_get_host,
- cf_ngtcp2_get_select_socks,
+ cf_ngtcp2_adjust_pollset,
cf_ngtcp2_data_pending,
cf_ngtcp2_send,
cf_ngtcp2_recv,
@@ -2706,7 +2335,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
CURLcode result;
(void)data;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/vquic/curl_osslq.c b/lib/vquic/curl_osslq.c
new file mode 100644
index 000000000..c499a004b
--- /dev/null
+++ b/lib/vquic/curl_osslq.c
@@ -0,0 +1,2237 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <nghttp3/nghttp3.h>
+
+#include "urldata.h"
+#include "sendf.h"
+#include "strdup.h"
+#include "rand.h"
+#include "multiif.h"
+#include "strcase.h"
+#include "cfilters.h"
+#include "cf-socket.h"
+#include "connect.h"
+#include "progress.h"
+#include "strerror.h"
+#include "dynbuf.h"
+#include "http1.h"
+#include "select.h"
+#include "inet_pton.h"
+#include "vquic.h"
+#include "vquic_int.h"
+#include "vquic-tls.h"
+#include "vtls/keylog.h"
+#include "vtls/vtls.h"
+#include "vtls/openssl.h"
+#include "curl_osslq.h"
+
+#include "warnless.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/* A stream window is the maximum amount we need to buffer for
+ * each active transfer. We use HTTP/3 flow control and only ACK
+ * when we take things out of the buffer.
+ * Chunk size is large enough to take a full DATA frame */
+#define H3_STREAM_WINDOW_SIZE (128 * 1024)
+#define H3_STREAM_CHUNK_SIZE (16 * 1024)
+/* The pool keeps spares around and half of a full stream windows
+ * seems good. More does not seem to improve performance.
+ * The benefit of the pool is that stream buffer to not keep
+ * spares. So memory consumption goes down when streams run empty,
+ * have a large upload done, etc. */
+#define H3_STREAM_POOL_SPARES \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE ) / 2
+/* Receive and Send max number of chunks just follows from the
+ * chunk size and window size */
+#define H3_STREAM_RECV_CHUNKS \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+#define H3_STREAM_SEND_CHUNKS \
+ (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+typedef uint32_t sslerr_t;
+#else
+typedef unsigned long sslerr_t;
+#endif
+
+
+/* How to access `call_data` from a cf_osslq filter */
+#undef CF_CTX_CALL_DATA
+#define CF_CTX_CALL_DATA(cf) \
+ ((struct cf_osslq_ctx *)(cf)->ctx)->call_data
+
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+static const char *SSL_ERROR_to_str(int err)
+{
+ switch(err) {
+ case SSL_ERROR_NONE:
+ return "SSL_ERROR_NONE";
+ case SSL_ERROR_SSL:
+ return "SSL_ERROR_SSL";
+ case SSL_ERROR_WANT_READ:
+ return "SSL_ERROR_WANT_READ";
+ case SSL_ERROR_WANT_WRITE:
+ return "SSL_ERROR_WANT_WRITE";
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return "SSL_ERROR_WANT_X509_LOOKUP";
+ case SSL_ERROR_SYSCALL:
+ return "SSL_ERROR_SYSCALL";
+ case SSL_ERROR_ZERO_RETURN:
+ return "SSL_ERROR_ZERO_RETURN";
+ case SSL_ERROR_WANT_CONNECT:
+ return "SSL_ERROR_WANT_CONNECT";
+ case SSL_ERROR_WANT_ACCEPT:
+ return "SSL_ERROR_WANT_ACCEPT";
+#if defined(SSL_ERROR_WANT_ASYNC)
+ case SSL_ERROR_WANT_ASYNC:
+ return "SSL_ERROR_WANT_ASYNC";
+#endif
+#if defined(SSL_ERROR_WANT_ASYNC_JOB)
+ case SSL_ERROR_WANT_ASYNC_JOB:
+ return "SSL_ERROR_WANT_ASYNC_JOB";
+#endif
+#if defined(SSL_ERROR_WANT_EARLY)
+ case SSL_ERROR_WANT_EARLY:
+ return "SSL_ERROR_WANT_EARLY";
+#endif
+ default:
+ return "SSL_ERROR unknown";
+ }
+}
+
+/* Return error string for last OpenSSL error */
+static char *ossl_strerror(unsigned long error, char *buf, size_t size)
+{
+ DEBUGASSERT(size);
+ *buf = '\0';
+
+#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
+ ERR_error_string_n((uint32_t)error, buf, size);
+#else
+ ERR_error_string_n(error, buf, size);
+#endif
+
+ if(!*buf) {
+ const char *msg = error ? "Unknown error" : "No error";
+ if(strlen(msg) < size)
+ strcpy(buf, msg);
+ }
+
+ return buf;
+}
+
+static CURLcode make_bio_addr(BIO_ADDR **pbio_addr,
+ const struct Curl_sockaddr_ex *addr)
+{
+ BIO_ADDR *ba;
+ CURLcode result = CURLE_FAILED_INIT;
+
+ ba = BIO_ADDR_new();
+ if(!ba) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ switch(addr->family) {
+ case AF_INET: {
+ struct sockaddr_in * const sin =
+ (struct sockaddr_in * const)(void *)&addr->sa_addr;
+ if(!BIO_ADDR_rawmake(ba, AF_INET, &sin->sin_addr,
+ sizeof(sin->sin_addr), sin->sin_port)) {
+ goto out;
+ }
+ result = CURLE_OK;
+ break;
+ }
+#ifdef ENABLE_IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 * const sin =
+ (struct sockaddr_in6 * const)(void *)&addr->sa_addr;
+ if(!BIO_ADDR_rawmake(ba, AF_INET6, &sin->sin6_addr,
+ sizeof(sin->sin6_addr), sin->sin6_port)) {
+ }
+ result = CURLE_OK;
+ break;
+ }
+#endif /* ENABLE_IPV6 */
+ default:
+ /* sunsupported */
+ DEBUGASSERT(0);
+ break;
+ }
+
+out:
+ if(result && ba) {
+ BIO_ADDR_free(ba);
+ ba = NULL;
+ }
+ *pbio_addr = ba;
+ return result;
+}
+
+/* QUIC stream (not necessarily H3) */
+struct cf_osslq_stream {
+ int64_t id;
+ SSL *ssl;
+ struct bufq recvbuf; /* QUIC war data recv buffer */
+ BIT(recvd_eos);
+ BIT(closed);
+ BIT(reset);
+ BIT(send_blocked);
+};
+
+static CURLcode cf_osslq_stream_open(struct cf_osslq_stream *s,
+ SSL *conn,
+ uint64_t flags,
+ struct bufc_pool *bufcp,
+ void *user_data)
+{
+ DEBUGASSERT(!s->ssl);
+ Curl_bufq_initp(&s->recvbuf, bufcp, 1, BUFQ_OPT_NONE);
+ s->ssl = SSL_new_stream(conn, flags);
+ if(!s->ssl) {
+ return CURLE_FAILED_INIT;
+ }
+ s->id = SSL_get_stream_id(s->ssl);
+ SSL_set_app_data(s->ssl, user_data);
+ return CURLE_OK;
+}
+
+static void cf_osslq_stream_cleanup(struct cf_osslq_stream *s)
+{
+ if(s->ssl) {
+ SSL_set_app_data(s->ssl, NULL);
+ SSL_free(s->ssl);
+ }
+ Curl_bufq_free(&s->recvbuf);
+ memset(s, 0, sizeof(*s));
+}
+
+static void cf_osslq_stream_close(struct cf_osslq_stream *s)
+{
+ if(s->ssl) {
+ SSL_free(s->ssl);
+ s->ssl = NULL;
+ }
+}
+
+struct cf_osslq_h3conn {
+ nghttp3_conn *conn;
+ nghttp3_settings settings;
+ struct cf_osslq_stream s_ctrl;
+ struct cf_osslq_stream s_qpack_enc;
+ struct cf_osslq_stream s_qpack_dec;
+ struct cf_osslq_stream remote_ctrl[3]; /* uni streams opened by the peer */
+ size_t remote_ctrl_n; /* number of peer streams opened */
+};
+
+static void cf_osslq_h3conn_cleanup(struct cf_osslq_h3conn *h3)
+{
+ size_t i;
+
+ if(h3->conn)
+ nghttp3_conn_del(h3->conn);
+ cf_osslq_stream_cleanup(&h3->s_ctrl);
+ cf_osslq_stream_cleanup(&h3->s_qpack_enc);
+ cf_osslq_stream_cleanup(&h3->s_qpack_dec);
+ for(i = 0; i < h3->remote_ctrl_n; ++i) {
+ cf_osslq_stream_cleanup(&h3->remote_ctrl[i]);
+ }
+}
+
+struct cf_osslq_ctx {
+ struct cf_quic_ctx q;
+ struct ssl_peer peer;
+ struct quic_tls_ctx tls;
+ struct cf_call_data call_data;
+ struct cf_osslq_h3conn h3;
+ struct curltime started_at; /* time the current attempt started */
+ struct curltime handshake_at; /* time connect handshake finished */
+ struct curltime first_byte_at; /* when first byte was recvd */
+ struct curltime reconnect_at; /* time the next attempt should start */
+ struct bufc_pool stream_bufcp; /* chunk pool for streams */
+ size_t max_stream_window; /* max flow window for one stream */
+ uint64_t max_idle_ms; /* max idle time for QUIC connection */
+ BIT(got_first_byte); /* if first byte was received */
+#ifdef USE_OPENSSL
+ BIT(x509_store_setup); /* if x509 store has been set up */
+ BIT(protocol_shutdown); /* QUIC connection is shut down */
+#endif
+};
+
+static void cf_osslq_ctx_clear(struct cf_osslq_ctx *ctx)
+{
+ struct cf_call_data save = ctx->call_data;
+
+ cf_osslq_h3conn_cleanup(&ctx->h3);
+ Curl_vquic_tls_cleanup(&ctx->tls);
+ vquic_ctx_free(&ctx->q);
+ Curl_bufcp_free(&ctx->stream_bufcp);
+ Curl_ssl_peer_cleanup(&ctx->peer);
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->call_data = save;
+}
+
+static void cf_osslq_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ if(ctx && ctx->tls.ssl) {
+ /* TODO: send connection close */
+ CURL_TRC_CF(data, cf, "cf_osslq_close()");
+ cf_osslq_ctx_clear(ctx);
+ }
+
+ cf->connected = FALSE;
+ CF_DATA_RESTORE(cf, save);
+}
+
+static void cf_osslq_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ CURL_TRC_CF(data, cf, "destroy");
+ if(ctx) {
+ CURL_TRC_CF(data, cf, "cf_osslq_destroy()");
+ cf_osslq_ctx_clear(ctx);
+ free(ctx);
+ }
+ cf->ctx = NULL;
+ /* No CF_DATA_RESTORE(cf, save) possible */
+ (void)save;
+}
+
+static CURLcode cf_osslq_h3conn_add_stream(struct cf_osslq_h3conn *h3,
+ SSL *stream_ssl,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ int64_t stream_id = SSL_get_stream_id(stream_ssl);
+
+ if(h3->remote_ctrl_n >= ARRAYSIZE(h3->remote_ctrl)) {
+ /* rejected, we are full */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] rejecting additional remote stream",
+ stream_id);
+ SSL_free(stream_ssl);
+ return CURLE_FAILED_INIT;
+ }
+ switch(SSL_get_stream_type(stream_ssl)) {
+ case SSL_STREAM_TYPE_READ: {
+ struct cf_osslq_stream *nstream = &h3->remote_ctrl[h3->remote_ctrl_n++];
+ nstream->id = stream_id;
+ nstream->ssl = stream_ssl;
+ Curl_bufq_initp(&nstream->recvbuf, &ctx->stream_bufcp, 1, BUFQ_OPT_NONE);
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] accepted new remote uni stream",
+ stream_id);
+ break;
+ }
+ default:
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] rejecting remote non-uni-read"
+ " stream", stream_id);
+ SSL_free(stream_ssl);
+ return CURLE_FAILED_INIT;
+ }
+ return CURLE_OK;
+
+}
+
+static CURLcode cf_osslq_ssl_err(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int detail, CURLcode def_result)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = def_result;
+ sslerr_t errdetail;
+ char ebuf[256] = "unknown";
+ const char *err_descr = ebuf;
+ long lerr;
+ int lib;
+ int reason;
+ struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+
+ errdetail = ERR_get_error();
+ lib = ERR_GET_LIB(errdetail);
+ reason = ERR_GET_REASON(errdetail);
+
+ if((lib == ERR_LIB_SSL) &&
+ ((reason == SSL_R_CERTIFICATE_VERIFY_FAILED) ||
+ (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) {
+ result = CURLE_PEER_FAILED_VERIFICATION;
+
+ lerr = SSL_get_verify_result(ctx->tls.ssl);
+ if(lerr != X509_V_OK) {
+ ssl_config->certverifyresult = lerr;
+ msnprintf(ebuf, sizeof(ebuf),
+ "SSL certificate problem: %s",
+ X509_verify_cert_error_string(lerr));
+ }
+ else
+ err_descr = "SSL certificate verification failed";
+ }
+#if defined(SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)
+ /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
+ OpenSSL version above v1.1.1, not LibreSSL, BoringSSL, or AWS-LC */
+ else if((lib == ERR_LIB_SSL) &&
+ (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
+ /* If client certificate is required, communicate the
+ error to client */
+ result = CURLE_SSL_CLIENTCERT;
+ ossl_strerror(errdetail, ebuf, sizeof(ebuf));
+ }
+#endif
+ else if((lib == ERR_LIB_SSL) && (reason == SSL_R_PROTOCOL_IS_SHUTDOWN)) {
+ ctx->protocol_shutdown = TRUE;
+ err_descr = "QUIC connectin has been shut down";
+ result = def_result;
+ }
+ else {
+ result = def_result;
+ ossl_strerror(errdetail, ebuf, sizeof(ebuf));
+ }
+
+ /* detail is already set to the SSL error above */
+
+ /* If we e.g. use SSLv2 request-method and the server doesn't like us
+ * (RST connection, etc.), OpenSSL gives no explanation whatsoever and
+ * the SO_ERROR is also lost.
+ */
+ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+ char extramsg[80]="";
+ int sockerr = SOCKERRNO;
+ const char *r_ip = NULL;
+ int r_port = 0;
+
+ Curl_cf_socket_peek(cf->next, data, NULL, NULL,
+ &r_ip, &r_port, NULL, NULL);
+ if(sockerr && detail == SSL_ERROR_SYSCALL)
+ Curl_strerror(sockerr, extramsg, sizeof(extramsg));
+ failf(data, "QUIC connect: %s in connection to %s:%d (%s)",
+ extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
+ ctx->peer.dispname, r_port, r_ip);
+ }
+ else {
+ /* Could be a CERT problem */
+ failf(data, "%s", err_descr);
+ }
+ return result;
+}
+
+static CURLcode cf_osslq_verify_peer(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+
+ cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ cf->conn->httpversion = 30;
+ cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+
+ return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
+}
+
+/**
+ * All about the H3 internals of a stream
+ */
+struct h3_stream_ctx {
+ struct cf_osslq_stream s;
+ struct bufq sendbuf; /* h3 request body */
+ struct bufq recvbuf; /* h3 response body */
+ struct h1_req_parser h1; /* h1 request parsing */
+ size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
+ size_t upload_blocked_len; /* the amount written last and EGAINed */
+ size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
+ uint64_t error3; /* HTTP/3 stream error code */
+ curl_off_t upload_left; /* number of request bytes left to upload */
+ curl_off_t download_recvd; /* number of response DATA bytes received */
+ int status_code; /* HTTP status code */
+ bool resp_hds_complete; /* we have a complete, final response */
+ bool closed; /* TRUE on stream close */
+ bool reset; /* TRUE on stream reset */
+ bool send_closed; /* stream is local closed */
+ BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
+};
+
+#define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \
+ ((struct HTTP *)(d)->req.p.http)->h3_ctx \
+ : NULL))
+#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
+#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
+ H3_STREAM_CTX(d)->s.id : -2)
+
+static CURLcode h3_data_setup(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+
+ if(!data || !data->req.p.http) {
+ failf(data, "initialization failure, transfer not http initialized");
+ return CURLE_FAILED_INIT;
+ }
+
+ if(stream)
+ return CURLE_OK;
+
+ stream = calloc(1, sizeof(*stream));
+ if(!stream)
+ return CURLE_OUT_OF_MEMORY;
+
+ stream->s.id = -1;
+ /* on send, we control how much we put into the buffer */
+ Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
+ H3_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
+ stream->sendbuf_len_in_flight = 0;
+ /* on recv, we need a flexible buffer limit since we also write
+ * headers to it that are not counted against the nghttp3 flow limits. */
+ Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
+ H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
+ stream->recv_buf_nonflow = 0;
+ Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
+
+ H3_STREAM_LCTX(data) = stream;
+ return CURLE_OK;
+}
+
+static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+
+ (void)cf;
+ if(stream) {
+ CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->s.id);
+ if(ctx->h3.conn && !stream->closed) {
+ nghttp3_conn_shutdown_stream_read(ctx->h3.conn, stream->s.id);
+ nghttp3_conn_close_stream(ctx->h3.conn, stream->s.id,
+ NGHTTP3_H3_REQUEST_CANCELLED);
+ nghttp3_conn_set_stream_user_data(ctx->h3.conn, stream->s.id, NULL);
+ stream->closed = TRUE;
+ }
+
+ cf_osslq_stream_cleanup(&stream->s);
+ Curl_bufq_free(&stream->sendbuf);
+ Curl_bufq_free(&stream->recvbuf);
+ Curl_h1_req_parse_free(&stream->h1);
+ free(stream);
+ H3_STREAM_LCTX(data) = NULL;
+ }
+}
+
+static struct cf_osslq_stream *cf_osslq_get_qstream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int64_t stream_id)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ struct Curl_easy *sdata;
+
+ if(stream && stream->s.id == stream_id) {
+ return &stream->s;
+ }
+ else if(ctx->h3.s_ctrl.id == stream_id) {
+ return &ctx->h3.s_ctrl;
+ }
+ else if(ctx->h3.s_qpack_enc.id == stream_id) {
+ return &ctx->h3.s_qpack_enc;
+ }
+ else if(ctx->h3.s_qpack_dec.id == stream_id) {
+ return &ctx->h3.s_qpack_dec;
+ }
+ else {
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream_id) {
+ stream = H3_STREAM_CTX(sdata);
+ return stream? &stream->s : NULL;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void h3_drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(stream && stream->upload_left && !stream->send_closed)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.select_bits != bits) {
+ data->state.select_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
+static CURLcode h3_data_pause(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool pause)
+{
+ if(!pause) {
+ /* unpaused. make it run again right away */
+ h3_drain_stream(cf, data);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+ return CURLE_OK;
+}
+
+static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ (void)conn;
+ (void)stream_id;
+
+ /* we might be called by nghttp3 after we already cleaned up */
+ if(!stream)
+ return 0;
+
+ stream->closed = TRUE;
+ stream->error3 = app_error_code;
+ if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
+ stream->reset = TRUE;
+ stream->send_closed = TRUE;
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] RESET: error %" PRId64,
+ stream->s.id, stream->error3);
+ }
+ else {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->s.id);
+ }
+ h3_drain_stream(cf, data);
+ return 0;
+}
+
+/*
+ * write_resp_raw() copies response data in raw format to the `data`'s
+ * receive buffer. If not enough space is available, it appends to the
+ * `data`'s overflow buffer.
+ */
+static CURLcode write_resp_raw(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *mem, size_t memlen,
+ bool flow)
+{
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ ssize_t nwritten;
+
+ (void)cf;
+ if(!stream) {
+ return CURLE_RECV_ERROR;
+ }
+ nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
+ if(nwritten < 0) {
+ return result;
+ }
+
+ if(!flow)
+ stream->recv_buf_nonflow += (size_t)nwritten;
+
+ if((size_t)nwritten < memlen) {
+ /* This MUST not happen. Our recbuf is dimensioned to hold the
+ * full max_stream_window and then some for this very reason. */
+ DEBUGASSERT(0);
+ return CURLE_RECV_ERROR;
+ }
+ return result;
+}
+
+static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
+ const uint8_t *buf, size_t buflen,
+ void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result;
+
+ (void)conn;
+ (void)stream3_id;
+
+ if(!stream)
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+
+ result = write_resp_raw(cf, data, buf, buflen, TRUE);
+ if(result) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu, ERROR receiving %d",
+ stream->s.id, buflen, result);
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+ }
+ stream->download_recvd += (curl_off_t)buflen;
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu, total=%zd",
+ stream->s.id, buflen, stream->download_recvd);
+ h3_drain_stream(cf, data);
+ return 0;
+}
+
+static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream_id,
+ size_t consumed, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+
+ (void)conn;
+ (void)stream_id;
+ if(stream)
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] deferred consume %zu bytes",
+ stream->s.id, consumed);
+ return 0;
+}
+
+static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
+ int32_t token, nghttp3_rcbuf *name,
+ nghttp3_rcbuf *value, uint8_t flags,
+ void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
+ nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ (void)conn;
+ (void)stream_id;
+ (void)token;
+ (void)flags;
+ (void)cf;
+
+ /* we might have cleaned up this transfer already */
+ if(!stream)
+ return 0;
+
+ if(token == NGHTTP3_QPACK_TOKEN__STATUS) {
+ char line[14]; /* status line is always 13 characters long */
+ size_t ncopy;
+
+ result = Curl_http_decode_status(&stream->status_code,
+ (const char *)h3val.base, h3val.len);
+ if(result)
+ return -1;
+ ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
+ stream->status_code);
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] status: %s", stream_id, line);
+ result = write_resp_raw(cf, data, line, ncopy, FALSE);
+ if(result) {
+ return -1;
+ }
+ }
+ else {
+ /* store as an HTTP1-style header */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] header: %.*s: %.*s",
+ stream_id, (int)h3name.len, h3name.base,
+ (int)h3val.len, h3val.base);
+ result = write_resp_raw(cf, data, h3name.base, h3name.len, FALSE);
+ if(result) {
+ return -1;
+ }
+ result = write_resp_raw(cf, data, ": ", 2, FALSE);
+ if(result) {
+ return -1;
+ }
+ result = write_resp_raw(cf, data, h3val.base, h3val.len, FALSE);
+ if(result) {
+ return -1;
+ }
+ result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
+ if(result) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
+ int fin, void *user_data, void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURLcode result = CURLE_OK;
+ (void)conn;
+ (void)stream_id;
+ (void)fin;
+ (void)cf;
+
+ if(!stream)
+ return 0;
+ /* add a CRLF only if we've received some headers */
+ result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
+ if(result) {
+ return -1;
+ }
+
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] end_headers, status=%d",
+ stream_id, stream->status_code);
+ if(stream->status_code / 100 != 1) {
+ stream->resp_hds_complete = TRUE;
+ }
+ h3_drain_stream(cf, data);
+ return 0;
+}
+
+static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ (void)conn;
+ (void)app_error_code;
+
+ if(!stream || !stream->s.ssl)
+ return 0;
+
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] stop_sending", stream_id);
+ cf_osslq_stream_close(&stream->s);
+ return 0;
+}
+
+static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data) {
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ int rv;
+ (void)conn;
+
+ if(stream && stream->s.ssl) {
+ SSL_STREAM_RESET_ARGS args = {0};
+ args.quic_error_code = app_error_code;
+ rv = !SSL_stream_reset(stream->s.ssl, &args, sizeof(args));
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
+ if(!rv) {
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static nghttp3_ssize
+cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
+ nghttp3_vec *vec, size_t veccnt,
+ uint32_t *pflags, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nwritten = 0;
+ size_t nvecs = 0;
+ (void)cf;
+ (void)conn;
+ (void)stream_id;
+ (void)user_data;
+ (void)veccnt;
+
+ if(!stream)
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+ /* nghttp3 keeps references to the sendbuf data until it is ACKed
+ * by the server (see `cb_h3_acked_req_body()` for updates).
+ * `sendbuf_len_in_flight` is the amount of bytes in `sendbuf`
+ * that we have already passed to nghttp3, but which have not been
+ * ACKed yet.
+ * Any amount beyond `sendbuf_len_in_flight` we need still to pass
+ * to nghttp3. Do that now, if we can. */
+ if(stream->sendbuf_len_in_flight < Curl_bufq_len(&stream->sendbuf)) {
+ nvecs = 0;
+ while(nvecs < veccnt &&
+ Curl_bufq_peek_at(&stream->sendbuf,
+ stream->sendbuf_len_in_flight,
+ (const unsigned char **)&vec[nvecs].base,
+ &vec[nvecs].len)) {
+ stream->sendbuf_len_in_flight += vec[nvecs].len;
+ nwritten += vec[nvecs].len;
+ ++nvecs;
+ }
+ DEBUGASSERT(nvecs > 0); /* we SHOULD have been be able to peek */
+ }
+
+ if(nwritten > 0 && stream->upload_left != -1)
+ stream->upload_left -= nwritten;
+
+ /* When we stopped sending and everything in `sendbuf` is "in flight",
+ * we are at the end of the request body. */
+ if(stream->upload_left == 0) {
+ *pflags = NGHTTP3_DATA_FLAG_EOF;
+ stream->send_closed = TRUE;
+ }
+ else if(!nwritten) {
+ /* Not EOF, and nothing to give, we signal WOULDBLOCK. */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN",
+ stream->s.id);
+ return NGHTTP3_ERR_WOULDBLOCK;
+ }
+
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> "
+ "%d vecs%s with %zu (buffered=%zu, left=%"
+ CURL_FORMAT_CURL_OFF_T ")",
+ stream->s.id, (int)nvecs,
+ *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
+ nwritten, Curl_bufq_len(&stream->sendbuf),
+ stream->upload_left);
+ return (nghttp3_ssize)nvecs;
+}
+
+static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
+ uint64_t datalen, void *user_data,
+ void *stream_user_data)
+{
+ struct Curl_cfilter *cf = user_data;
+ struct Curl_easy *data = stream_user_data;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ size_t skiplen;
+
+ (void)cf;
+ if(!stream)
+ return 0;
+ /* The server acknowledged `datalen` of bytes from our request body.
+ * This is a delta. We have kept this data in `sendbuf` for
+ * re-transmissions and can free it now. */
+ if(datalen >= (uint64_t)stream->sendbuf_len_in_flight)
+ skiplen = stream->sendbuf_len_in_flight;
+ else
+ skiplen = (size_t)datalen;
+ Curl_bufq_skip(&stream->sendbuf, skiplen);
+ stream->sendbuf_len_in_flight -= skiplen;
+
+ /* Everything ACKed, we resume upload processing */
+ if(!stream->sendbuf_len_in_flight) {
+ int rv = nghttp3_conn_resume_stream(conn, stream_id);
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+ return NGHTTP3_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static nghttp3_callbacks ngh3_callbacks = {
+ cb_h3_acked_stream_data,
+ cb_h3_stream_close,
+ cb_h3_recv_data,
+ cb_h3_deferred_consume,
+ NULL, /* begin_headers */
+ cb_h3_recv_header,
+ cb_h3_end_headers,
+ NULL, /* begin_trailers */
+ cb_h3_recv_header,
+ NULL, /* end_trailers */
+ cb_h3_stop_sending,
+ NULL, /* end_stream */
+ cb_h3_reset_stream,
+ NULL, /* shutdown */
+ NULL /* recv_settings */
+};
+
+static CURLcode cf_osslq_h3conn_init(struct cf_osslq_ctx *ctx, SSL *conn,
+ void *user_data)
+{
+ struct cf_osslq_h3conn *h3 = &ctx->h3;
+ CURLcode result;
+ int rc;
+
+ nghttp3_settings_default(&h3->settings);
+ rc = nghttp3_conn_client_new(&h3->conn,
+ &ngh3_callbacks,
+ &h3->settings,
+ nghttp3_mem_default(),
+ user_data);
+ if(rc) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ result = cf_osslq_stream_open(&h3->s_ctrl, conn,
+ SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
+ &ctx->stream_bufcp, NULL);
+ if(result) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto out;
+ }
+ result = cf_osslq_stream_open(&h3->s_qpack_enc, conn,
+ SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
+ &ctx->stream_bufcp, NULL);
+ if(result) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto out;
+ }
+ result = cf_osslq_stream_open(&h3->s_qpack_dec, conn,
+ SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
+ &ctx->stream_bufcp, NULL);
+ if(result) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto out;
+ }
+
+ rc = nghttp3_conn_bind_control_stream(h3->conn, h3->s_ctrl.id);
+ if(rc) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto out;
+ }
+ rc = nghttp3_conn_bind_qpack_streams(h3->conn, h3->s_qpack_enc.id,
+ h3->s_qpack_dec.id);
+ if(rc) {
+ result = CURLE_QUIC_CONNECT_ERROR;
+ goto out;
+ }
+
+ result = CURLE_OK;
+out:
+ return result;
+}
+
+static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result;
+ int rv;
+ const struct Curl_sockaddr_ex *peer_addr = NULL;
+ int peer_port;
+ BIO *bio = NULL;
+ BIO_ADDR *baddr = NULL;
+
+ Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
+ H3_STREAM_POOL_SPARES);
+ result = Curl_ssl_peer_init(&ctx->peer, cf);
+ if(result)
+ goto out;
+
+#define H3_ALPN "\x2h3"
+ result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
+ H3_ALPN, sizeof(H3_ALPN) - 1,
+ NULL, NULL);
+ if(result)
+ goto out;
+
+ result = vquic_ctx_init(&ctx->q);
+ if(result)
+ goto out;
+
+ result = CURLE_QUIC_CONNECT_ERROR;
+ Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
+ &peer_addr, NULL, &peer_port, NULL, NULL);
+ if(!peer_addr)
+ goto out;
+
+ ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
+ rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
+ &ctx->q.local_addrlen);
+ if(rv == -1)
+ goto out;
+
+ result = make_bio_addr(&baddr, peer_addr);
+ if(result) {
+ failf(data, "error creating BIO_ADDR from sockaddr");
+ goto out;
+ }
+
+ bio = BIO_new_dgram(ctx->q.sockfd, BIO_NOCLOSE);
+ if(!bio) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if(!SSL_set1_initial_peer_addr(ctx->tls.ssl, baddr)) {
+ failf(data, "failed to set the initial peer address");
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+ if(!SSL_set_blocking_mode(ctx->tls.ssl, 0)) {
+ failf(data, "failed to turn off blocking mode");
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+
+ SSL_set_bio(ctx->tls.ssl, bio, bio);
+ bio = NULL;
+ SSL_set_connect_state(ctx->tls.ssl);
+ SSL_set_incoming_stream_policy(ctx->tls.ssl,
+ SSL_INCOMING_STREAM_POLICY_ACCEPT, 0);
+ /* setup the H3 things on top of the QUIC connection */
+ result = cf_osslq_h3conn_init(ctx, ctx->tls.ssl, cf);
+
+out:
+ if(bio)
+ BIO_free(bio);
+ if(baddr)
+ BIO_ADDR_free(baddr);
+ CURL_TRC_CF(data, cf, "QUIC tls init -> %d", result);
+ return result;
+}
+
+struct h3_quic_recv_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+ struct cf_osslq_stream *s;
+};
+
+static ssize_t h3_quic_recv(void *reader_ctx,
+ unsigned char *buf, size_t len,
+ CURLcode *err)
+{
+ struct h3_quic_recv_ctx *x = reader_ctx;
+ size_t nread;
+ int rv;
+
+ *err = CURLE_OK;
+ rv = SSL_read_ex(x->s->ssl, buf, len, &nread);
+ if(rv <= 0) {
+ int detail = SSL_get_error(x->s->ssl, rv);
+ if(detail == SSL_ERROR_WANT_READ || detail == SSL_ERROR_WANT_WRITE) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ else if(detail == SSL_ERROR_ZERO_RETURN) {
+ CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] h3_quic_recv -> EOS",
+ x->s->id);
+ x->s->recvd_eos = TRUE;
+ return 0;
+ }
+ else if(SSL_get_stream_read_state(x->s->ssl) ==
+ SSL_STREAM_STATE_RESET_REMOTE) {
+ uint64_t app_error_code = NGHTTP3_H3_NO_ERROR;
+ SSL_get_stream_read_error_code(x->s->ssl, &app_error_code);
+ CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] h3_quic_recv -> RESET, "
+ "rv=%d, app_err=%" PRIu64,
+ x->s->id, rv, app_error_code);
+ if(app_error_code != NGHTTP3_H3_NO_ERROR) {
+ x->s->reset = TRUE;
+ }
+ x->s->recvd_eos = TRUE;
+ return 0;
+ }
+ else {
+ *err = cf_osslq_ssl_err(x->cf, x->data, detail, CURLE_RECV_ERROR);
+ return -1;
+ }
+ }
+ else {
+ /* CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] h3_quic_recv -> %zu bytes",
+ x->s->id, nread); */
+ }
+ return (ssize_t)nread;
+}
+
+static CURLcode cf_osslq_stream_recv(struct cf_osslq_stream *s,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ ssize_t nread;
+ struct h3_quic_recv_ctx x;
+ int rv, eagain = FALSE;
+ size_t total_recv_len = 0;
+
+ DEBUGASSERT(s);
+ if(s->closed)
+ return CURLE_OK;
+
+ x.cf = cf;
+ x.data = data;
+ x.s = s;
+ while(s->ssl && !s->closed && !eagain &&
+ (total_recv_len < H3_STREAM_CHUNK_SIZE)) {
+ if(Curl_bufq_is_empty(&s->recvbuf) && !s->recvd_eos) {
+ while(!eagain && !s->recvd_eos && !Curl_bufq_is_full(&s->recvbuf)) {
+ nread = Curl_bufq_sipn(&s->recvbuf, 0, h3_quic_recv, &x, &result);
+ if(nread < 0) {
+ if(result != CURLE_AGAIN)
+ goto out;
+ result = CURLE_OK;
+ eagain = TRUE;
+ }
+ }
+ }
+
+ /* Forward what we have to nghttp3 */
+ if(!Curl_bufq_is_empty(&s->recvbuf)) {
+ const unsigned char *buf;
+ size_t blen;
+
+ while(Curl_bufq_peek(&s->recvbuf, &buf, &blen)) {
+ nread = nghttp3_conn_read_stream(ctx->h3.conn, s->id,
+ buf, blen, 0);
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] forward %zu bytes "
+ "to nghttp3 -> %zd", s->id, blen, nread);
+ if(nread < 0) {
+ failf(data, "nghttp3_conn_read_stream(len=%zu) error: %s",
+ blen, nghttp3_strerror((int)nread));
+ result = CURLE_RECV_ERROR;
+ goto out;
+ }
+ /* success, `nread` is the flow for QUIC to count as "consumed",
+ * not sure how that will work with OpenSSL. Anyways, without error,
+ * all data that we passed is not owned by nghttp3. */
+ Curl_bufq_skip(&s->recvbuf, blen);
+ total_recv_len += blen;
+ }
+ }
+
+ /* When we forwarded everything, handle RESET/EOS */
+ if(Curl_bufq_is_empty(&s->recvbuf) && !s->closed) {
+ result = CURLE_OK;
+ if(s->reset) {
+ uint64_t app_error;
+ if(!SSL_get_stream_read_error_code(s->ssl, &app_error)) {
+ failf(data, "SSL_get_stream_read_error_code returned error");
+ result = CURLE_RECV_ERROR;
+ goto out;
+ }
+ rv = nghttp3_conn_close_stream(ctx->h3.conn, s->id, app_error);
+ s->closed = TRUE;
+ if(rv < 0 && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+ failf(data, "nghttp3_conn_close_stream returned error: %s",
+ nghttp3_strerror(rv));
+ result = CURLE_RECV_ERROR;
+ goto out;
+ }
+ }
+ else if(s->recvd_eos) {
+ rv = nghttp3_conn_close_stream(ctx->h3.conn, s->id,
+ NGHTTP3_H3_NO_ERROR);
+ s->closed = TRUE;
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] close nghttp3 stream -> %d",
+ s->id, rv);
+ if(rv < 0 && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+ failf(data, "nghttp3_conn_close_stream returned error: %s",
+ nghttp3_strerror(rv));
+ result = CURLE_RECV_ERROR;
+ goto out;
+ }
+ }
+ }
+ }
+out:
+ if(result)
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_osslq_stream_recv -> %d",
+ s->id, result);
+ return result;
+}
+
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ if(!ctx->tls.ssl)
+ goto out;
+
+ ERR_clear_error();
+
+ /* 1. Check for new incoming streams */
+ while(1) {
+ SSL *snew = SSL_accept_stream(ctx->tls.ssl, SSL_ACCEPT_STREAM_NO_BLOCK);
+ if(!snew)
+ break;
+
+ (void)cf_osslq_h3conn_add_stream(&ctx->h3, snew, cf, data);
+ }
+
+ if(!SSL_handle_events(ctx->tls.ssl)) {
+ int detail = SSL_get_error(ctx->tls.ssl, 0);
+ result = cf_osslq_ssl_err(cf, data, detail, CURLE_RECV_ERROR);
+ }
+
+ if(ctx->h3.conn) {
+ size_t i;
+ for(i = 0; i < ctx->h3.remote_ctrl_n; ++i) {
+ result = cf_osslq_stream_recv(&ctx->h3.remote_ctrl[i], cf, data);
+ if(result)
+ goto out;
+ }
+ }
+
+ if(ctx->h3.conn) {
+ struct Curl_easy *sdata;
+ struct h3_stream_ctx *stream;
+ /* PULL all open streams */
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if(sdata->conn == data->conn && CURL_WANT_RECV(sdata)) {
+ stream = H3_STREAM_CTX(sdata);
+ if(stream && !stream->closed &&
+ !Curl_bufq_is_full(&stream->recvbuf)) {
+ result = cf_osslq_stream_recv(&stream->s, cf, sdata);
+ if(result)
+ goto out;
+ }
+ }
+ }
+ }
+
+out:
+ CURL_TRC_CF(data, cf, "progress_ingress -> %d", result);
+ return result;
+}
+
+/* Iterate over all streams and check if blocked can be unblocked */
+static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct Curl_easy *sdata;
+ struct h3_stream_ctx *stream;
+
+ if(ctx->h3.conn) {
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if(sdata->conn == data->conn) {
+ stream = H3_STREAM_CTX(sdata);
+ if(stream && stream->s.ssl && stream->s.send_blocked &&
+ !SSL_want_write(stream->s.ssl)) {
+ nghttp3_conn_unblock_stream(ctx->h3.conn, stream->s.id);
+ stream->s.send_blocked = FALSE;
+ h3_drain_stream(cf, sdata);
+ CURL_TRC_CF(sdata, cf, "unblocked");
+ }
+ }
+ }
+ }
+ return CURLE_OK;
+}
+
+static CURLcode h3_send_streams(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ if(!ctx->tls.ssl || !ctx->h3.conn)
+ goto out;
+
+ for(;;) {
+ struct cf_osslq_stream *s = NULL;
+ nghttp3_vec vec[16];
+ nghttp3_ssize n, i;
+ int64_t stream_id;
+ size_t written;
+ int eos, ok, rv;
+ size_t total_len, acked_len = 0;
+ bool blocked = FALSE;
+
+ n = nghttp3_conn_writev_stream(ctx->h3.conn, &stream_id, &eos,
+ vec, ARRAYSIZE(vec));
+ if(n < 0) {
+ failf(data, "nghttp3_conn_writev_stream returned error: %s",
+ nghttp3_strerror((int)n));
+ result = CURLE_SEND_ERROR;
+ goto out;
+ }
+ if(stream_id < 0) {
+ result = CURLE_OK;
+ goto out;
+ }
+
+ /* Get the stream for this data */
+ s = cf_osslq_get_qstream(cf, data, stream_id);
+ if(!s) {
+ failf(data, "nghttp3_conn_writev_stream gave unknown stream %" PRId64,
+ stream_id);
+ result = CURLE_SEND_ERROR;
+ goto out;
+ }
+ /* Now write the data to the stream's SSL*, it may not all fit! */
+ DEBUGASSERT(s->id == stream_id);
+ for(i = 0, total_len = 0; i < n; ++i) {
+ total_len += vec[i].len;
+ }
+ for(i = 0; (i < n) && !blocked; ++i) {
+ /* Without stream->s.ssl, we closed that already, so
+ * pretend the write did succeed. */
+ written = vec[i].len;
+ ok = !s->ssl || SSL_write_ex(s->ssl, vec[i].base, vec[i].len,
+ &written);
+ if(ok) {
+ /* As OpenSSL buffers the data, we count this as acknowledged
+ * from nghttp3's point of view */
+ CURL_TRC_CF(data, cf, "[%"PRId64"] send %zu bytes to QUIC ok",
+ s->id, vec[i].len);
+ acked_len += vec[i].len;
+ }
+ else {
+ int detail = SSL_get_error(s->ssl, 0);
+ switch(detail) {
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_READ:
+ /* QUIC blocked us from writing more */
+ CURL_TRC_CF(data, cf, "[%"PRId64"] send %zu bytes to QUIC blocked",
+ s->id, vec[i].len);
+ written = 0;
+ nghttp3_conn_block_stream(ctx->h3.conn, s->id);
+ s->send_blocked = blocked = TRUE;
+ break;
+ default:
+ failf(data, "[%"PRId64"] send %zu bytes to QUIC, SSL error %d",
+ s->id, vec[i].len, detail);
+ result = cf_osslq_ssl_err(cf, data, detail, CURLE_SEND_ERROR);
+ goto out;
+ }
+ }
+ }
+
+ if(acked_len > 0 || (eos && !s->send_blocked)) {
+ /* Since QUIC buffers the data written internally, we can tell
+ * nghttp3 that it can move forward on it */
+ rv = nghttp3_conn_add_write_offset(ctx->h3.conn, s->id, acked_len);
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+ failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ result = CURLE_SEND_ERROR;
+ goto out;
+ }
+ rv = nghttp3_conn_add_ack_offset(ctx->h3.conn, s->id, acked_len);
+ if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
+ failf(data, "nghttp3_conn_add_ack_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ result = CURLE_SEND_ERROR;
+ goto out;
+ }
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] forwarded %zu/%zu h3 bytes "
+ "to QUIC, eos=%d", s->id, acked_len, total_len, eos);
+ }
+
+ if(eos && !s->send_blocked) {
+ /* wrote everything and H3 indicates end of stream */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] closing QUIC stream", s->id);
+ SSL_stream_conclude(s->ssl, 0);
+ }
+ }
+
+out:
+ CURL_TRC_CF(data, cf, "h3_send_streams -> %d", result);
+ return result;
+}
+
+static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+
+ if(!ctx->tls.ssl)
+ goto out;
+
+ ERR_clear_error();
+ result = h3_send_streams(cf, data);
+ if(result)
+ goto out;
+
+ if(!SSL_handle_events(ctx->tls.ssl)) {
+ int detail = SSL_get_error(ctx->tls.ssl, 0);
+ result = cf_osslq_ssl_err(cf, data, detail, CURLE_SEND_ERROR);
+ }
+
+ result = cf_osslq_check_and_unblock(cf, data);
+
+out:
+ CURL_TRC_CF(data, cf, "progress_egress -> %d", result);
+ return result;
+}
+
+static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ struct timeval tv;
+ timediff_t timeoutms;
+ int is_infinite = TRUE;
+
+ if(ctx->tls.ssl &&
+ SSL_get_event_timeout(ctx->tls.ssl, &tv, &is_infinite) &&
+ !is_infinite) {
+ timeoutms = curlx_tvtoms(&tv);
+ /* QUIC want to be called again latest at the returned timeout */
+ if(timeoutms <= 0) {
+ result = cf_progress_ingress(cf, data);
+ if(result)
+ goto out;
+ result = cf_progress_egress(cf, data);
+ if(result)
+ goto out;
+ if(SSL_get_event_timeout(ctx->tls.ssl, &tv, &is_infinite)) {
+ timeoutms = curlx_tvtoms(&tv);
+ }
+ }
+ if(!is_infinite) {
+ Curl_expire(data, timeoutms, EXPIRE_QUIC);
+ CURL_TRC_CF(data, cf, "QUIC expiry in %ldms", (long)timeoutms);
+ }
+ }
+out:
+ return result;
+}
+
+static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking, bool *done)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ struct cf_call_data save;
+ struct curltime now;
+ int err;
+
+ if(cf->connected) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ /* Connect the UDP filter first */
+ if(!cf->next->connected) {
+ result = Curl_conn_cf_connect(cf->next, data, blocking, done);
+ if(result || !*done)
+ return result;
+ }
+
+ *done = FALSE;
+ now = Curl_now();
+ CF_DATA_SAVE(save, cf, data);
+
+ if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
+ /* Not time yet to attempt the next connect */
+ CURL_TRC_CF(data, cf, "waiting for reconnect time");
+ goto out;
+ }
+
+ if(!ctx->tls.ssl) {
+ ctx->started_at = now;
+ result = cf_osslq_ctx_start(cf, data);
+ if(result)
+ goto out;
+ }
+
+ if(!ctx->got_first_byte) {
+ int readable = SOCKET_READABLE(ctx->q.sockfd, 0);
+ if(readable > 0 && (readable & CURL_CSELECT_IN)) {
+ ctx->got_first_byte = TRUE;
+ ctx->first_byte_at = Curl_now();
+ }
+ }
+
+ ERR_clear_error();
+ err = SSL_do_handshake(ctx->tls.ssl);
+
+ if(err == 1) {
+ /* connected */
+ ctx->handshake_at = now;
+ CURL_TRC_CF(data, cf, "handshake complete after %dms",
+ (int)Curl_timediff(now, ctx->started_at));
+ result = cf_osslq_verify_peer(cf, data);
+ if(!result) {
+ CURL_TRC_CF(data, cf, "peer verified");
+ cf->connected = TRUE;
+ cf->conn->alpn = CURL_HTTP_VERSION_3;
+ *done = TRUE;
+ connkeep(cf->conn, "HTTP/3 default");
+ }
+ }
+ else {
+ int detail = SSL_get_error(ctx->tls.ssl, err);
+ switch(detail) {
+ case SSL_ERROR_WANT_READ:
+ CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_RECV");
+ result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
+ goto out;
+ case SSL_ERROR_WANT_WRITE:
+ CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_SEND");
+ result = CURLE_OK;
+ goto out;
+#ifdef SSL_ERROR_WANT_ASYNC
+ case SSL_ERROR_WANT_ASYNC:
+ CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_ASYNC");
+ result = CURLE_OK;
+ goto out;
+#endif
+#ifdef SSL_ERROR_WANT_RETRY_VERIFY
+ case SSL_ERROR_WANT_RETRY_VERIFY:
+ result = CURLE_OK;
+ goto out;
+#endif
+ default:
+ result = cf_osslq_ssl_err(cf, data, detail, CURLE_COULDNT_CONNECT);
+ goto out;
+ }
+ }
+
+out:
+ if(result == CURLE_RECV_ERROR && ctx->tls.ssl && ctx->protocol_shutdown) {
+ /* When a QUIC server instance is shutting down, it may send us a
+ * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
+ * state. The CONNECT may work in the near future again. Indicate
+ * that as a "weird" reply. */
+ result = CURLE_WEIRD_SERVER_REPLY;
+ }
+
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(result) {
+ const char *r_ip = NULL;
+ int r_port = 0;
+
+ Curl_cf_socket_peek(cf->next, data, NULL, NULL,
+ &r_ip, &r_port, NULL, NULL);
+ infof(data, "QUIC connect to %s port %u failed: %s",
+ r_ip, r_port, curl_easy_strerror(result));
+ }
+#endif
+ if(!result)
+ result = check_and_set_expiry(cf, data);
+ if(result || *done)
+ CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static ssize_t h3_stream_open(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const void *buf, size_t len,
+ CURLcode *err)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = NULL;
+ struct dynhds h2_headers;
+ size_t nheader;
+ nghttp3_nv *nva = NULL;
+ int rc = 0;
+ unsigned int i;
+ ssize_t nwritten = -1;
+ nghttp3_data_reader reader;
+ nghttp3_data_reader *preader = NULL;
+
+ Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
+
+ *err = h3_data_setup(cf, data);
+ if(*err)
+ goto out;
+ stream = H3_STREAM_CTX(data);
+ DEBUGASSERT(stream);
+ if(!stream) {
+ *err = CURLE_FAILED_INIT;
+ goto out;
+ }
+
+ nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
+ if(nwritten < 0)
+ goto out;
+ if(!stream->h1.done) {
+ /* need more data */
+ goto out;
+ }
+ DEBUGASSERT(stream->h1.req);
+
+ *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
+ if(*err) {
+ nwritten = -1;
+ goto out;
+ }
+ /* no longer needed */
+ Curl_h1_req_parse_free(&stream->h1);
+
+ nheader = Curl_dynhds_count(&h2_headers);
+ nva = malloc(sizeof(nghttp3_nv) * nheader);
+ if(!nva) {
+ *err = CURLE_OUT_OF_MEMORY;
+ nwritten = -1;
+ goto out;
+ }
+
+ for(i = 0; i < nheader; ++i) {
+ struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
+ nva[i].name = (unsigned char *)e->name;
+ nva[i].namelen = e->namelen;
+ nva[i].value = (unsigned char *)e->value;
+ nva[i].valuelen = e->valuelen;
+ nva[i].flags = NGHTTP3_NV_FLAG_NONE;
+ }
+
+ DEBUGASSERT(stream->s.id == -1);
+ *err = cf_osslq_stream_open(&stream->s, ctx->tls.ssl, 0,
+ &ctx->stream_bufcp, data);
+ if(*err) {
+ failf(data, "can't get bidi streams");
+ *err = CURLE_SEND_ERROR;
+ goto out;
+ }
+
+ switch(data->state.httpreq) {
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ case HTTPREQ_POST_MIME:
+ case HTTPREQ_PUT:
+ /* known request body size or -1 */
+ if(data->state.infilesize != -1)
+ stream->upload_left = data->state.infilesize;
+ else
+ /* data sending without specifying the data amount up front */
+ stream->upload_left = -1; /* unknown */
+ break;
+ default:
+ /* there is not request body */
+ stream->upload_left = 0; /* no request body */
+ break;
+ }
+
+ stream->send_closed = (stream->upload_left == 0);
+ if(!stream->send_closed) {
+ reader.read_data = cb_h3_read_req_body;
+ preader = &reader;
+ }
+
+ rc = nghttp3_conn_submit_request(ctx->h3.conn, stream->s.id,
+ nva, nheader, preader, data);
+ if(rc) {
+ switch(rc) {
+ case NGHTTP3_ERR_CONN_CLOSING:
+ CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send, "
+ "connection is closing", stream->s.id);
+ break;
+ default:
+ CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send -> %d (%s)",
+ stream->s.id, rc, nghttp3_strerror(rc));
+ break;
+ }
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+
+ if(Curl_trc_is_verbose(data)) {
+ infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s",
+ stream->s.id, data->state.url);
+ for(i = 0; i < nheader; ++i) {
+ infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->s.id,
+ (int)nva[i].namelen, nva[i].name,
+ (int)nva[i].valuelen, nva[i].value);
+ }
+ }
+
+out:
+ free(nva);
+ Curl_dynhds_free(&h2_headers);
+ return nwritten;
+}
+
+static ssize_t cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
+ const void *buf, size_t len, CURLcode *err)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ struct cf_call_data save;
+ ssize_t nwritten;
+ CURLcode result;
+
+ CF_DATA_SAVE(save, cf, data);
+ DEBUGASSERT(cf->connected);
+ DEBUGASSERT(ctx->tls.ssl);
+ DEBUGASSERT(ctx->h3.conn);
+ *err = CURLE_OK;
+
+ result = cf_progress_ingress(cf, data);
+ if(result) {
+ *err = result;
+ nwritten = -1;
+ goto out;
+ }
+
+ result = cf_progress_egress(cf, data);
+ if(result) {
+ *err = result;
+ nwritten = -1;
+ goto out;
+ }
+
+ if(!stream || stream->s.id < 0) {
+ nwritten = h3_stream_open(cf, data, buf, len, err);
+ if(nwritten < 0) {
+ CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err);
+ goto out;
+ }
+ stream = H3_STREAM_CTX(data);
+ }
+ else if(stream->upload_blocked_len) {
+ /* the data in `buf` has already been submitted or added to the
+ * buffers, but have been EAGAINed on the last invocation. */
+ DEBUGASSERT(len >= stream->upload_blocked_len);
+ if(len < stream->upload_blocked_len) {
+ /* Did we get called again with a smaller `len`? This should not
+ * happen. We are not prepared to handle that. */
+ failf(data, "HTTP/3 send again with decreased length");
+ *err = CURLE_HTTP3;
+ nwritten = -1;
+ goto out;
+ }
+ nwritten = (ssize_t)stream->upload_blocked_len;
+ stream->upload_blocked_len = 0;
+ }
+ else if(stream->closed) {
+ if(stream->resp_hds_complete) {
+ /* Server decided to close the stream after having sent us a final
+ * response. This is valid if it is not interested in the request
+ * body. This happens on 30x or 40x responses.
+ * We silently discard the data sent, since this is not a transport
+ * error situation. */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
+ "on closed stream with response", stream->s.id);
+ *err = CURLE_OK;
+ nwritten = (ssize_t)len;
+ goto out;
+ }
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+ "-> stream closed", stream->s.id, len);
+ *err = CURLE_HTTP3;
+ nwritten = -1;
+ goto out;
+ }
+ else {
+ nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err);
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send, add to "
+ "sendbuf(len=%zu) -> %zd, %d",
+ stream->s.id, len, nwritten, *err);
+ if(nwritten < 0) {
+ goto out;
+ }
+
+ (void)nghttp3_conn_resume_stream(ctx->h3.conn, stream->s.id);
+ }
+
+ result = cf_progress_egress(cf, data);
+ if(result) {
+ *err = result;
+ nwritten = -1;
+ }
+
+ if(stream && nwritten > 0 && stream->sendbuf_len_in_flight) {
+ /* We have unacknowledged DATA and cannot report success to our
+ * caller. Instead we EAGAIN and remember how much we have already
+ * "written" into our various internal connection buffers. */
+ stream->upload_blocked_len = nwritten;
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), "
+ "%zu bytes in flight -> EGAIN", stream->s.id, len,
+ stream->sendbuf_len_in_flight);
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ }
+
+out:
+ result = check_and_set_expiry(cf, data);
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+ stream? stream->s.id : -1, len, nwritten, *err);
+ CF_DATA_RESTORE(cf, save);
+ return nwritten;
+}
+
+static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h3_stream_ctx *stream,
+ CURLcode *err)
+{
+ ssize_t nread = -1;
+
+ (void)cf;
+ if(stream->reset) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " reset by server", stream->s.id);
+ *err = stream->resp_hds_complete? CURLE_PARTIAL_FILE : CURLE_HTTP3;
+ goto out;
+ }
+ else if(!stream->resp_hds_complete) {
+ failf(data,
+ "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
+ " all response header fields, treated as error",
+ stream->s.id);
+ *err = CURLE_HTTP3;
+ goto out;
+ }
+ *err = CURLE_OK;
+ nread = 0;
+
+out:
+ return nread;
+}
+
+static ssize_t cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ ssize_t nread = -1;
+ struct cf_call_data save;
+ CURLcode result;
+
+ (void)ctx;
+ CF_DATA_SAVE(save, cf, data);
+ DEBUGASSERT(cf->connected);
+ DEBUGASSERT(ctx);
+ DEBUGASSERT(ctx->tls.ssl);
+ DEBUGASSERT(ctx->h3.conn);
+ *err = CURLE_OK;
+
+ if(!stream) {
+ *err = CURLE_RECV_ERROR;
+ goto out;
+ }
+
+ if(!Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ if(nread < 0) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->s.id, len, nread, *err);
+ goto out;
+ }
+ }
+
+ result = cf_progress_ingress(cf, data);
+ if(result) {
+ *err = result;
+ nread = -1;
+ goto out;
+ }
+
+ /* recvbuf had nothing before, maybe after progressing ingress? */
+ if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
+ nread = Curl_bufq_read(&stream->recvbuf,
+ (unsigned char *)buf, len, err);
+ if(nread < 0) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
+ "-> %zd, %d", stream->s.id, len, nread, *err);
+ goto out;
+ }
+ }
+
+ if(nread > 0) {
+ h3_drain_stream(cf, data);
+ }
+ else {
+ if(stream->closed) {
+ nread = recv_closed_stream(cf, data, stream, err);
+ goto out;
+ }
+ *err = CURLE_AGAIN;
+ nread = -1;
+ }
+
+out:
+ if(cf_progress_egress(cf, data)) {
+ *err = CURLE_SEND_ERROR;
+ nread = -1;
+ }
+ else {
+ CURLcode result2 = check_and_set_expiry(cf, data);
+ if(result2) {
+ *err = result2;
+ nread = -1;
+ }
+ }
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv(len=%zu) -> %zd, %d",
+ stream? stream->s.id : -1, len, nread, *err);
+ CF_DATA_RESTORE(cf, save);
+ return nread;
+}
+
+/*
+ * Called from transfer.c:data_pending to know if we should keep looping
+ * to receive more data from the connection.
+ */
+static bool cf_osslq_data_pending(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ const struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ (void)cf;
+ return stream && !Curl_bufq_is_empty(&stream->recvbuf);
+}
+
+static CURLcode cf_osslq_data_event(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int event, int arg1, void *arg2)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ CURLcode result = CURLE_OK;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ (void)arg1;
+ (void)arg2;
+ switch(event) {
+ case CF_CTRL_DATA_SETUP:
+ break;
+ case CF_CTRL_DATA_PAUSE:
+ result = h3_data_pause(cf, data, (arg1 != 0));
+ break;
+ case CF_CTRL_DATA_DETACH:
+ h3_data_done(cf, data);
+ break;
+ case CF_CTRL_DATA_DONE:
+ h3_data_done(cf, data);
+ break;
+ case CF_CTRL_DATA_DONE_SEND: {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ if(stream && !stream->send_closed) {
+ stream->send_closed = TRUE;
+ stream->upload_left = Curl_bufq_len(&stream->sendbuf);
+ (void)nghttp3_conn_resume_stream(ctx->h3.conn, stream->s.id);
+ }
+ break;
+ }
+ case CF_CTRL_DATA_IDLE: {
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
+ CURL_TRC_CF(data, cf, "data idle");
+ if(stream && !stream->closed) {
+ result = check_and_set_expiry(cf, data);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
+static bool cf_osslq_conn_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ bool alive = FALSE;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ *input_pending = FALSE;
+ if(!ctx->tls.ssl)
+ goto out;
+
+ /* TODO: how to check negotiated connection idle time? */
+
+ if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
+ goto out;
+
+ alive = TRUE;
+ if(*input_pending) {
+ CURLcode result;
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other transfer, there shouldn't be any data here,
+ only "protocol frames" */
+ *input_pending = FALSE;
+ result = cf_progress_ingress(cf, data);
+ CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result);
+ alive = result? FALSE : TRUE;
+ }
+
+out:
+ CF_DATA_RESTORE(cf, save);
+ return alive;
+}
+
+static void cf_osslq_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+
+ if(!ctx->tls.ssl) {
+ /* NOP */
+ }
+ else if(!cf->connected) {
+ /* during handshake, transfer has not started yet. we always
+ * add our socket for polling if SSL wants to send/recv */
+ Curl_pollset_set(data, ps, ctx->q.sockfd,
+ SSL_net_read_desired(ctx->tls.ssl),
+ SSL_net_write_desired(ctx->tls.ssl));
+ }
+ else {
+ /* once connected, we only modify the socket if it is present.
+ * this avoids adding it for paused transfers. */
+ bool want_recv, want_send;
+ Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+ if(want_recv || want_send) {
+ Curl_pollset_set(data, ps, ctx->q.sockfd,
+ SSL_net_read_desired(ctx->tls.ssl),
+ SSL_net_write_desired(ctx->tls.ssl));
+ }
+ }
+}
+
+static CURLcode cf_osslq_query(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query, int *pres1, void *pres2)
+{
+ struct cf_osslq_ctx *ctx = cf->ctx;
+ struct cf_call_data save;
+
+ switch(query) {
+ case CF_QUERY_MAX_CONCURRENT: {
+ /* TODO: how to get this? */
+ CF_DATA_SAVE(save, cf, data);
+ *pres1 = 100;
+ CURL_TRC_CF(data, cf, "query max_conncurrent -> %d", *pres1);
+ CF_DATA_RESTORE(cf, save);
+ return CURLE_OK;
+ }
+ case CF_QUERY_CONNECT_REPLY_MS:
+ if(ctx->got_first_byte) {
+ timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
+ }
+ else
+ *pres1 = -1;
+ return CURLE_OK;
+ case CF_QUERY_TIMER_CONNECT: {
+ struct curltime *when = pres2;
+ if(ctx->got_first_byte)
+ *when = ctx->first_byte_at;
+ return CURLE_OK;
+ }
+ case CF_QUERY_TIMER_APPCONNECT: {
+ struct curltime *when = pres2;
+ if(cf->connected)
+ *when = ctx->handshake_at;
+ return CURLE_OK;
+ }
+ default:
+ break;
+ }
+ return cf->next?
+ cf->next->cft->query(cf->next, data, query, pres1, pres2) :
+ CURLE_UNKNOWN_OPTION;
+}
+
+struct Curl_cftype Curl_cft_http3 = {
+ "HTTP/3",
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ 0,
+ cf_osslq_destroy,
+ cf_osslq_connect,
+ cf_osslq_close,
+ Curl_cf_def_get_host,
+ cf_osslq_adjust_pollset,
+ cf_osslq_data_pending,
+ cf_osslq_send,
+ cf_osslq_recv,
+ cf_osslq_data_event,
+ cf_osslq_conn_is_alive,
+ Curl_cf_def_conn_keep_alive,
+ cf_osslq_query,
+};
+
+CURLcode Curl_cf_osslq_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai)
+{
+ struct cf_osslq_ctx *ctx = NULL;
+ struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
+ CURLcode result;
+
+ (void)data;
+ ctx = calloc(1, sizeof(*ctx));
+ if(!ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ cf_osslq_ctx_clear(ctx);
+
+ result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
+ if(result)
+ goto out;
+
+ result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
+ if(result)
+ goto out;
+
+ cf->conn = conn;
+ udp_cf->conn = cf->conn;
+ udp_cf->sockindex = cf->sockindex;
+ cf->next = udp_cf;
+
+out:
+ *pcf = (!result)? cf : NULL;
+ if(result) {
+ if(udp_cf)
+ Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
+ Curl_safefree(cf);
+ Curl_safefree(ctx);
+ }
+ return result;
+}
+
+bool Curl_conn_is_osslq(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex)
+{
+ struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
+
+ (void)data;
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_http3)
+ return TRUE;
+ if(cf->cft->flags & CF_TYPE_IP_CONNECT)
+ return FALSE;
+ }
+ return FALSE;
+}
+
+/*
+ * Store ngtcp2 version info in this buffer.
+ */
+void Curl_osslq_ver(char *p, size_t len)
+{
+ const nghttp3_info *ht3 = nghttp3_version(0);
+ (void)msnprintf(p, len, "nghttp3/%s", ht3->version_str);
+}
+
+#endif /* USE_OPENSSL_QUIC && USE_NGHTTP3 */
diff --git a/lib/vquic/curl_osslq.h b/lib/vquic/curl_osslq.h
new file mode 100644
index 000000000..0e12d7023
--- /dev/null
+++ b/lib/vquic/curl_osslq.h
@@ -0,0 +1,51 @@
+#ifndef HEADER_CURL_VQUIC_CURL_OSSLQ_H
+#define HEADER_CURL_VQUIC_CURL_OSSLQ_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
+
+struct Curl_cfilter;
+
+#include "urldata.h"
+
+void Curl_osslq_ver(char *p, size_t len);
+
+CURLcode Curl_cf_osslq_create(struct Curl_cfilter **pcf,
+ struct Curl_easy *data,
+ struct connectdata *conn,
+ const struct Curl_addrinfo *ai);
+
+bool Curl_conn_is_osslq(const struct Curl_easy *data,
+ const struct connectdata *conn,
+ int sockindex);
+#endif
+
+#endif /* HEADER_CURL_VQUIC_CURL_OSSLQ_H */
diff --git a/lib/vquic/curl_quiche.c b/lib/vquic/curl_quiche.c
index 3f5d32743..fcb0eb8f8 100644
--- a/lib/vquic/curl_quiche.c
+++ b/lib/vquic/curl_quiche.c
@@ -43,6 +43,7 @@
#include "http1.h"
#include "vquic.h"
#include "vquic_int.h"
+#include "vquic-tls.h"
#include "curl_quiche.h"
#include "transfer.h"
#include "inet_pton.h"
@@ -55,10 +56,10 @@
#include "curl_memory.h"
#include "memdebug.h"
-/* #define DEBUG_QUICHE */
+/* HTTP/3 error values defined in RFC 9114, ch. 8.1 */
+#define CURL_H3_NO_ERROR (0x0100)
#define QUIC_MAX_STREAMS (100)
-#define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
#define H3_STREAM_WINDOW_SIZE (128 * 1024)
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
@@ -84,30 +85,22 @@ void Curl_quiche_ver(char *p, size_t len)
(void)msnprintf(p, len, "quiche/%s", quiche_version());
}
-static void keylog_callback(const SSL *ssl, const char *line)
-{
- (void)ssl;
- Curl_tls_keylog_write_line(line);
-}
-
struct cf_quiche_ctx {
struct cf_quic_ctx q;
+ struct ssl_peer peer;
+ struct quic_tls_ctx tls;
quiche_conn *qconn;
quiche_config *cfg;
quiche_h3_conn *h3c;
quiche_h3_config *h3config;
uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
- SSL_CTX *sslctx;
- SSL *ssl;
struct curltime started_at; /* time the current attempt started */
struct curltime handshake_at; /* time connect handshake finished */
- struct curltime first_byte_at; /* when first byte was recvd */
struct curltime reconnect_at; /* time the next attempt should start */
struct bufc_pool stream_bufcp; /* chunk pool for streams */
curl_off_t data_recvd;
- size_t sends_on_hold; /* # of streams with SEND_HOLD set */
+ uint64_t max_idle_ms; /* max idle time for QUIC conn */
BIT(goaway); /* got GOAWAY from server */
- BIT(got_first_byte); /* if first byte was received */
BIT(x509_store_setup); /* if x509 store has been set up */
};
@@ -122,108 +115,23 @@ static void quiche_debug_log(const char *line, void *argp)
static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
{
if(ctx) {
- vquic_ctx_free(&ctx->q);
- if(ctx->qconn)
- quiche_conn_free(ctx->qconn);
- if(ctx->h3config)
- quiche_h3_config_free(ctx->h3config);
if(ctx->h3c)
quiche_h3_conn_free(ctx->h3c);
+ if(ctx->h3config)
+ quiche_h3_config_free(ctx->h3config);
+ if(ctx->qconn)
+ quiche_conn_free(ctx->qconn);
if(ctx->cfg)
quiche_config_free(ctx->cfg);
+ /* quiche just freed ctx->tls.ssl */
+ ctx->tls.ssl = NULL;
+ Curl_vquic_tls_cleanup(&ctx->tls);
+ Curl_ssl_peer_cleanup(&ctx->peer);
+ vquic_ctx_free(&ctx->q);
Curl_bufcp_free(&ctx->stream_bufcp);
- memset(ctx, 0, sizeof(*ctx));
- }
-}
-
-static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_quiche_ctx *ctx = cf->ctx;
-
- if(!ctx->x509_store_setup) {
- if(cf->conn->ssl_config.verifypeer) {
- const char * const ssl_cafile = cf->conn->ssl_config.CAfile;
- const char * const ssl_capath = cf->conn->ssl_config.CApath;
- if(ssl_cafile || ssl_capath) {
- SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL);
- /* tell OpenSSL where to find CA certificates that are used to verify
- the server's certificate. */
- if(!SSL_CTX_load_verify_locations(ctx->sslctx, ssl_cafile,
- ssl_capath)) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return CURLE_SSL_CACERT_BADFILE;
- }
- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
- }
-#ifdef CURL_CA_FALLBACK
- else {
- /* 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(ctx->sslctx);
- }
-#endif
- }
- ctx->x509_store_setup = TRUE;
- }
- return CURLE_OK;
-}
-
-static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- struct cf_quiche_ctx *ctx = cf->ctx;
- unsigned char checkip[16];
- struct connectdata *conn = data->conn;
- const char *curves = conn->ssl_config.curves;
-
- DEBUGASSERT(!ctx->sslctx);
- ctx->sslctx = SSL_CTX_new(TLS_method());
- if(!ctx->sslctx)
- return CURLE_OUT_OF_MEMORY;
-
- SSL_CTX_set_alpn_protos(ctx->sslctx,
- (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
- sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
-
- SSL_CTX_set_default_verify_paths(ctx->sslctx);
- /* 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(ctx->sslctx, keylog_callback);
- }
-
- if(curves && !SSL_CTX_set1_curves_list(ctx->sslctx, curves)) {
- failf(data, "failed setting curves list for QUIC: '%s'", curves);
- return CURLE_SSL_CIPHER;
- }
-
- ctx->ssl = SSL_new(ctx->sslctx);
- if(!ctx->ssl)
- return CURLE_QUIC_CONNECT_ERROR;
-
- SSL_set_app_data(ctx->ssl, cf);
-
- if((0 == Curl_inet_pton(AF_INET, cf->conn->host.name, checkip))
-#ifdef ENABLE_IPV6
- && (0 == Curl_inet_pton(AF_INET6, cf->conn->host.name, checkip))
-#endif
- ) {
- char *snihost = Curl_ssl_snihost(data, cf->conn->host.name, NULL);
- if(!snihost || !SSL_set_tlsext_host_name(ctx->ssl, snihost)) {
- failf(data, "Failed set SNI");
- SSL_free(ctx->ssl);
- ctx->ssl = NULL;
- return CURLE_QUIC_CONNECT_ERROR;
- }
+ memset(ctx, 0, sizeof(*ctx));
}
-
- return CURLE_OK;
}
/**
@@ -240,6 +148,7 @@ struct stream_ctx {
bool send_closed; /* stream is locally closed */
bool resp_hds_complete; /* complete, final response has been received */
bool resp_got_header; /* TRUE when h3 stream has recvd some HEADER */
+ BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
};
#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
@@ -249,56 +158,20 @@ struct stream_ctx {
#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
H3_STREAM_CTX(d)->id : -2)
-static bool stream_send_is_suspended(struct Curl_easy *data)
-{
- return (data->req.keepon & KEEP_SEND_HOLD);
-}
-
-static void stream_send_suspend(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_quiche_ctx *ctx = cf->ctx;
-
- if((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) {
- data->req.keepon |= KEEP_SEND_HOLD;
- ++ctx->sends_on_hold;
- if(H3_STREAM_ID(data) >= 0)
- CURL_TRC_CF(data, cf, "[%"PRId64"] suspend sending",
- H3_STREAM_ID(data));
- else
- CURL_TRC_CF(data, cf, "[%s] suspend sending", data->state.url);
- }
-}
-
-static void stream_send_resume(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_quiche_ctx *ctx = cf->ctx;
-
- if(stream_send_is_suspended(data)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- --ctx->sends_on_hold;
- if(H3_STREAM_ID(data) >= 0)
- CURL_TRC_CF(data, cf, "[%"PRId64"] resume sending",
- H3_STREAM_ID(data));
- else
- CURL_TRC_CF(data, cf, "[%s] resume sending", data->state.url);
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
- }
-}
-
static void check_resumes(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- struct cf_quiche_ctx *ctx = cf->ctx;
struct Curl_easy *sdata;
-
- if(ctx->sends_on_hold) {
- DEBUGASSERT(data->multi);
- for(sdata = data->multi->easyp;
- sdata && ctx->sends_on_hold; sdata = sdata->next) {
- if(stream_send_is_suspended(sdata)) {
- stream_send_resume(cf, sdata);
+ struct stream_ctx *stream;
+
+ DEBUGASSERT(data->multi);
+ for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
+ if(sdata->conn == data->conn) {
+ stream = H3_STREAM_CTX(sdata);
+ if(stream && stream->quic_flow_blocked) {
+ stream->quic_flow_blocked = FALSE;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ CURL_TRC_CF(data, cf, "[%"PRId64"] unblock", stream->id);
}
}
}
@@ -333,9 +206,15 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
(void)cf;
if(stream) {
CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
- if(stream_send_is_suspended(data)) {
- data->req.keepon &= ~KEEP_SEND_HOLD;
- --ctx->sends_on_hold;
+ if(ctx->qconn && !stream->closed) {
+ quiche_conn_stream_shutdown(ctx->qconn, stream->id,
+ QUICHE_SHUTDOWN_READ, CURL_H3_NO_ERROR);
+ if(!stream->send_closed) {
+ quiche_conn_stream_shutdown(ctx->qconn, stream->id,
+ QUICHE_SHUTDOWN_WRITE, CURL_H3_NO_ERROR);
+ stream->send_closed = TRUE;
+ }
+ stream->closed = TRUE;
}
Curl_bufq_free(&stream->recvbuf);
Curl_h1_req_parse_free(&stream->h1);
@@ -354,8 +233,8 @@ static void drain_stream(struct Curl_cfilter *cf,
bits = CURL_CSELECT_IN;
if(stream && !stream->send_closed && stream->upload_left)
bits |= CURL_CSELECT_OUT;
- if(data->state.dselect_bits != bits) {
- data->state.dselect_bits = bits;
+ if(data->state.select_bits != bits) {
+ data->state.select_bits = bits;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
@@ -590,7 +469,6 @@ static CURLcode h3_process_event(struct Curl_cfilter *cf,
}
stream->closed = TRUE;
streamclose(cf->conn, "End of stream");
- data->req.keepon &= ~KEEP_SEND_HOLD;
break;
case QUICHE_H3_EVENT_GOAWAY:
@@ -686,7 +564,7 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
return CURLE_OK;
}
else if(QUICHE_ERR_TLS_FAIL == nread) {
- long verify_ok = SSL_get_verify_result(ctx->ssl);
+ long verify_ok = SSL_get_verify_result(ctx->tls.ssl);
if(verify_ok != X509_V_OK) {
failf(r->data, "SSL certificate problem: %s",
X509_verify_cert_error_string(verify_ok));
@@ -714,7 +592,7 @@ static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
CURLcode result;
DEBUGASSERT(ctx->qconn);
- result = quic_x509_store_setup(cf, data);
+ result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
if(result)
return result;
@@ -854,7 +732,7 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
if(stream->reset) {
failf(data,
"HTTP/3 stream %" PRId64 " reset by server", stream->id);
- *err = stream->resp_got_header? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
+ *err = stream->resp_got_header? CURLE_PARTIAL_FILE : CURLE_HTTP3;
CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv, was reset -> %d",
stream->id, *err);
}
@@ -864,7 +742,7 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
" all response header fields, treated as error",
stream->id);
/* *err = CURLE_PARTIAL_FILE; */
- *err = CURLE_RECV_ERROR;
+ *err = CURLE_HTTP3;
CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv, closed incomplete"
" -> %d", stream->id, *err);
}
@@ -883,6 +761,8 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
ssize_t nread = -1;
CURLcode result;
+ vquic_ctx_update_time(&ctx->q);
+
if(!stream) {
*err = CURLE_RECV_ERROR;
return -1;
@@ -1035,9 +915,8 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) {
/* quiche seems to report this error if the connection window is
* exhausted. Which happens frequently and intermittent. */
- CURL_TRC_CF(data, cf, "send_request(%s) rejected with BLOCKED",
- data->state.url);
- stream_send_suspend(cf, data);
+ CURL_TRC_CF(data, cf, "[%"PRId64"] blocked", stream->id);
+ stream->quic_flow_blocked = TRUE;
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
@@ -1081,6 +960,8 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
CURLcode result;
ssize_t nwritten;
+ vquic_ctx_update_time(&ctx->q);
+
*err = cf_process_ingress(cf, data);
if(*err) {
nwritten = -1;
@@ -1093,6 +974,28 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
goto out;
stream = H3_STREAM_CTX(data);
}
+ else if(stream->closed) {
+ if(stream->resp_hds_complete) {
+ /* sending request body on a stream that has been closed by the
+ * server. If the server has send us a final response, we should
+ * silently discard the send data.
+ * This happens for example on redirects where the server, instead
+ * of reading the full request body just closed the stream after
+ * sending the 30x response.
+ * This is sort of a race: had the transfer loop called recv first,
+ * it would see the response and stop/discard sending on its own- */
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
+ "on closed stream with response", stream->id);
+ *err = CURLE_OK;
+ nwritten = (ssize_t)len;
+ goto out;
+ }
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+ "-> stream closed", stream->id, len);
+ *err = CURLE_HTTP3;
+ nwritten = -1;
+ goto out;
+ }
else {
bool eof = (stream->upload_left >= 0 &&
(curl_off_t)len >= stream->upload_left);
@@ -1104,26 +1007,17 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
"-> window exhausted", stream->id, len);
- stream_send_suspend(cf, data);
+ stream->quic_flow_blocked = TRUE;
}
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
}
- else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE &&
- stream->closed && stream->resp_hds_complete) {
- /* sending request body on a stream that has been closed by the
- * server. If the server has send us a final response, we should
- * silently discard the send data.
- * This happens for example on redirects where the server, instead
- * of reading the full request body just closed the stream after
- * sending the 30x response.
- * This is sort of a race: had the transfer loop called recv first,
- * it would see the response and stop/discard sending on its own- */
- CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
- "on closed stream with response", stream->id);
- *err = CURLE_OK;
- nwritten = (ssize_t)len;
+ else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) {
+ CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
+ "-> invalid stream state", stream->id, len);
+ *err = CURLE_HTTP3;
+ nwritten = -1;
goto out;
}
else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
@@ -1173,30 +1067,35 @@ static bool stream_is_writeable(struct Curl_cfilter *cf,
struct cf_quiche_ctx *ctx = cf->ctx;
struct stream_ctx *stream = H3_STREAM_CTX(data);
- return stream &&
- quiche_conn_stream_writable(ctx->qconn, (uint64_t)stream->id, 1);
+ return stream && (quiche_conn_stream_writable(ctx->qconn,
+ (uint64_t)stream->id, 1) > 0);
}
-static int cf_quiche_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
struct cf_quiche_ctx *ctx = cf->ctx;
- struct SingleRequest *k = &data->req;
- int rv = GETSOCK_BLANK;
+ bool want_recv, want_send;
- socks[0] = ctx->q.sockfd;
+ if(!ctx->qconn)
+ return;
- /* in an HTTP/3 connection we can basically always get a frame so we should
- always be ready for one */
- rv |= GETSOCK_READSOCK(0);
+ Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
+ if(want_recv || want_send) {
+ struct stream_ctx *stream = H3_STREAM_CTX(data);
+ bool c_exhaust, s_exhaust;
- /* we're still uploading or the HTTP/3 layer wants to send data */
- if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
- && stream_is_writeable(cf, data))
- rv |= GETSOCK_WRITESOCK(0);
+ c_exhaust = FALSE; /* Have not found any call in quiche that tells
+ us if the connection itself is blocked */
+ s_exhaust = want_send && stream && stream->id >= 0 &&
+ (stream->quic_flow_blocked || !stream_is_writeable(cf, data));
+ want_recv = (want_recv || c_exhaust || s_exhaust);
+ want_send = (!s_exhaust && want_send) ||
+ !Curl_bufq_is_empty(&ctx->q.sendbuf);
- return rv;
+ Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
+ }
}
/*
@@ -1238,10 +1137,12 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
- case CF_CTRL_DATA_DONE: {
+ case CF_CTRL_DATA_DETACH:
+ h3_data_done(cf, data);
+ break;
+ case CF_CTRL_DATA_DONE:
h3_data_done(cf, data);
break;
- }
case CF_CTRL_DATA_DONE_SEND: {
struct stream_ctx *stream = H3_STREAM_CTX(data);
if(stream && !stream->send_closed) {
@@ -1272,61 +1173,6 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
return result;
}
-static CURLcode cf_verify_peer(struct Curl_cfilter *cf,
- struct Curl_easy *data)
-{
- struct cf_quiche_ctx *ctx = cf->ctx;
- CURLcode result = CURLE_OK;
-
- cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- cf->conn->httpversion = 30;
- cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
-
- if(cf->conn->ssl_config.verifyhost) {
- X509 *server_cert;
- server_cert = SSL_get_peer_certificate(ctx->ssl);
- if(!server_cert) {
- result = CURLE_PEER_FAILED_VERIFICATION;
- goto out;
- }
- result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
- X509_free(server_cert);
- if(result)
- goto out;
- }
- else
- CURL_TRC_CF(data, cf, "Skipped certificate verification");
-
- ctx->h3config = quiche_h3_config_new();
- if(!ctx->h3config) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
-
- /* Create a new HTTP/3 connection on the QUIC connection. */
- ctx->h3c = quiche_h3_conn_new_with_transport(ctx->qconn, ctx->h3config);
- if(!ctx->h3c) {
- result = CURLE_OUT_OF_MEMORY;
- goto out;
- }
- if(data->set.ssl.certinfo)
- /* asked to gather certificate info */
- (void)Curl_ossl_certchain(data, ctx->ssl);
-
-out:
- if(result) {
- if(ctx->h3config) {
- quiche_h3_config_free(ctx->h3config);
- ctx->h3config = NULL;
- }
- if(ctx->h3c) {
- quiche_h3_conn_free(ctx->h3c);
- ctx->h3c = NULL;
- }
- }
- return result;
-}
-
static CURLcode cf_connect_start(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@@ -1345,6 +1191,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
debug_log_init = 1;
}
#endif
+ ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
H3_STREAM_POOL_SPARES);
ctx->data_recvd = 0;
@@ -1353,13 +1200,17 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
if(result)
return result;
+ result = Curl_ssl_peer_init(&ctx->peer, cf);
+ if(result)
+ return result;
+
ctx->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
if(!ctx->cfg) {
failf(data, "can't create quiche config");
return CURLE_FAILED_INIT;
}
quiche_config_enable_pacing(ctx->cfg, false);
- quiche_config_set_max_idle_timeout(ctx->cfg, QUIC_IDLE_TIMEOUT);
+ quiche_config_set_max_idle_timeout(ctx->cfg, ctx->max_idle_ms * 1000);
quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024)
/* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */);
quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS);
@@ -1381,9 +1232,10 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
- 1);
- DEBUGASSERT(!ctx->ssl);
- DEBUGASSERT(!ctx->sslctx);
- result = quic_ssl_setup(cf, data);
+ result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
+ QUICHE_H3_APPLICATION_PROTOCOL,
+ sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1,
+ NULL, cf);
if(result)
return result;
@@ -1404,14 +1256,14 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
(struct sockaddr *)&ctx->q.local_addr,
ctx->q.local_addrlen,
&sockaddr->sa_addr, sockaddr->addrlen,
- ctx->cfg, ctx->ssl, false);
+ ctx->cfg, ctx->tls.ssl, false);
if(!ctx->qconn) {
failf(data, "can't create quiche connection");
return CURLE_OUT_OF_MEMORY;
}
/* Known to not work on Windows */
-#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
+#if !defined(_WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
{
int qfd;
(void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd);
@@ -1443,13 +1295,24 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
return CURLE_OK;
}
+static CURLcode cf_quiche_verify_peer(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ struct cf_quiche_ctx *ctx = cf->ctx;
+
+ cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ cf->conn->httpversion = 30;
+ cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+
+ return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
+}
+
static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
struct cf_quiche_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
- struct curltime now;
if(cf->connected) {
*done = TRUE;
@@ -1464,9 +1327,10 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
}
*done = FALSE;
- now = Curl_now();
+ vquic_ctx_update_time(&ctx->q);
- if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
+ if(ctx->reconnect_at.tv_sec &&
+ Curl_timediff(ctx->q.last_op, ctx->reconnect_at) < 0) {
/* Not time yet to attempt the next connect */
CURL_TRC_CF(data, cf, "waiting for reconnect time");
goto out;
@@ -1476,7 +1340,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
result = cf_connect_start(cf, data);
if(result)
goto out;
- ctx->started_at = now;
+ ctx->started_at = ctx->q.last_op;
result = cf_flush_egress(cf, data);
/* we do not expect to be able to recv anything yet */
goto out;
@@ -1491,12 +1355,24 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
goto out;
if(quiche_conn_is_established(ctx->qconn)) {
+ ctx->handshake_at = ctx->q.last_op;
CURL_TRC_CF(data, cf, "handshake complete after %dms",
- (int)Curl_timediff(now, ctx->started_at));
- ctx->handshake_at = now;
- result = cf_verify_peer(cf, data);
+ (int)Curl_timediff(ctx->handshake_at, ctx->started_at));
+ result = cf_quiche_verify_peer(cf, data);
if(!result) {
CURL_TRC_CF(data, cf, "peer verified");
+ ctx->h3config = quiche_h3_config_new();
+ if(!ctx->h3config) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ /* Create a new HTTP/3 connection on the QUIC connection. */
+ ctx->h3c = quiche_h3_conn_new_with_transport(ctx->qconn, ctx->h3config);
+ if(!ctx->h3c) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
cf->connected = TRUE;
cf->conn->alpn = CURL_HTTP_VERSION_3;
*done = TRUE;
@@ -1506,27 +1382,9 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
else if(quiche_conn_is_draining(ctx->qconn)) {
/* When a QUIC server instance is shutting down, it may send us a
* CONNECTION_CLOSE right away. Our connection then enters the DRAINING
- * state.
- * This may be a stopping of the service or it may be that the server
- * is reloading and a new instance will start serving soon.
- * In any case, we tear down our socket and start over with a new one.
- * We re-open the underlying UDP cf right now, but do not start
- * connecting until called again.
- */
- int reconn_delay_ms = 200;
-
- CURL_TRC_CF(data, cf, "connect, remote closed, reconnect after %dms",
- reconn_delay_ms);
- Curl_conn_cf_close(cf->next, data);
- cf_quiche_ctx_clear(ctx);
- result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
- if(!result && *done) {
- *done = FALSE;
- ctx->reconnect_at = Curl_now();
- ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
- Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
- result = CURLE_OK;
- }
+ * state. The CONNECT may work in the near future again. Indicate
+ * that as a "weird" reply. */
+ result = CURLE_WEIRD_SERVER_REPLY;
}
out:
@@ -1550,6 +1408,7 @@ static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data)
if(ctx) {
if(ctx->qconn) {
+ vquic_ctx_update_time(&ctx->q);
(void)quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0);
/* flushing the egress is not a failsafe way to deliver all the
outstanding packets, but we also don't want to get stuck here... */
@@ -1586,8 +1445,8 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
return CURLE_OK;
}
case CF_QUERY_CONNECT_REPLY_MS:
- if(ctx->got_first_byte) {
- timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
+ if(ctx->q.got_first_byte) {
+ timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
*pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
}
else
@@ -1595,8 +1454,8 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
return CURLE_OK;
case CF_QUERY_TIMER_CONNECT: {
struct curltime *when = pres2;
- if(ctx->got_first_byte)
- *when = ctx->first_byte_at;
+ if(ctx->q.got_first_byte)
+ *when = ctx->q.first_byte_at;
return CURLE_OK;
}
case CF_QUERY_TIMER_APPCONNECT: {
@@ -1617,9 +1476,32 @@ static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending)
{
+ struct cf_quiche_ctx *ctx = cf->ctx;
bool alive = TRUE;
*input_pending = FALSE;
+ if(!ctx->qconn)
+ return FALSE;
+
+ /* Both sides of the QUIC connection announce they max idle times in
+ * the transport parameters. Look at the minimum of both and if
+ * we exceed this, regard the connection as dead. The other side
+ * may have completely purged it and will no longer respond
+ * to any packets from us. */
+ {
+ quiche_transport_params qpeerparams;
+ timediff_t idletime;
+ uint64_t idle_ms = ctx->max_idle_ms;
+
+ if(quiche_conn_peer_transport_params(ctx->qconn, &qpeerparams) &&
+ qpeerparams.peer_max_idle_timeout &&
+ qpeerparams.peer_max_idle_timeout < idle_ms)
+ idle_ms = qpeerparams.peer_max_idle_timeout;
+ idletime = Curl_timediff(Curl_now(), cf->conn->lastused);
+ if(idletime > 0 && (uint64_t)idletime > idle_ms)
+ return FALSE;
+ }
+
if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
return FALSE;
@@ -1646,7 +1528,7 @@ struct Curl_cftype Curl_cft_http3 = {
cf_quiche_connect,
cf_quiche_close,
Curl_cf_def_get_host,
- cf_quiche_get_select_socks,
+ cf_quiche_adjust_pollset,
cf_quiche_data_pending,
cf_quiche_send,
cf_quiche_recv,
@@ -1667,7 +1549,7 @@ CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/lib/vquic/vquic-tls.c b/lib/vquic/vquic-tls.c
new file mode 100644
index 000000000..cc7794e40
--- /dev/null
+++ b/lib/vquic/vquic-tls.c
@@ -0,0 +1,609 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(ENABLE_QUIC) && \
+ (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
+
+#ifdef USE_OPENSSL
+#include <openssl/err.h>
+#include "vtls/openssl.h"
+#elif defined(USE_GNUTLS)
+#include <gnutls/abstract.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/crypto.h>
+#include <nettle/sha2.h>
+#include "vtls/gtls.h"
+#elif defined(USE_WOLFSSL)
+#include <wolfssl/options.h>
+#include <wolfssl/ssl.h>
+#include <wolfssl/quic.h>
+#include "vtls/wolfssl.h"
+#endif
+
+#include "urldata.h"
+#include "curl_trc.h"
+#include "cfilters.h"
+#include "multiif.h"
+#include "vtls/keylog.h"
+#include "vtls/vtls.h"
+#include "vquic-tls.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
+
+#ifdef USE_OPENSSL
+#define QUIC_CIPHERS \
+ "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
+ "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
+#define QUIC_GROUPS "P-256:X25519:P-384:P-521"
+#elif defined(USE_GNUTLS)
+#define QUIC_PRIORITY \
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
+ "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
+ "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
+ "%DISABLE_TLS13_COMPAT_MODE"
+#elif defined(USE_WOLFSSL)
+#define QUIC_CIPHERS \
+ "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_" \
+ "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
+#define QUIC_GROUPS "P-256:P-384:P-521"
+#endif
+
+
+#ifdef USE_OPENSSL
+
+static void keylog_callback(const SSL *ssl, const char *line)
+{
+ (void)ssl;
+ Curl_tls_keylog_write_line(line);
+}
+
+static CURLcode curl_ossl_init_ctx(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ Curl_vquic_tls_ctx_setup *ctx_setup)
+{
+ struct ssl_primary_config *conn_config;
+ CURLcode result = CURLE_FAILED_INIT;
+
+ DEBUGASSERT(!ctx->ssl_ctx);
+#ifdef USE_OPENSSL_QUIC
+ ctx->ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
+#else
+ ctx->ssl_ctx = SSL_CTX_new(TLS_method());
+#endif
+ if(!ctx->ssl_ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config) {
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+
+ if(ctx_setup) {
+ result = ctx_setup(ctx, cf, data);
+ if(result)
+ goto out;
+ }
+
+ SSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
+
+ {
+ const char *curves = conn_config->curves ?
+ conn_config->curves : QUIC_GROUPS;
+ if(!SSL_CTX_set1_curves_list(ctx->ssl_ctx, curves)) {
+ failf(data, "failed setting curves list for QUIC: '%s'", curves);
+ return CURLE_SSL_CIPHER;
+ }
+ }
+
+#ifndef OPENSSL_IS_BORINGSSL
+ {
+ const char *ciphers13 = conn_config->cipher_list13 ?
+ conn_config->cipher_list13 : QUIC_CIPHERS;
+ if(SSL_CTX_set_ciphersuites(ctx->ssl_ctx, ciphers13) != 1) {
+ failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "QUIC cipher selection: %s", ciphers13);
+ }
+#endif
+
+ /* 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(ctx->ssl_ctx, keylog_callback);
+ }
+
+ /* OpenSSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+ * anyway. In the latter case the result of the verification is checked with
+ * SSL_get_verify_result() below. */
+ SSL_CTX_set_verify(ctx->ssl_ctx, conn_config->verifypeer ?
+ SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
+
+ /* give application a chance to interfere with SSL set up. */
+ if(data->set.ssl.fsslctx) {
+ /* When a user callback is installed to modify the SSL_CTX,
+ * we need to do the full initialization before calling it.
+ * See: #11800 */
+ if(!ctx->x509_store_setup) {
+ result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
+ if(result)
+ goto out;
+ ctx->x509_store_setup = TRUE;
+ }
+ Curl_set_in_callback(data, true);
+ result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
+ data->set.ssl.fsslctxp);
+ Curl_set_in_callback(data, false);
+ if(result) {
+ failf(data, "error signaled by ssl ctx callback");
+ goto out;
+ }
+ }
+ result = CURLE_OK;
+
+out:
+ if(result && ctx->ssl_ctx) {
+ SSL_CTX_free(ctx->ssl_ctx);
+ ctx->ssl_ctx = NULL;
+ }
+ return result;
+}
+
+static CURLcode curl_ossl_set_client_cert(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ SSL_CTX *ssl_ctx = ctx->ssl_ctx;
+ const struct ssl_config_data *ssl_config;
+
+ ssl_config = Curl_ssl_cf_get_config(cf, data);
+ DEBUGASSERT(ssl_config);
+
+ if(ssl_config->primary.clientcert ||
+ ssl_config->primary.cert_blob ||
+ ssl_config->cert_type) {
+ return Curl_ossl_set_client_cert(
+ data, ssl_ctx, ssl_config->primary.clientcert,
+ ssl_config->primary.cert_blob, ssl_config->cert_type,
+ ssl_config->key, ssl_config->key_blob,
+ ssl_config->key_type, ssl_config->key_passwd);
+ }
+
+ return CURLE_OK;
+}
+
+/** SSL callbacks ***/
+
+static CURLcode curl_ossl_init_ssl(struct quic_tls_ctx *ctx,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const char *alpn, size_t alpn_len,
+ void *user_data)
+{
+ DEBUGASSERT(!ctx->ssl);
+ ctx->ssl = SSL_new(ctx->ssl_ctx);
+
+ SSL_set_app_data(ctx->ssl, user_data);
+ SSL_set_connect_state(ctx->ssl);
+#ifndef USE_OPENSSL_QUIC
+ SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
+#endif
+
+ if(alpn)
+ SSL_set_alpn_protos(ctx->ssl, (const uint8_t *)alpn, (int)alpn_len);
+
+ if(peer->sni) {
+ if(!SSL_set_tlsext_host_name(ctx->ssl, peer->sni)) {
+ failf(data, "Failed set SNI");
+ SSL_free(ctx->ssl);
+ ctx->ssl = NULL;
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+ }
+ return CURLE_OK;
+}
+
+#elif defined(USE_GNUTLS)
+static int keylog_callback(gnutls_session_t session, const char *label,
+ const gnutls_datum_t *secret)
+{
+ gnutls_datum_t crandom;
+ gnutls_datum_t srandom;
+
+ gnutls_session_get_random(session, &crandom, &srandom);
+ if(crandom.size != 32) {
+ return -1;
+ }
+
+ Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
+ return 0;
+}
+
+static CURLcode curl_gtls_init_ctx(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const char *alpn, size_t alpn_len,
+ Curl_vquic_tls_ctx_setup *ctx_setup,
+ void *user_data)
+{
+ struct ssl_primary_config *conn_config;
+ CURLcode result;
+ gnutls_datum_t alpns[5];
+ /* this will need some attention when HTTPS proxy over QUIC get fixed */
+ long * const pverifyresult = &data->set.ssl.certverifyresult;
+ int rc;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
+ DEBUGASSERT(ctx->gtls == NULL);
+ ctx->gtls = calloc(1, sizeof(*(ctx->gtls)));
+ if(!ctx->gtls)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = gtls_client_init(data, conn_config, &data->set.ssl,
+ peer, ctx->gtls, pverifyresult);
+ if(result)
+ return result;
+
+ gnutls_session_set_ptr(ctx->gtls->session, user_data);
+
+ if(ctx_setup) {
+ result = ctx_setup(ctx, cf, data);
+ if(result)
+ return result;
+ }
+
+ rc = gnutls_priority_set_direct(ctx->gtls->session, QUIC_PRIORITY, NULL);
+ if(rc < 0) {
+ CURL_TRC_CF(data, cf, "gnutls_priority_set_direct failed: %s\n",
+ gnutls_strerror(rc));
+ return CURLE_QUIC_CONNECT_ERROR;
+ }
+
+ /* 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(ctx->gtls->session, keylog_callback);
+ }
+
+ /* convert the ALPN string from our arguments to a list of strings
+ * that gnutls wants and will convert internally back to this very
+ * string for sending to the server. nice. */
+ if(alpn) {
+ size_t i, alen = alpn_len;
+ unsigned char *s = (unsigned char *)alpn;
+ unsigned char slen;
+ for(i = 0; (i < ARRAYSIZE(alpns)) && alen; ++i) {
+ slen = s[0];
+ if(slen >= alen)
+ return CURLE_FAILED_INIT;
+ alpns[i].data = s + 1;
+ alpns[i].size = slen;
+ s += slen + 1;
+ alen -= (size_t)slen + 1;
+ }
+ if(alen) /* not all alpn chars used, wrong format or too many */
+ return CURLE_FAILED_INIT;
+ if(i) {
+ gnutls_alpn_set_protocols(ctx->gtls->session,
+ alpns, (unsigned int)i,
+ GNUTLS_ALPN_MANDATORY);
+ }
+ }
+
+ return CURLE_OK;
+}
+#elif defined(USE_WOLFSSL)
+
+#if defined(HAVE_SECRET_CALLBACK)
+static void keylog_callback(const WOLFSSL *ssl, const char *line)
+{
+ (void)ssl;
+ Curl_tls_keylog_write_line(line);
+}
+#endif
+
+static CURLcode curl_wssl_init_ctx(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ Curl_vquic_tls_ctx_setup *ctx_setup)
+{
+ struct ssl_primary_config *conn_config;
+ CURLcode result = CURLE_FAILED_INIT;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config) {
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+
+ ctx->ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
+ if(!ctx->ssl_ctx) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ if(ctx_setup) {
+ result = ctx_setup(ctx, cf, data);
+ if(result)
+ goto out;
+ }
+
+ wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
+
+ if(wolfSSL_CTX_set_cipher_list(ctx->ssl_ctx, conn_config->cipher_list13 ?
+ conn_config->cipher_list13 :
+ QUIC_CIPHERS) != 1) {
+ char error_buffer[256];
+ ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
+ failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
+ goto out;
+ }
+
+ if(wolfSSL_CTX_set1_groups_list(ctx->ssl_ctx, conn_config->curves ?
+ conn_config->curves :
+ (char *)QUIC_GROUPS) != 1) {
+ failf(data, "wolfSSL failed to set curves");
+ goto out;
+ }
+
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+#if defined(HAVE_SECRET_CALLBACK)
+ wolfSSL_CTX_set_keylog_callback(ctx->ssl_ctx, keylog_callback);
+#else
+ failf(data, "wolfSSL was built without keylog callback");
+ goto out;
+#endif
+ }
+
+ if(conn_config->verifypeer) {
+ const char * const ssl_cafile = conn_config->CAfile;
+ const char * const ssl_capath = conn_config->CApath;
+
+ wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
+ if(ssl_cafile || ssl_capath) {
+ /* tell wolfSSL where to find CA certificates that are used to verify
+ the server's certificate. */
+ int rc =
+ wolfSSL_CTX_load_verify_locations_ex(ctx->ssl_ctx, ssl_cafile,
+ ssl_capath,
+ WOLFSSL_LOAD_FLAG_IGNORE_ERR);
+ if(SSL_SUCCESS != rc) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ goto out;
+ }
+ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+ }
+#ifdef CURL_CA_FALLBACK
+ else {
+ /* verifying the peer without any CA certificates won't work so
+ use wolfssl's built-in default as fallback */
+ wolfSSL_CTX_set_default_verify_paths(ctx->ssl_ctx);
+ }
+#endif
+ }
+ else {
+ wolfSSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_NONE, NULL);
+ }
+
+ /* give application a chance to interfere with SSL set up. */
+ if(data->set.ssl.fsslctx) {
+ Curl_set_in_callback(data, true);
+ result = (*data->set.ssl.fsslctx)(data, ctx->ssl_ctx,
+ data->set.ssl.fsslctxp);
+ Curl_set_in_callback(data, false);
+ if(result) {
+ failf(data, "error signaled by ssl ctx callback");
+ goto out;
+ }
+ }
+ result = CURLE_OK;
+
+out:
+ if(result && ctx->ssl_ctx) {
+ SSL_CTX_free(ctx->ssl_ctx);
+ ctx->ssl_ctx = NULL;
+ }
+ return result;
+}
+
+/** SSL callbacks ***/
+
+static CURLcode curl_wssl_init_ssl(struct quic_tls_ctx *ctx,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const char *alpn, size_t alpn_len,
+ void *user_data)
+{
+ (void)data;
+ DEBUGASSERT(!ctx->ssl);
+ DEBUGASSERT(ctx->ssl_ctx);
+ ctx->ssl = wolfSSL_new(ctx->ssl_ctx);
+
+ wolfSSL_set_app_data(ctx->ssl, user_data);
+ wolfSSL_set_connect_state(ctx->ssl);
+ wolfSSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
+
+ if(alpn)
+ wolfSSL_set_alpn_protos(ctx->ssl, (const unsigned char *)alpn,
+ (int)alpn_len);
+
+ if(peer->sni) {
+ wolfSSL_UseSNI(ctx->ssl, WOLFSSL_SNI_HOST_NAME,
+ peer->sni, (unsigned short)strlen(peer->sni));
+ }
+
+ return CURLE_OK;
+}
+#endif /* defined(USE_WOLFSSL) */
+
+CURLcode Curl_vquic_tls_init(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const char *alpn, size_t alpn_len,
+ Curl_vquic_tls_ctx_setup *ctx_setup,
+ void *user_data)
+{
+ CURLcode result;
+
+#ifdef USE_OPENSSL
+ result = curl_ossl_init_ctx(ctx, cf, data, ctx_setup);
+ if(result)
+ return result;
+
+ result = curl_ossl_set_client_cert(ctx, cf, data);
+ if(result)
+ return result;
+
+ return curl_ossl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
+#elif defined(USE_GNUTLS)
+ (void)result;
+ return curl_gtls_init_ctx(ctx, cf, data, peer, alpn, alpn_len,
+ ctx_setup, user_data);
+#elif defined(USE_WOLFSSL)
+ result = curl_wssl_init_ctx(ctx, cf, data, ctx_setup);
+ if(result)
+ return result;
+
+ return curl_wssl_init_ssl(ctx, data, peer, alpn, alpn_len, user_data);
+#else
+#error "no TLS lib in used, should not happen"
+ return CURLE_FAILED_INIT;
+#endif
+}
+
+void Curl_vquic_tls_cleanup(struct quic_tls_ctx *ctx)
+{
+#ifdef USE_OPENSSL
+ if(ctx->ssl)
+ SSL_free(ctx->ssl);
+ if(ctx->ssl_ctx)
+ SSL_CTX_free(ctx->ssl_ctx);
+#elif defined(USE_GNUTLS)
+ if(ctx->gtls) {
+ if(ctx->gtls->cred)
+ gnutls_certificate_free_credentials(ctx->gtls->cred);
+ if(ctx->gtls->session)
+ gnutls_deinit(ctx->gtls->session);
+ free(ctx->gtls);
+ }
+#elif defined(USE_WOLFSSL)
+ if(ctx->ssl)
+ wolfSSL_free(ctx->ssl);
+ if(ctx->ssl_ctx)
+ wolfSSL_CTX_free(ctx->ssl_ctx);
+#endif
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+CURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+#ifdef USE_OPENSSL
+ if(!ctx->x509_store_setup) {
+ CURLcode result = Curl_ssl_setup_x509_store(cf, data, ctx->ssl_ctx);
+ if(result)
+ return result;
+ ctx->x509_store_setup = TRUE;
+ }
+#else
+ (void)ctx; (void)cf; (void)data;
+#endif
+ return CURLE_OK;
+}
+
+CURLcode Curl_vquic_tls_verify_peer(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer)
+{
+ struct ssl_primary_config *conn_config;
+ CURLcode result = CURLE_OK;
+
+ conn_config = Curl_ssl_cf_get_primary_config(cf);
+ if(!conn_config)
+ return CURLE_FAILED_INIT;
+
+ if(conn_config->verifyhost) {
+#ifdef USE_OPENSSL
+ X509 *server_cert;
+ server_cert = SSL_get1_peer_certificate(ctx->ssl);
+ if(!server_cert) {
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ result = Curl_ossl_verifyhost(data, cf->conn, peer, server_cert);
+ X509_free(server_cert);
+ if(result)
+ return result;
+#elif defined(USE_GNUTLS)
+ result = Curl_gtls_verifyserver(data, ctx->gtls->session,
+ conn_config, &data->set.ssl, peer,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
+ if(result)
+ return result;
+#elif defined(USE_WOLFSSL)
+ if(!peer->sni ||
+ wolfSSL_check_domain_name(ctx->ssl, peer->sni) == SSL_FAILURE)
+ return CURLE_PEER_FAILED_VERIFICATION;
+#endif
+ infof(data, "Verified certificate just fine");
+ }
+ else
+ infof(data, "Skipped certificate verification");
+#ifdef USE_OPENSSL
+ if(data->set.ssl.certinfo)
+ /* asked to gather certificate info */
+ (void)Curl_ossl_certchain(data, ctx->ssl);
+#endif
+ return result;
+}
+
+
+#endif /* !ENABLE_QUIC && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */
diff --git a/lib/vquic/vquic-tls.h b/lib/vquic/vquic-tls.h
new file mode 100644
index 000000000..9c0dfd8d5
--- /dev/null
+++ b/lib/vquic/vquic-tls.h
@@ -0,0 +1,98 @@
+#ifndef HEADER_CURL_VQUIC_TLS_H
+#define HEADER_CURL_VQUIC_TLS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "bufq.h"
+
+#if defined(ENABLE_QUIC) && \
+ (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL))
+
+struct quic_tls_ctx {
+#ifdef USE_OPENSSL
+ SSL_CTX *ssl_ctx;
+ SSL *ssl;
+#elif defined(USE_GNUTLS)
+ struct gtls_instance *gtls;
+#elif defined(USE_WOLFSSL)
+ WOLFSSL_CTX *ssl_ctx;
+ WOLFSSL *ssl;
+#endif
+ BIT(x509_store_setup); /* if x509 store has been set up */
+};
+
+/**
+ * Callback passed to `Curl_vquic_tls_init()` that can
+ * do early initializations on the not otherwise configured TLS
+ * instances created. This varies by TLS backend:
+ * - openssl/wolfssl: SSL_CTX* has just been created
+ * - gnutls: gtls_client_init() has run
+ */
+typedef CURLcode Curl_vquic_tls_ctx_setup(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * Initialize the QUIC TLS instances based of the SSL configurations
+ * for the connection filter, transfer and peer.
+ * @param ctx the TLS context to initialize
+ * @param cf the connection filter involved
+ * @param data the transfer involved
+ * @param peer the peer that will be connected to
+ * @param alpn the ALPN string in protocol format ((len+bytes+)+),
+ * may be NULL
+ * @param alpn_len the overall number of bytes in `alpn`
+ * @param ctx_setup optional callback for very early TLS config
+ * @param user_data optional pointer to set in TLS application context
+ */
+CURLcode Curl_vquic_tls_init(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ const char *alpn, size_t alpn_len,
+ Curl_vquic_tls_ctx_setup *ctx_setup,
+ void *user_data);
+
+/**
+ * Cleanup all data that has been initialized.
+ */
+void Curl_vquic_tls_cleanup(struct quic_tls_ctx *ctx);
+
+CURLcode Curl_vquic_tls_before_recv(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * After the QUIC basic handshake has been, verify that the peer
+ * (and its certificate) fulfill our requirements.
+ */
+CURLcode Curl_vquic_tls_verify_peer(struct quic_tls_ctx *ctx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer);
+
+#endif /* !ENABLE_QUIC && (USE_OPENSSL || USE_GNUTLS || USE_WOLFSSL) */
+
+#endif /* HEADER_CURL_VQUIC_TLS_H */
diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c
index 9a1a1bbb3..612d25bb0 100644
--- a/lib/vquic/vquic.c
+++ b/lib/vquic/vquic.c
@@ -46,6 +46,7 @@
#include "curl_trc.h"
#include "curl_msh3.h"
#include "curl_ngtcp2.h"
+#include "curl_osslq.h"
#include "curl_quiche.h"
#include "rand.h"
#include "vquic.h"
@@ -74,6 +75,8 @@ void Curl_quic_ver(char *p, size_t len)
{
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
Curl_ngtcp2_ver(p, len);
+#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+ Curl_osslq_ver(p, len);
#elif defined(USE_QUICHE)
Curl_quiche_ver(p, len);
#elif defined(USE_MSH3)
@@ -100,6 +103,7 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
}
}
#endif
+ vquic_ctx_update_time(qctx);
return CURLE_OK;
}
@@ -109,6 +113,11 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx)
Curl_bufq_free(&qctx->sendbuf);
}
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx)
+{
+ qctx->last_op = Curl_now();
+}
+
static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct cf_quic_ctx *qctx,
@@ -173,7 +182,7 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf,
qctx->no_gso = TRUE;
return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
default:
failf(data, "sendmsg() returned %zd (errno %d)", sent, SOCKERRNO);
return CURLE_SEND_ERROR;
@@ -242,6 +251,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
const uint8_t *pkt, size_t pktlen,
size_t gsolen, size_t *psent)
{
+ CURLcode result;
#ifdef DEBUGBUILD
/* simulate network blocking/partial writes */
if(qctx->wblock_percent > 0) {
@@ -254,10 +264,14 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
}
#endif
if(qctx->no_gso && pktlen > gsolen) {
- return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
+ result = send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
}
-
- return do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent);
+ else {
+ result = do_sendmsg(cf, data, qctx, pkt, pktlen, gsolen, psent);
+ }
+ if(!result)
+ qctx->last_io = qctx->last_op;
+ return result;
}
CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data,
@@ -524,13 +538,22 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf,
size_t max_pkts,
vquic_recv_pkt_cb *recv_cb, void *userp)
{
+ CURLcode result;
#if defined(HAVE_SENDMMSG)
- return recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+ result = recvmmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
#elif defined(HAVE_SENDMSG)
- return recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+ result = recvmsg_packets(cf, data, qctx, max_pkts, recv_cb, userp);
#else
- return recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp);
+ result = recvfrom_packets(cf, data, qctx, max_pkts, recv_cb, userp);
#endif
+ if(!result) {
+ if(!qctx->got_first_byte) {
+ qctx->got_first_byte = TRUE;
+ qctx->first_byte_at = qctx->last_op;
+ }
+ qctx->last_io = qctx->last_op;
+ }
+ return result;
}
/*
@@ -588,6 +611,8 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
DEBUGASSERT(transport == TRNSPRT_QUIC);
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
return Curl_cf_ngtcp2_create(pcf, data, conn, ai);
+#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+ return Curl_cf_osslq_create(pcf, data, conn, ai);
#elif defined(USE_QUICHE)
return Curl_cf_quiche_create(pcf, data, conn, ai);
#elif defined(USE_MSH3)
@@ -607,6 +632,8 @@ bool Curl_conn_is_http3(const struct Curl_easy *data,
{
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
return Curl_conn_is_ngtcp2(data, conn, sockindex);
+#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
+ return Curl_conn_is_osslq(data, conn, sockindex);
#elif defined(USE_QUICHE)
return Curl_conn_is_quiche(data, conn, sockindex);
#elif defined(USE_MSH3)
diff --git a/lib/vquic/vquic_int.h b/lib/vquic/vquic_int.h
index dbcd009d7..c218a949c 100644
--- a/lib/vquic/vquic_int.h
+++ b/lib/vquic/vquic_int.h
@@ -31,6 +31,8 @@
#define MAX_PKT_BURST 10
#define MAX_UDP_PAYLOAD_SIZE 1452
+/* Default QUIC connection timeout we announce from our side */
+#define CURL_QUIC_MAX_IDLE_MS (120 * 1000)
struct cf_quic_ctx {
curl_socket_t sockfd; /* connected UDP socket */
@@ -38,18 +40,24 @@ struct cf_quic_ctx {
socklen_t local_addrlen; /* length of local address */
struct bufq sendbuf; /* buffer for sending one or more packets */
+ struct curltime first_byte_at; /* when first byte was recvd */
+ struct curltime last_op; /* last (attempted) send/recv operation */
+ struct curltime last_io; /* last successful socket IO */
size_t gsolen; /* length of individual packets in send buf */
size_t split_len; /* if != 0, buffer length after which GSO differs */
size_t split_gsolen; /* length of individual packets after split_len */
#ifdef DEBUGBUILD
int wblock_percent; /* percent of writes doing EAGAIN */
#endif
- bool no_gso; /* do not use gso on sending */
+ BIT(got_first_byte); /* if first byte was received */
+ BIT(no_gso); /* do not use gso on sending */
};
CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx);
void vquic_ctx_free(struct cf_quic_ctx *qctx);
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx);
+
void vquic_push_blocked_pkt(struct Curl_cfilter *cf,
struct cf_quic_ctx *qctx,
const uint8_t *pkt, size_t pktlen, size_t gsolen);
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index b0f49d60c..c6dc63ae6 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -31,6 +31,8 @@
#include <limits.h>
+/* in 0.10.0 or later, ignore deprecated warnings */
+#define SSH_SUPPRESS_DEPRECATED
#include <libssh/libssh.h>
#include <libssh/sftp.h>
@@ -89,13 +91,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-/* in 0.10.0 or later, ignore deprecated warnings */
-#if defined(__GNUC__) && \
- (LIBSSH_VERSION_MINOR >= 10) || \
- (LIBSSH_VERSION_MAJOR > 0)
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
/* A recent macro provided by libssh. Or make our own. */
#ifndef SSH_STRING_FREE_CHAR
#define SSH_STRING_FREE_CHAR(x) \
@@ -166,7 +161,7 @@ const struct Curl_handler Curl_handler_scp = {
ZERO_NULL, /* domore_getsock */
myssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
@@ -193,7 +188,7 @@ const struct Curl_handler Curl_handler_sftp = {
ZERO_NULL, /* domore_getsock */
myssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
@@ -444,11 +439,8 @@ static int myssh_is_known(struct Curl_easy *data)
keymatch = CURLKHMATCH_OK;
break;
case SSH_KNOWN_HOSTS_OTHER:
- /* fallthrough */
case SSH_KNOWN_HOSTS_NOT_FOUND:
- /* fallthrough */
case SSH_KNOWN_HOSTS_UNKNOWN:
- /* fallthrough */
case SSH_KNOWN_HOSTS_ERROR:
keymatch = CURLKHMATCH_MISSING;
break;
@@ -464,7 +456,6 @@ static int myssh_is_known(struct Curl_easy *data)
keymatch = CURLKHMATCH_OK;
break;
case SSH_SERVER_FILE_NOT_FOUND:
- /* fallthrough */
case SSH_SERVER_NOT_KNOWN:
keymatch = CURLKHMATCH_MISSING;
break;
@@ -628,7 +619,7 @@ restart:
if(rc < 0)
return SSH_ERROR;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case 1:
sshc->kbd_state = 1;
@@ -703,7 +694,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
state(data, SSH_S_STARTUP);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_S_STARTUP:
rc = ssh_connect(sshc->ssh_session);
@@ -718,7 +709,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_HOSTKEY);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_HOSTKEY:
rc = myssh_is_known(data);
@@ -728,7 +719,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
state(data, SSH_AUTHLIST);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_AUTHLIST:{
sshc->authed = FALSE;
@@ -909,7 +900,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
state(data, SSH_AUTH_PASS);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_AUTH_PASS:
rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
@@ -972,7 +963,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
state(data, SSH_SFTP_REALPATH);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_SFTP_REALPATH:
/*
* Get the "home" directory
@@ -1159,13 +1150,23 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
else if(statvfs) {
+ #ifdef _MSC_VER
+ #define CURL_LIBSSH_VFS_SIZE_MASK "I64u"
+ #else
+ #define CURL_LIBSSH_VFS_SIZE_MASK PRIu64
+ #endif
char *tmp = aprintf("statvfs:\n"
- "f_bsize: %llu\n" "f_frsize: %llu\n"
- "f_blocks: %llu\n" "f_bfree: %llu\n"
- "f_bavail: %llu\n" "f_files: %llu\n"
- "f_ffree: %llu\n" "f_favail: %llu\n"
- "f_fsid: %llu\n" "f_flag: %llu\n"
- "f_namemax: %llu\n",
+ "f_bsize: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_frsize: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_blocks: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_bfree: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_bavail: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_files: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_ffree: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_favail: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_fsid: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_flag: %" CURL_LIBSSH_VFS_SIZE_MASK "\n"
+ "f_namemax: %" CURL_LIBSSH_VFS_SIZE_MASK "\n",
statvfs->f_bsize, statvfs->f_frsize,
statvfs->f_blocks, statvfs->f_bfree,
statvfs->f_bavail, statvfs->f_files,
@@ -1307,13 +1308,14 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
}
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
+ char scratch[4*1024];
size_t readthisamountnow =
- (data->state.resume_from - passed > data->set.buffer_size) ?
- (size_t)data->set.buffer_size :
- curlx_sotouz(data->state.resume_from - passed);
+ (data->state.resume_from - passed >
+ (curl_off_t)sizeof(scratch)) ?
+ sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
- data->state.fread_func(data->state.buffer, 1,
+ data->state.fread_func(scratch, 1,
readthisamountnow, data->state.in);
passed += actuallyread;
@@ -1359,7 +1361,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _sending_ function even when the socket turns
out readable as the underlying libssh sftp send function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_OUT;
+ data->state.select_bits = CURL_CSELECT_OUT;
/* since we don't really wait for anything at this point, we want the
state machine to move on as soon as possible so we set a very short
@@ -1466,13 +1468,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, 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;
- /* output debug output if that is requested */
- Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
- sshc->readdir_len);
}
else {
if(Curl_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) {
@@ -1555,7 +1551,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
sshc->readdir_longentry = NULL;
state(data, SSH_SFTP_READDIR_BOTTOM);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_SFTP_READDIR_BOTTOM:
if(Curl_dyn_addn(&sshc->readdir_buf, "\n", 1))
result = CURLE_OUT_OF_MEMORY;
@@ -1564,12 +1560,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_dyn_ptr(&sshc->readdir_buf),
Curl_dyn_len(&sshc->readdir_buf));
- if(!result) {
- /* output debug output if that is requested */
- Curl_debug(data, CURLINFO_DATA_OUT, Curl_dyn_ptr(&sshc->readdir_buf),
- Curl_dyn_len(&sshc->readdir_buf));
- data->req.bytecount += Curl_dyn_len(&sshc->readdir_buf);
- }
ssh_string_free_char(sshc->readdir_tmp);
sshc->readdir_tmp = NULL;
@@ -1741,7 +1731,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _receiving_ function even when the socket turns
out writableable as the underlying libssh recv function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_IN;
+ data->state.select_bits = CURL_CSELECT_IN;
if(result) {
/* this should never occur; the close state should be entered
@@ -1869,7 +1859,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _sending_ function even when the socket turns
out readable as the underlying libssh scp send function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_OUT;
+ data->state.select_bits = CURL_CSELECT_OUT;
state(data, SSH_STOP);
@@ -1885,7 +1875,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
state(data, SSH_SCP_DOWNLOAD);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_SCP_DOWNLOAD:{
curl_off_t bytecount;
@@ -1909,7 +1899,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _receiving_ function even when the socket turns
out writableable as the underlying libssh recv function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_IN;
+ data->state.select_bits = CURL_CSELECT_IN;
state(data, SSH_STOP);
break;
@@ -1949,7 +1939,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
ssh_set_blocking(sshc->ssh_session, 0);
state(data, SSH_SESSION_DISCONNECT);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_SESSION_DISCONNECT:
/* during weird times when we've been prematurely aborted, the channel
@@ -1963,17 +1953,16 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
ssh_disconnect(sshc->ssh_session);
if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
/* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
- explicitly mark it as closed with the memdebug macro. This libssh
+ tell the connection to forget about it. This libssh
bug is fixed in 0.10.0. */
- fake_sclose(conn->sock[FIRSTSOCKET]);
- conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
+ Curl_conn_forget_socket(data, FIRSTSOCKET);
}
SSH_STRING_FREE_CHAR(sshc->homedir);
data->state.most_recent_ftp_entrypath = NULL;
state(data, SSH_SESSION_FREE);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_SESSION_FREE:
if(sshc->ssh_session) {
ssh_free(sshc->ssh_session);
@@ -2024,7 +2013,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
break;
case SSH_QUIT:
- /* fallthrough, just stop! */
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
@@ -2615,7 +2603,7 @@ static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
return -1;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case 1:
conn->proto.sshc.sftp_recv_state = 1;
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
index f539b393b..e9dfef950 100644
--- a/lib/vssh/libssh2.c
+++ b/lib/vssh/libssh2.c
@@ -138,7 +138,7 @@ const struct Curl_handler Curl_handler_scp = {
ZERO_NULL, /* domore_getsock */
ssh_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ssh_attach, /* attach */
PORT_SSH, /* defport */
@@ -167,7 +167,7 @@ const struct Curl_handler Curl_handler_sftp = {
ZERO_NULL, /* domore_getsock */
ssh_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ssh_attach, /* attach */
PORT_SSH, /* defport */
@@ -589,10 +589,9 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
switch(rc) {
default: /* unknown return codes will equal reject */
- /* FALLTHROUGH */
case CURLKHSTAT_REJECT:
state(data, SSH_SESSION_FREE);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURLKHSTAT_DEFER:
/* DEFER means bail out but keep the SSH_HOSTKEY state */
result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
@@ -601,9 +600,8 @@ static CURLcode ssh_knownhost(struct Curl_easy *data)
/* remove old host+key that doesn't match */
if(host)
libssh2_knownhost_del(sshc->kh, host);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURLKHSTAT_FINE:
- /* FALLTHROUGH */
case CURLKHSTAT_FINE_ADD_TO_FILE:
/* proceed */
if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
@@ -997,7 +995,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
state(data, SSH_S_STARTUP);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_S_STARTUP:
rc = session_startup(sshc->ssh_session, sock);
@@ -1016,7 +1014,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_HOSTKEY);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSH_HOSTKEY:
/*
* Before we authenticate we should check the hostkey's fingerprint
@@ -1537,139 +1535,137 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_SFTP_NEXT_QUOTE);
break;
}
- {
- /*
- * the arguments following the command must be separated from the
- * command with a space so we can check for it unconditionally
- */
- cp = strchr(cmd, ' ');
- if(!cp) {
- failf(data, "Syntax error command '%s', missing parameter",
- cmd);
+
+ /*
+ * the arguments following the command must be separated from the
+ * command with a space so we can check for it unconditionally
+ */
+ cp = strchr(cmd, ' ');
+ if(!cp) {
+ failf(data, "Syntax error command '%s', missing parameter",
+ cmd);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
+ }
+
+ /*
+ * also, every command takes at least one argument so we get that
+ * first argument right now
+ */
+ result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
+ break;
+ }
+
+ /*
+ * SFTP is a binary protocol, so we don't send text commands
+ * to the server. Instead, we scan for commands used by
+ * OpenSSH's sftp program and call the appropriate libssh2
+ * functions.
+ */
+ if(strncasecompare(cmd, "chgrp ", 6) ||
+ strncasecompare(cmd, "chmod ", 6) ||
+ strncasecompare(cmd, "chown ", 6) ||
+ strncasecompare(cmd, "atime ", 6) ||
+ strncasecompare(cmd, "mtime ", 6)) {
+ /* attribute change */
+
+ /* sshc->quote_path1 contains the mode to set */
+ /* get the destination */
+ result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in %s: Bad second parameter", cmd);
+ Curl_safefree(sshc->quote_path1);
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
+ sshc->actualcode = result;
break;
}
-
- /*
- * also, every command takes at least one argument so we get that
- * first argument right now
- */
- result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
+ memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
+ state(data, SSH_SFTP_QUOTE_STAT);
+ break;
+ }
+ if(strncasecompare(cmd, "ln ", 3) ||
+ strncasecompare(cmd, "symlink ", 8)) {
+ /* symbolic linking */
+ /* sshc->quote_path1 is the source */
+ /* get the destination */
+ result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
if(result) {
if(result == CURLE_OUT_OF_MEMORY)
failf(data, "Out of memory");
else
- failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
+ failf(data,
+ "Syntax error in ln/symlink: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
state(data, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
break;
}
-
- /*
- * SFTP is a binary protocol, so we don't send text commands
- * to the server. Instead, we scan for commands used by
- * OpenSSH's sftp program and call the appropriate libssh2
- * functions.
- */
- if(strncasecompare(cmd, "chgrp ", 6) ||
- strncasecompare(cmd, "chmod ", 6) ||
- strncasecompare(cmd, "chown ", 6) ||
- strncasecompare(cmd, "atime ", 6) ||
- strncasecompare(cmd, "mtime ", 6)) {
- /* attribute change */
-
- /* sshc->quote_path1 contains the mode to set */
- /* get the destination */
- result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY)
- failf(data, "Out of memory");
- else
- failf(data, "Syntax error in %s: Bad second parameter", cmd);
- Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- break;
- }
- memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
- state(data, SSH_SFTP_QUOTE_STAT);
- break;
- }
- if(strncasecompare(cmd, "ln ", 3) ||
- strncasecompare(cmd, "symlink ", 8)) {
- /* symbolic linking */
- /* sshc->quote_path1 is the source */
- /* get the destination */
- result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY)
- failf(data, "Out of memory");
- else
- failf(data,
- "Syntax error in ln/symlink: Bad second parameter");
- Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- break;
- }
- state(data, SSH_SFTP_QUOTE_SYMLINK);
- break;
- }
- else if(strncasecompare(cmd, "mkdir ", 6)) {
- /* create dir */
- state(data, SSH_SFTP_QUOTE_MKDIR);
- break;
- }
- else if(strncasecompare(cmd, "rename ", 7)) {
- /* rename file */
- /* first param is the source path */
- /* second param is the dest. path */
- result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
- if(result) {
- if(result == CURLE_OUT_OF_MEMORY)
- failf(data, "Out of memory");
- else
- failf(data, "Syntax error in rename: Bad second parameter");
- Curl_safefree(sshc->quote_path1);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = result;
- break;
- }
- state(data, SSH_SFTP_QUOTE_RENAME);
- break;
- }
- else if(strncasecompare(cmd, "rmdir ", 6)) {
- /* delete dir */
- state(data, SSH_SFTP_QUOTE_RMDIR);
- break;
- }
- else if(strncasecompare(cmd, "rm ", 3)) {
- state(data, SSH_SFTP_QUOTE_UNLINK);
+ state(data, SSH_SFTP_QUOTE_SYMLINK);
+ break;
+ }
+ else if(strncasecompare(cmd, "mkdir ", 6)) {
+ /* create dir */
+ state(data, SSH_SFTP_QUOTE_MKDIR);
+ break;
+ }
+ else if(strncasecompare(cmd, "rename ", 7)) {
+ /* rename file */
+ /* first param is the source path */
+ /* second param is the dest. path */
+ result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY)
+ failf(data, "Out of memory");
+ else
+ failf(data, "Syntax error in rename: Bad second parameter");
+ Curl_safefree(sshc->quote_path1);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = result;
break;
}
+ state(data, SSH_SFTP_QUOTE_RENAME);
+ break;
+ }
+ else if(strncasecompare(cmd, "rmdir ", 6)) {
+ /* delete dir */
+ state(data, SSH_SFTP_QUOTE_RMDIR);
+ break;
+ }
+ else if(strncasecompare(cmd, "rm ", 3)) {
+ state(data, SSH_SFTP_QUOTE_UNLINK);
+ break;
+ }
#ifdef HAS_STATVFS_SUPPORT
- else if(strncasecompare(cmd, "statvfs ", 8)) {
- state(data, SSH_SFTP_QUOTE_STATVFS);
- break;
- }
-#endif
-
- failf(data, "Unknown SFTP command");
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- state(data, SSH_SFTP_CLOSE);
- sshc->nextstate = SSH_NO_STATE;
- sshc->actualcode = CURLE_QUOTE_ERROR;
+ else if(strncasecompare(cmd, "statvfs ", 8)) {
+ state(data, SSH_SFTP_QUOTE_STATVFS);
break;
}
+#endif
+
+ failf(data, "Unknown SFTP command");
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ state(data, SSH_SFTP_CLOSE);
+ sshc->nextstate = SSH_NO_STATE;
+ sshc->actualcode = CURLE_QUOTE_ERROR;
+ break;
}
- break;
case SSH_SFTP_NEXT_QUOTE:
Curl_safefree(sshc->quote_path1);
@@ -1962,13 +1958,23 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
break;
}
else if(rc == 0) {
+ #ifdef _MSC_VER
+ #define CURL_LIBSSH2_VFS_SIZE_MASK "I64u"
+ #else
+ #define CURL_LIBSSH2_VFS_SIZE_MASK "llu"
+ #endif
char *tmp = aprintf("statvfs:\n"
- "f_bsize: %llu\n" "f_frsize: %llu\n"
- "f_blocks: %llu\n" "f_bfree: %llu\n"
- "f_bavail: %llu\n" "f_files: %llu\n"
- "f_ffree: %llu\n" "f_favail: %llu\n"
- "f_fsid: %llu\n" "f_flag: %llu\n"
- "f_namemax: %llu\n",
+ "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
+ "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n",
statvfs.f_bsize, statvfs.f_frsize,
statvfs.f_blocks, statvfs.f_bfree,
statvfs.f_bavail, statvfs.f_files,
@@ -2152,14 +2158,15 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
}
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
+ char scratch[4*1024];
size_t readthisamountnow =
- (data->state.resume_from - passed > data->set.buffer_size) ?
- (size_t)data->set.buffer_size :
- curlx_sotouz(data->state.resume_from - passed);
+ (data->state.resume_from - passed >
+ (curl_off_t)sizeof(scratch)) ?
+ sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread;
Curl_set_in_callback(data, true);
- actuallyread = data->state.fread_func(data->state.buffer, 1,
+ actuallyread = data->state.fread_func(scratch, 1,
readthisamountnow,
data->state.in);
Curl_set_in_callback(data, false);
@@ -2205,7 +2212,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _sending_ function even when the socket turns
out readable as the underlying libssh2 sftp send function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_OUT;
+ data->state.select_bits = CURL_CSELECT_OUT;
/* since we don't really wait for anything at this point, we want the
state machine to move on as soon as possible so we set a very short
@@ -2341,14 +2348,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_STOP);
break;
}
- /* since this counts what we send to the client, we include the
- newline in this counter */
- data->req.bytecount += readdir_len + 1;
- /* output debug output if that is requested */
- Curl_debug(data, CURLINFO_DATA_IN, sshp->readdir_filename,
- readdir_len);
- Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
}
else {
result = Curl_dyn_add(&sshp->readdir, sshp->readdir_longentry);
@@ -2427,13 +2427,6 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
Curl_dyn_ptr(&sshp->readdir),
Curl_dyn_len(&sshp->readdir));
- if(!result) {
- /* output debug output if that is requested */
- Curl_debug(data, CURLINFO_DATA_IN,
- Curl_dyn_ptr(&sshp->readdir),
- Curl_dyn_len(&sshp->readdir));
- data->req.bytecount += Curl_dyn_len(&sshp->readdir);
- }
if(result) {
Curl_dyn_free(&sshp->readdir);
state(data, SSH_STOP);
@@ -2608,7 +2601,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _receiving_ function even when the socket turns
out writableable as the underlying libssh2 recv function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_IN;
+ data->state.select_bits = CURL_CSELECT_IN;
if(result) {
/* this should never occur; the close state should be entered
@@ -2763,7 +2756,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _sending_ function even when the socket turns
out readable as the underlying libssh2 scp send function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_OUT;
+ data->state.select_bits = CURL_CSELECT_OUT;
state(data, SSH_STOP);
}
@@ -2825,7 +2818,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _receiving_ function even when the socket turns
out writableable as the underlying libssh2 recv function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_IN;
+ data->state.select_bits = CURL_CSELECT_IN;
if(result) {
state(data, SSH_SCP_CHANNEL_FREE);
@@ -3030,7 +3023,6 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
break;
case SSH_QUIT:
- /* fallthrough, just stop! */
default:
/* internal error */
sshc->nextstate = SSH_NO_STATE;
@@ -3299,6 +3291,27 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
#ifndef CURL_DISABLE_PROXY
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
/*
+ Setup libssh2 callbacks to make it read/write TLS from the socket.
+
+ ssize_t
+ recvcb(libssh2_socket_t sock, void *buffer, size_t length,
+ int flags, void **abstract);
+
+ ssize_t
+ sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
+ int flags, void **abstract);
+
+ */
+#if LIBSSH2_VERSION_NUM >= 0x010b01
+ infof(data, "Uses HTTPS proxy");
+ libssh2_session_callback_set2(sshc->ssh_session,
+ LIBSSH2_CALLBACK_RECV,
+ (libssh2_cb_generic *)ssh_tls_recv);
+ libssh2_session_callback_set2(sshc->ssh_session,
+ LIBSSH2_CALLBACK_SEND,
+ (libssh2_cb_generic *)ssh_tls_send);
+#else
+ /*
* This crazy union dance is here to avoid assigning a void pointer a
* function pointer as it is invalid C. The problem is of course that
* libssh2 has such an API...
@@ -3318,22 +3331,11 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
sshsend.sendptr = ssh_tls_send;
infof(data, "Uses HTTPS proxy");
- /*
- Setup libssh2 callbacks to make it read/write TLS from the socket.
-
- ssize_t
- recvcb(libssh2_socket_t sock, void *buffer, size_t length,
- int flags, void **abstract);
-
- ssize_t
- sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
- int flags, void **abstract);
-
- */
libssh2_session_callback_set(sshc->ssh_session,
LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
libssh2_session_callback_set(sshc->ssh_session,
LIBSSH2_CALLBACK_SEND, sshsend.sendp);
+#endif
/* Store the underlying TLS recv/send function pointers to be used when
reading from the proxy */
diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h
index 1e1b1379c..ca0533aa5 100644
--- a/lib/vssh/ssh.h
+++ b/lib/vssh/ssh.h
@@ -267,6 +267,7 @@ void Curl_ssh_attach(struct Curl_easy *data,
/* for non-SSH builds */
#define Curl_ssh_cleanup()
#define Curl_ssh_attach(x,y)
+#define Curl_ssh_init() 0
#endif
#endif /* HEADER_CURL_SSH_H */
diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
index 39cee5076..7396791ce 100644
--- a/lib/vssh/wolfssh.c
+++ b/lib/vssh/wolfssh.c
@@ -42,6 +42,7 @@
#include "select.h"
#include "multiif.h"
#include "warnless.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -92,7 +93,7 @@ const struct Curl_handler Curl_handler_scp = {
ZERO_NULL, /* domore_getsock */
wssh_getsock, /* perform_getsock */
wscp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
@@ -121,7 +122,7 @@ const struct Curl_handler Curl_handler_sftp = {
ZERO_NULL, /* domore_getsock */
wssh_getsock, /* perform_getsock */
wsftp_disconnect, /* disconnect */
- ZERO_NULL, /* readwrite */
+ ZERO_NULL, /* write_resp */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
PORT_SSH, /* defport */
@@ -343,9 +344,6 @@ static CURLcode wssh_setup_connection(struct Curl_easy *data,
return CURLE_OK;
}
-static Curl_recv wscp_recv, wsftp_recv;
-static Curl_send wscp_send, wsftp_send;
-
static int userauth(byte authtype,
WS_UserAuthData* authdata,
void *ctx)
@@ -515,15 +513,9 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
return CURLE_OK;
}
else if(name && (rc == WS_SUCCESS)) {
- sshc->homedir = malloc(name->fSz + 1);
- if(!sshc->homedir) {
+ sshc->homedir = Curl_memdup0(name->fName, name->fSz);
+ if(!sshc->homedir)
sshc->actualcode = CURLE_OUT_OF_MEMORY;
- }
- else {
- memcpy(sshc->homedir, name->fName, name->fSz);
- sshc->homedir[name->fSz] = 0;
- infof(data, "wolfssh SFTP realpath succeeded");
- }
wolfSSH_SFTPNAME_list_free(name);
state(data, SSH_STOP);
return CURLE_OK;
@@ -649,14 +641,15 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
}
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
+ char scratch[4*1024];
size_t readthisamountnow =
- (data->state.resume_from - passed > data->set.buffer_size) ?
- (size_t)data->set.buffer_size :
- curlx_sotouz(data->state.resume_from - passed);
+ (data->state.resume_from - passed >
+ (curl_off_t)sizeof(scratch)) ?
+ sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread;
Curl_set_in_callback(data, true);
- actuallyread = data->state.fread_func(data->state.buffer, 1,
+ actuallyread = data->state.fread_func(scratch, 1,
readthisamountnow,
data->state.in);
Curl_set_in_callback(data, false);
@@ -702,7 +695,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _sending_ function even when the socket turns
out readable as the underlying libssh2 sftp send function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_OUT;
+ data->state.select_bits = CURL_CSELECT_OUT;
/* since we don't really wait for anything at this point, we want the
state machine to move on as soon as possible so we set a very short
@@ -798,7 +791,7 @@ static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block)
/* we want to use the _receiving_ function even when the socket turns
out writableable as the underlying libssh2 recv function will deal
with both accordingly */
- conn->cselect_bits = CURL_CSELECT_IN;
+ data->state.select_bits = CURL_CSELECT_IN;
if(result) {
/* this should never occur; the close state should be entered
diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c
index 934149c1b..58394bab9 100644
--- a/lib/vtls/bearssl.c
+++ b/lib/vtls/bearssl.c
@@ -509,7 +509,6 @@ static CURLcode bearssl_set_selected_ciphers(struct Curl_easy *data,
{
uint16_t selected_ciphers[NUM_OF_CIPHERS];
size_t selected_count = 0;
- char cipher_name[CIPHER_NAME_BUF_LEN];
const char *cipher_start = ciphers;
const char *cipher_end;
size_t i, j;
@@ -518,41 +517,48 @@ static CURLcode bearssl_set_selected_ciphers(struct Curl_easy *data,
return CURLE_SSL_CIPHER;
while(true) {
+ const char *cipher;
+ size_t clen;
+
/* Extract the next cipher name from the ciphers string */
while(is_separator(*cipher_start))
++cipher_start;
- if(*cipher_start == '\0')
+ if(!*cipher_start)
break;
cipher_end = cipher_start;
- while(*cipher_end != '\0' && !is_separator(*cipher_end))
+ while(*cipher_end && !is_separator(*cipher_end))
++cipher_end;
- j = cipher_end - cipher_start < CIPHER_NAME_BUF_LEN - 1 ?
- cipher_end - cipher_start : CIPHER_NAME_BUF_LEN - 1;
- strncpy(cipher_name, cipher_start, j);
- cipher_name[j] = '\0';
+
+ clen = cipher_end - cipher_start;
+ cipher = cipher_start;
+
cipher_start = cipher_end;
/* Lookup the cipher name in the table of available ciphers. If the cipher
name starts with "TLS_" we do the lookup by IANA name. Otherwise, we try
to match cipher name by an (OpenSSL) alias. */
- if(strncasecompare(cipher_name, "TLS_", 4)) {
+ if(strncasecompare(cipher, "TLS_", 4)) {
for(i = 0; i < NUM_OF_CIPHERS &&
- !strcasecompare(cipher_name, ciphertable[i].name); ++i);
+ (strlen(ciphertable[i].name) == clen) &&
+ !strncasecompare(cipher, ciphertable[i].name, clen); ++i);
}
else {
for(i = 0; i < NUM_OF_CIPHERS &&
- !strcasecompare(cipher_name, ciphertable[i].alias_name); ++i);
+ (strlen(ciphertable[i].alias_name) == clen) &&
+ !strncasecompare(cipher, ciphertable[i].alias_name, clen); ++i);
}
if(i == NUM_OF_CIPHERS) {
- infof(data, "BearSSL: unknown cipher in list: %s", cipher_name);
+ infof(data, "BearSSL: unknown cipher in list: %.*s",
+ (int)clen, cipher);
continue;
}
/* No duplicates allowed */
for(j = 0; j < selected_count &&
- selected_ciphers[j] != ciphertable[i].num; j++);
+ selected_ciphers[j] != ciphertable[i].num; j++);
if(j < selected_count) {
- infof(data, "BearSSL: duplicate cipher in list: %s", cipher_name);
+ infof(data, "BearSSL: duplicate cipher in list: %.*s",
+ (int)clen, cipher);
continue;
}
@@ -582,17 +588,12 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
const char * const ssl_cafile =
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
(ca_info_blob ? NULL : conn_config->CAfile);
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
const bool verifypeer = conn_config->verifypeer;
const bool verifyhost = conn_config->verifyhost;
CURLcode ret;
unsigned version_min, version_max;
int session_set = 0;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
DEBUGASSERT(backend);
CURL_TRC_CF(data, cf, "connect_step1");
@@ -706,11 +707,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
}
- if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
-#ifdef ENABLE_IPV6
- || (1 == Curl_inet_pton(AF_INET6, hostname, &addr))
-#endif
- ) {
+ if(connssl->peer.is_ip_address) {
if(verifyhost) {
failf(data, "BearSSL: "
"host verification of IP address is not supported");
@@ -719,12 +716,11 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
hostname = NULL;
}
else {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
+ if(!connssl->peer.sni) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
- hostname = snihost;
+ hostname = connssl->peer.sni;
CURL_TRC_CF(data, cf, "connect_step1, SNI set");
}
@@ -749,26 +745,26 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
return CURLE_OK;
}
-static int bearssl_get_select_socks(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- curl_socket_t *socks)
+static void bearssl_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
- if(sock == CURL_SOCKET_BAD)
- return GETSOCK_BLANK;
- else {
- struct bearssl_ssl_backend_data *backend =
- (struct bearssl_ssl_backend_data *)connssl->backend;
- unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
- if(state & BR_SSL_SENDREC) {
- socks[0] = sock;
- return GETSOCK_WRITESOCK(0);
+ if(!cf->connected) {
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ if(sock != CURL_SOCKET_BAD) {
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
+ unsigned state = br_ssl_engine_current_state(&backend->ctx.eng);
+
+ if(state & BR_SSL_SENDREC) {
+ Curl_pollset_set_out_only(data, ps, sock);
+ }
+ else {
+ Curl_pollset_set_in_only(data, ps, sock);
+ }
}
}
- socks[0] = sock;
- return GETSOCK_READSOCK(0);
}
static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
@@ -1210,7 +1206,7 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_cert_status_request, /* cert_status_request */
bearssl_connect, /* connect */
bearssl_connect_nonblocking, /* connect_nonblocking */
- bearssl_get_select_socks, /* getsock */
+ bearssl_adjust_pollset, /* adjust_pollset */
bearssl_get_internals, /* get_internals */
bearssl_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index c538a966e..b95c5be3c 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -402,18 +402,13 @@ set_ssl_version_min_max(struct Curl_easy *data,
CURLcode gtls_client_init(struct Curl_easy *data,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
+ struct ssl_peer *peer,
struct gtls_instance *gtls,
long *pverifyresult)
{
unsigned int init_flags;
int rc;
bool sni = TRUE; /* default is SNI enabled */
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
const char *prioritylist;
const char *err = NULL;
const char *tls13support;
@@ -460,50 +455,60 @@ CURLcode gtls_client_init(struct Curl_easy *data,
}
#endif
- if(config->CAfile) {
- /* set the trusted CA cert bundle file */
- gnutls_certificate_set_verify_flags(gtls->cred,
- GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+ if(config->verifypeer) {
+ bool imported_native_ca = false;
- rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
- config->CAfile,
- GNUTLS_X509_FMT_PEM);
- if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)",
- config->CAfile, gnutls_strerror(rc));
- if(config->verifypeer) {
- *pverifyresult = rc;
- return CURLE_SSL_CACERT_BADFILE;
+ if(ssl_config->native_ca_store) {
+ rc = gnutls_certificate_set_x509_system_trust(gtls->cred);
+ if(rc < 0)
+ infof(data, "error reading native ca store (%s), continuing anyway",
+ gnutls_strerror(rc));
+ else {
+ infof(data, "found %d certificates in native ca store", rc);
+ if(rc > 0)
+ imported_native_ca = true;
}
}
- else
- infof(data, "found %d certificates in %s", rc, config->CAfile);
- }
- if(config->CApath) {
- /* set the trusted CA cert directory */
- rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
- config->CApath,
- GNUTLS_X509_FMT_PEM);
- if(rc < 0) {
- infof(data, "error reading ca cert file %s (%s)",
- config->CApath, gnutls_strerror(rc));
- if(config->verifypeer) {
- *pverifyresult = rc;
- return CURLE_SSL_CACERT_BADFILE;
+ if(config->CAfile) {
+ /* set the trusted CA cert bundle file */
+ gnutls_certificate_set_verify_flags(gtls->cred,
+ GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+
+ rc = gnutls_certificate_set_x509_trust_file(gtls->cred,
+ config->CAfile,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)%s",
+ config->CAfile, gnutls_strerror(rc),
+ (imported_native_ca ? ", continuing anyway" : ""));
+ if(!imported_native_ca) {
+ *pverifyresult = rc;
+ return CURLE_SSL_CACERT_BADFILE;
+ }
}
+ else
+ infof(data, "found %d certificates in %s", rc, config->CAfile);
}
- else
- infof(data, "found %d certificates in %s", rc, config->CApath);
- }
-#ifdef CURL_CA_FALLBACK
- /* use system ca certificate store as fallback */
- if(config->verifypeer && !(config->CAfile || config->CApath)) {
- /* this ignores errors on purpose */
- gnutls_certificate_set_x509_system_trust(gtls->cred);
+ if(config->CApath) {
+ /* set the trusted CA cert directory */
+ rc = gnutls_certificate_set_x509_trust_dir(gtls->cred,
+ config->CApath,
+ GNUTLS_X509_FMT_PEM);
+ if(rc < 0) {
+ infof(data, "error reading ca cert file %s (%s)%s",
+ config->CApath, gnutls_strerror(rc),
+ (imported_native_ca ? ", continuing anyway" : ""));
+ if(!imported_native_ca) {
+ *pverifyresult = rc;
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ infof(data, "found %d certificates in %s", rc, config->CApath);
+ }
}
-#endif
if(config->CRLfile) {
/* set the CRL list file */
@@ -537,15 +542,9 @@ CURLcode gtls_client_init(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
- if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
- sni) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
- if(!snihost || gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
- snihost, snilen) < 0) {
+ if(sni && peer->sni) {
+ if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
+ peer->sni, strlen(peer->sni)) < 0) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -585,13 +584,9 @@ CURLcode gtls_client_init(struct Curl_easy *data,
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
if(config->username) {
- size_t len = strlen(prioritylist);
-
- char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
+ char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
if(!prioritysrp)
return CURLE_OUT_OF_MEMORY;
- strcpy(prioritysrp, prioritylist);
- strcpy(prioritysrp + len, ":" GNUTLS_SRP);
rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
free(prioritysrp);
@@ -699,7 +694,7 @@ gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_OK;
result = gtls_client_init(data, conn_config, ssl_config,
- connssl->hostname,
+ &connssl->peer,
&backend->gtls, pverifyresult);
if(result)
return result;
@@ -811,8 +806,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
- const char *dispname,
+ struct ssl_peer *peer,
const char *pinned_key)
{
unsigned int cert_list_size;
@@ -824,16 +818,17 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
char certname[65] = ""; /* limited to 64 chars by ASN.1 */
size_t size;
time_t certclock;
- const char *ptr;
int rc;
CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ const char *ptr;
unsigned int algo;
unsigned int bits;
gnutls_protocol_t version = gnutls_protocol_get_version(session);
#endif
long * const certverifyresult = &ssl_config->certverifyresult;
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* 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),
gnutls_cipher_get(session),
@@ -841,6 +836,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
infof(data, "SSL connection using %s / %s",
gnutls_protocol_get_name(version), ptr);
+#endif
/* This function will return the peer's raw certificate (chain) as sent by
the peer. These certificates are in raw format (DER encoded for
@@ -1068,7 +1064,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
in RFC2818 (HTTPS), which takes into account wildcards, and the subject
alternative name PKIX extension. Returns non zero on success, and zero on
failure. */
- rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
+ rc = gnutls_x509_crt_check_hostname(x509_cert, peer->hostname);
#if GNUTLS_VERSION_NUMBER < 0x030306
/* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
addresses. */
@@ -1081,10 +1077,10 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
unsigned char addrbuf[sizeof(struct use_addr)];
size_t addrlen = 0;
- if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
+ if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
addrlen = 4;
#ifdef ENABLE_IPV6
- else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
+ else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
addrlen = 16;
#endif
@@ -1114,13 +1110,13 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
if(!rc) {
if(config->verifyhost) {
failf(data, "SSL: certificate subject name (%s) does not match "
- "target host name '%s'", certname, dispname);
+ "target host name '%s'", certname, peer->dispname);
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, " common name: %s (does not match '%s')",
- certname, dispname);
+ certname, peer->dispname);
}
else
infof(data, " common name: %s (matched)", certname);
@@ -1253,8 +1249,7 @@ static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
CURLcode result;
result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
- connssl->hostname, connssl->dispname,
- pinned_key);
+ &connssl->peer, pinned_key);
if(result)
goto out;
@@ -1662,7 +1657,7 @@ const struct Curl_ssl Curl_ssl_gnutls = {
gtls_cert_status_request, /* cert_status_request */
gtls_connect, /* connect */
gtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
gtls_get_internals, /* get_internals */
gtls_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index ac141e1c6..1a81c01e9 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -43,6 +43,7 @@ struct Curl_easy;
struct Curl_cfilter;
struct ssl_primary_config;
struct ssl_config_data;
+struct ssl_peer;
struct gtls_instance {
gnutls_session_t session;
@@ -56,7 +57,7 @@ CURLcode
gtls_client_init(struct Curl_easy *data,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
+ struct ssl_peer *peer,
struct gtls_instance *gtls,
long *pverifyresult);
@@ -65,8 +66,7 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
gnutls_session_t session,
struct ssl_primary_config *config,
struct ssl_config_data *ssl_config,
- const char *hostname,
- const char *dispname,
+ struct ssl_peer *peer,
const char *pinned_key);
extern const struct Curl_ssl Curl_ssl_gnutls;
diff --git a/lib/vtls/keylog.c b/lib/vtls/keylog.c
index d37bb183e..fbcb25cfb 100644
--- a/lib/vtls/keylog.c
+++ b/lib/vtls/keylog.c
@@ -23,6 +23,11 @@
***************************************************************************/
#include "curl_setup.h"
+#if defined(USE_OPENSSL) || \
+ defined(USE_WOLFSSL) || \
+ (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
+ defined(USE_QUICHE)
+
#include "keylog.h"
#include <curl/curl.h>
@@ -55,7 +60,7 @@ Curl_tls_keylog_open(void)
if(keylog_file_name) {
keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
if(keylog_file_fp) {
-#ifdef WIN32
+#ifdef _WIN32
if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
#else
if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
@@ -157,3 +162,5 @@ Curl_tls_keylog_write(const char *label,
fputs(line, keylog_file_fp);
return true;
}
+
+#endif /* TLS or QUIC backend */
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 2f994d741..7d70de53b 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -36,6 +36,13 @@
/* Define this to enable lots of debugging for mbedTLS */
/* #define MBEDTLS_DEBUG */
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+/* mbedTLS (as of v3.5.1) has a duplicate function declaration
+ in its public headers. Disable the warning that detects it. */
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
#include <mbedtls/version.h>
#if MBEDTLS_VERSION_NUMBER >= 0x02040000
#include <mbedtls/net_sockets.h>
@@ -56,6 +63,10 @@
# endif
#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#include "urldata.h"
#include "sendf.h"
#include "inet_pton.h"
@@ -67,6 +78,7 @@
#include "select.h"
#include "multiif.h"
#include "mbedtls_threadlock.h"
+#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -153,7 +165,6 @@ static void mbed_debug(void *context, int level, const char *f_name,
infof(data, "%s", line);
(void) level;
}
-#else
#endif
static int mbedtls_bio_cf_write(void *bio,
@@ -165,6 +176,9 @@ static int mbedtls_bio_cf_write(void *bio,
CURLcode result;
DEBUGASSERT(data);
+ if(!data)
+ return 0;
+
nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d",
blen, nwritten, result);
@@ -182,6 +196,8 @@ static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
CURLcode result;
DEBUGASSERT(data);
+ if(!data)
+ return 0;
/* OpenSSL catches this case, so should we. */
if(!buf)
return 0;
@@ -322,7 +338,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
const char * const ssl_crlfile = ssl_config->primary.CRLfile;
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
int ret = -1;
char errorbuf[128];
@@ -367,11 +383,10 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
terminated even when provided the exact length, forcing us to waste
extra memory here. */
- unsigned char *newblob = malloc(ca_info_blob->len + 1);
+ unsigned char *newblob = Curl_memdup0(ca_info_blob->data,
+ ca_info_blob->len);
if(!newblob)
return CURLE_OUT_OF_MEMORY;
- memcpy(newblob, ca_info_blob->data, ca_info_blob->len);
- newblob[ca_info_blob->len] = 0; /* null terminate */
ret = mbedtls_x509_crt_parse(&backend->cacert, newblob,
ca_info_blob->len + 1);
free(newblob);
@@ -441,11 +456,10 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null
terminated even when provided the exact length, forcing us to waste
extra memory here. */
- unsigned char *newblob = malloc(ssl_cert_blob->len + 1);
+ unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data,
+ ssl_cert_blob->len);
if(!newblob)
return CURLE_OUT_OF_MEMORY;
- memcpy(newblob, ssl_cert_blob->data, ssl_cert_blob->len);
- newblob[ssl_cert_blob->len] = 0; /* null terminate */
ret = mbedtls_x509_crt_parse(&backend->clicert, newblob,
ssl_cert_blob->len + 1);
free(newblob);
@@ -639,9 +653,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
mbedtls_ssl_conf_own_cert(&backend->config,
&backend->clicert, &backend->pk);
}
- {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost || mbedtls_ssl_set_hostname(&backend->ssl, snihost)) {
+
+ if(connssl->peer.sni) {
+ if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni)) {
/* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and
the name to set in the SNI extension. So even if curl connects to a
host specified as an IP address, this function must be used. */
@@ -1207,6 +1221,9 @@ static int mbedtls_init(void)
static void mbedtls_cleanup(void)
{
+#ifdef THREADING_SUPPORT
+ mbedtls_entropy_free(&ts_entropy);
+#endif /* THREADING_SUPPORT */
(void)Curl_mbedtlsthreadlock_thread_cleanup();
}
@@ -1274,7 +1291,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
Curl_none_cert_status_request, /* cert_status_request */
mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */
mbedtls_close_all, /* close_all */
diff --git a/lib/vtls/mbedtls_threadlock.c b/lib/vtls/mbedtls_threadlock.c
index bcb7106a6..22b1b221e 100644
--- a/lib/vtls/mbedtls_threadlock.c
+++ b/lib/vtls/mbedtls_threadlock.c
@@ -51,7 +51,7 @@ int Curl_mbedtlsthreadlock_thread_setup(void)
{
int i;
- mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1);
+ mutex_buf = calloc(1, NUMT * sizeof(MBEDTLS_MUTEX_T));
if(!mutex_buf)
return 0; /* error, no number of threads defined */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 9f9c8d136..8d6087022 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -79,6 +79,8 @@
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/pkcs12.h>
+#include <openssl/tls1.h>
+#include <openssl/evp.h>
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP)
#include <openssl/ocsp.h>
@@ -96,6 +98,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
+#endif
/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS
renegotiations when built with BoringSSL. Renegotiating is non-compliant
@@ -173,8 +178,6 @@
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
#define HAVE_EVP_PKEY_GET_PARAMS 1
-#else
-#define SSL_get1_peer_certificate SSL_get_peer_certificate
#endif
#ifdef HAVE_EVP_PKEY_GET_PARAMS
@@ -235,7 +238,11 @@
#elif defined(OPENSSL_IS_AWSLC)
#define OSSL_PACKAGE "AWS-LC"
#else
-#define OSSL_PACKAGE "OpenSSL"
+# if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
+# define OSSL_PACKAGE "quictls"
+# else
+# define OSSL_PACKAGE "OpenSSL"
+#endif
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
@@ -538,9 +545,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
#else
RSA_get0_key(rsa, &n, &e, NULL);
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
- BIO_printf(mem, "%d", BN_num_bits(n));
+ BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0);
#else
- BIO_printf(mem, "%d", BN_num_bits(rsa->n));
+ BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0);
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
push_certinfo("RSA Public Key", i);
print_pubkey_BN(rsa, n, i);
@@ -947,8 +954,9 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
#endif
if(!*buf) {
- strncpy(buf, (error ? "Unknown error" : "No error"), size);
- buf[size - 1] = '\0';
+ const char *msg = error ? "Unknown error" : "No error";
+ if(strlen(msg) < size)
+ strcpy(buf, msg);
}
return buf;
@@ -1080,6 +1088,7 @@ static int ssl_ui_reader(UI *ui, UI_STRING *uis)
UI_set_result(ui, uis, password);
return 1;
}
+ FALLTHROUGH();
default:
break;
}
@@ -1098,6 +1107,7 @@ static int ssl_ui_writer(UI *ui, UI_STRING *uis)
(UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
return 1;
}
+ FALLTHROUGH();
default:
break;
}
@@ -1515,7 +1525,7 @@ fail:
case SSL_FILETYPE_PEM:
if(cert_done)
break;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case SSL_FILETYPE_ASN1:
cert_use_result = key_blob ?
SSL_CTX_use_PrivateKey_blob(ctx, key_blob, file_type, key_passwd) :
@@ -1745,7 +1755,7 @@ static int ossl_init(void)
static void ossl_cleanup(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
- !defined(LIBRESSL_VERSION_NUMBER)
+ (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)
/* OpenSSL 1.1 deprecates all these cleanup functions and
turns them into no-ops in OpenSSL 1.0 compatibility mode */
#else
@@ -2098,22 +2108,6 @@ static bool subj_alt_hostcheck(struct Curl_easy *data,
return FALSE;
}
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert, const char *hostname,
- const char *dispname);
-
-CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert)
-{
- const char *hostname, *dispname;
- int port;
-
- (void)conn;
- Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &dispname, &port);
- return ossl_verifyhost(data, conn, server_cert, hostname, dispname);
-}
-
/* Quote from RFC2818 section 3.1 "Server Identity"
If a subjectAltName extension of type dNSName is present, that MUST
@@ -2136,10 +2130,8 @@ CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
This function is now used from ngtcp2 (QUIC) as well.
*/
-static CURLcode
-ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- X509 *server_cert, const char *hostname,
- const char *dispname)
+CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
+ struct ssl_peer *peer, X509 *server_cert)
{
bool matched = FALSE;
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
@@ -2156,25 +2148,21 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
size_t hostlen;
(void)conn;
- hostlen = strlen(hostname);
-
-#ifndef ENABLE_IPV6
- /* Silence compiler warnings for unused params */
- (void) conn;
-#endif
-
+ hostlen = strlen(peer->hostname);
+ if(peer->is_ip_address) {
#ifdef ENABLE_IPV6
- if(conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, hostname, &addr)) {
- target = GEN_IPADD;
- addrlen = sizeof(struct in6_addr);
- }
- else
-#endif
- if(Curl_inet_pton(AF_INET, hostname, &addr)) {
+ if(conn->bits.ipv6_ip &&
+ Curl_inet_pton(AF_INET6, peer->hostname, &addr)) {
target = GEN_IPADD;
- addrlen = sizeof(struct in_addr);
+ addrlen = sizeof(struct in6_addr);
}
+ else
+#endif
+ if(Curl_inet_pton(AF_INET, peer->hostname, &addr)) {
+ target = GEN_IPADD;
+ addrlen = sizeof(struct in_addr);
+ }
+ }
/* get a "list" of alternative names */
altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
@@ -2224,9 +2212,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
string and we cannot match it. */
- subj_alt_hostcheck(data,
- altptr,
- altlen, hostname, hostlen, dispname)) {
+ subj_alt_hostcheck(data, altptr, altlen,
+ peer->hostname, hostlen,
+ peer->dispname)) {
dnsmatched = TRUE;
}
break;
@@ -2238,7 +2226,7 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
ipmatched = TRUE;
infof(data,
" subjectAltName: host \"%s\" matched cert's IP address!",
- dispname);
+ peer->dispname);
}
break;
}
@@ -2254,9 +2242,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
/* an alternative name matched */
;
else if(dNSName || iPAddress) {
- infof(data, " subjectAltName does not match %s", dispname);
+ infof(data, " subjectAltName does not match %s", peer->dispname);
failf(data, "SSL: no alternative certificate subject name matches "
- "target host name '%s'", dispname);
+ "target host name '%s'", peer->dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -2320,9 +2308,9 @@ ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
result = CURLE_PEER_FAILED_VERIFICATION;
}
else if(!Curl_cert_hostcheck((const char *)peer_CN,
- peerlen, hostname, hostlen)) {
+ peerlen, peer->hostname, hostlen)) {
failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", peer_CN, dispname);
+ "target host name '%s'", peer_CN, peer->dispname);
result = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -2731,12 +2719,6 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
#ifdef USE_OPENSSL
/* ====================================================== */
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-# define use_sni(x) sni = (x)
-#else
-# define use_sni(x) Curl_nop_stmt
-#endif
-
/* Check for OpenSSL 1.0.2 which has ALPN support. */
#undef HAS_ALPN
#if OPENSSL_VERSION_NUMBER >= 0x10002000L \
@@ -2869,7 +2851,7 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
return CURLE_NOT_BUILT_IN;
#endif
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURL_SSLVERSION_TLSv1_2:
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
*ctx_options |= SSL_OP_NO_TLSv1_1;
@@ -2877,7 +2859,7 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
return CURLE_NOT_BUILT_IN;
#endif
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURL_SSLVERSION_TLSv1_1:
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
*ctx_options |= SSL_OP_NO_TLSv1;
@@ -2885,7 +2867,7 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
return CURLE_NOT_BUILT_IN;
#endif
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1:
break;
@@ -2896,12 +2878,12 @@ ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
*ctx_options |= SSL_OP_NO_TLSv1_1;
#endif
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURL_SSLVERSION_MAX_TLSv1_1:
#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
*ctx_options |= SSL_OP_NO_TLSv1_2;
#endif
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURL_SSLVERSION_MAX_TLSv1_2:
#ifdef TLS1_3_VERSION
*ctx_options |= SSL_OP_NO_TLSv1_3;
@@ -3032,6 +3014,151 @@ static CURLcode load_cacert_from_memory(X509_STORE *store,
return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE;
}
+#if defined(USE_WIN32_CRYPTO)
+static CURLcode import_windows_cert_store(struct Curl_easy *data,
+ const char *name,
+ X509_STORE *store,
+ bool *imported)
+{
+ CURLcode result = CURLE_OK;
+ HCERTSTORE hStore;
+
+ *imported = false;
+
+ hStore = CertOpenSystemStoreA(0, name);
+ 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\"", 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((HRESULT)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\"", cert_name);
+#endif
+ *imported = true;
+ }
+ X509_free(x509);
+ }
+
+ free(enhkey_usage);
+ CertFreeCertificateContext(pContext);
+ CertCloseStore(hStore, 0);
+
+ if(result)
+ return result;
+ }
+
+ return result;
+}
+#endif
+
static CURLcode populate_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
X509_STORE *store)
@@ -3050,6 +3177,8 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
bool imported_native_ca = false;
bool imported_ca_info_blob = false;
+ CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
+ ssl_cafile? ssl_cafile : "none", !!ca_info_blob);
if(!store)
return CURLE_OUT_OF_MEMORY;
@@ -3061,140 +3190,25 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
https://datatracker.ietf.org/doc/html/rfc5280 */
if(ssl_config->native_ca_store) {
- HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("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\"", 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((HRESULT)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\"", cert_name);
-#endif
- imported_native_ca = true;
- }
- X509_free(x509);
- }
-
- free(enhkey_usage);
- CertFreeCertificateContext(pContext);
- CertCloseStore(hStore, 0);
-
+ const char *storeNames[] = {
+ "ROOT", /* Trusted Root Certification Authorities */
+ "CA" /* Intermediate Certification Authorities */
+ };
+ size_t i;
+ for(i = 0; i < ARRAYSIZE(storeNames); ++i) {
+ bool imported = false;
+ result = import_windows_cert_store(data, storeNames[i], store,
+ &imported);
if(result)
return result;
+ if(imported) {
+ infof(data, "successfully imported Windows %s store", storeNames[i]);
+ imported_native_ca = true;
+ }
+ else
+ infof(data, "error importing Windows %s store, continuing anyway",
+ storeNames[i]);
}
- if(imported_native_ca)
- infof(data, "successfully imported Windows CA store");
- else
- infof(data, "error importing Windows CA store, continuing anyway");
}
#endif
if(ca_info_blob) {
@@ -3210,7 +3224,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
}
if(ssl_cafile || ssl_capath) {
-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) {
if(!imported_native_ca && !imported_ca_info_blob) {
@@ -3339,6 +3353,7 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
X509_STORE *store = NULL;
+ DEBUGASSERT(multi);
if(multi &&
multi->ssl_backend_data &&
multi->ssl_backend_data->store &&
@@ -3358,6 +3373,7 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
struct multi_ssl_backend_data *mbackend;
+ DEBUGASSERT(multi);
if(!multi)
return;
@@ -3449,17 +3465,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
BIO *bio;
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- bool sni;
- const char *hostname = connssl->hostname;
-
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
-#endif
const long int ssl_version = conn_config->version;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
@@ -3494,7 +3499,6 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
#else
req_method = SSLv23_client_method();
#endif
- use_sni(TRUE);
break;
case CURL_SSLVERSION_SSLv2:
failf(data, "No SSLv2 support");
@@ -3787,13 +3791,8 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
backend->server_cert = 0x0;
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
- if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
-#ifdef ENABLE_IPV6
- (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
-#endif
- sni) {
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost || !SSL_set_tlsext_host_name(backend->handle, snihost)) {
+ if(connssl->peer.sni) {
+ if(!SSL_set_tlsext_host_name(backend->handle, connssl->peer.sni)) {
failf(data, "Failed set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -3802,6 +3801,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
SSL_set_app_data(backend->handle, cf);
+ connssl->reused_session = FALSE;
if(ssl_config->primary.sessionid) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) {
@@ -3815,6 +3815,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
}
/* Informational message */
infof(data, "SSL reusing session ID");
+ connssl->reused_session = TRUE;
}
Curl_ssl_sessionid_unlock(data);
}
@@ -3975,7 +3976,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
Curl_strerror(sockerr, extramsg, sizeof(extramsg));
failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ",
extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
- connssl->hostname, connssl->port);
+ connssl->peer.hostname, connssl->port);
return result;
}
@@ -3986,13 +3987,28 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
}
}
else {
+ int psigtype_nid = NID_undef;
+ const char *negotiated_group_name = NULL;
+
/* we connected fine, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ SSL_get_peer_signature_type_nid(backend->handle, &psigtype_nid);
+#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
+ negotiated_group_name = SSL_get0_group_name(backend->handle);
+#else
+ negotiated_group_name =
+ OBJ_nid2sn(SSL_get_negotiated_group(backend->handle) & 0x0000FFFF);
+#endif
+#endif
+
/* Informational message */
- infof(data, "SSL connection using %s / %s",
+ infof(data, "SSL connection using %s / %s / %s / %s",
SSL_get_version(backend->handle),
- SSL_get_cipher(backend->handle));
+ SSL_get_cipher(backend->handle),
+ negotiated_group_name? negotiated_group_name : "[blank]",
+ OBJ_nid2sn(psigtype_nid));
#ifdef HAS_ALPN
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
@@ -4069,6 +4085,75 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
return result;
}
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \
+ !defined(OPENSSL_IS_BORINGSSL) && \
+ !defined(OPENSSL_IS_AWSLC) && \
+ !defined(CURL_DISABLE_VERBOSE_STRINGS)
+static void infof_certstack(struct Curl_easy *data, const SSL *ssl)
+{
+ STACK_OF(X509) *certstack;
+ long verify_result;
+ int num_cert_levels;
+ int cert_level;
+
+ verify_result = SSL_get_verify_result(ssl);
+ if(verify_result != X509_V_OK)
+ certstack = SSL_get_peer_cert_chain(ssl);
+ else
+ certstack = SSL_get0_verified_chain(ssl);
+ num_cert_levels = sk_X509_num(certstack);
+
+ for(cert_level = 0; cert_level < num_cert_levels; cert_level++) {
+ char cert_algorithm[80] = "";
+ char group_name_final[80] = "";
+ const X509_ALGOR *palg_cert = NULL;
+ const ASN1_OBJECT *paobj_cert = NULL;
+ X509 *current_cert;
+ EVP_PKEY *current_pkey;
+ int key_bits;
+ int key_sec_bits;
+ int get_group_name;
+ const char *type_name;
+
+ current_cert = sk_X509_value(certstack, cert_level);
+
+ X509_get0_signature(NULL, &palg_cert, current_cert);
+ X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert);
+ OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0);
+
+ current_pkey = X509_get0_pubkey(current_cert);
+ key_bits = EVP_PKEY_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits
+#endif
+ key_sec_bits = EVP_PKEY_get_security_bits(current_pkey);
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+ {
+ char group_name[80] = "";
+ get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name,
+ sizeof(group_name), NULL);
+ msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name);
+ }
+ type_name = EVP_PKEY_get0_type_name(current_pkey);
+#else
+ get_group_name = 0;
+ type_name = NULL;
+#endif
+
+ infof(data,
+ " Certificate level %d: "
+ "Public key type %s%s (%d/%d Bits/secBits), signed using %s",
+ cert_level, type_name ? type_name : "?",
+ get_group_name == 0 ? "" : group_name_final,
+ key_bits, key_sec_bits, cert_algorithm);
+ }
+}
+#else
+#define infof_certstack(data, ssl)
+#endif
+
/*
* Get the server cert, verify it and show it, etc., only call failf() if the
* 'strict' argument is TRUE as otherwise all this is for informational
@@ -4147,8 +4232,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
BIO_free(mem);
if(conn_config->verifyhost) {
- result = ossl_verifyhost(data, conn, backend->server_cert,
- connssl->hostname, connssl->dispname);
+ result = Curl_ossl_verifyhost(data, conn, &connssl->peer,
+ backend->server_cert);
if(result) {
X509_free(backend->server_cert);
backend->server_cert = NULL;
@@ -4258,11 +4343,28 @@ static CURLcode servercert(struct Curl_cfilter *cf,
infof(data, " SSL certificate verify ok.");
}
+ infof_certstack(data, backend->handle);
+
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
!defined(OPENSSL_NO_OCSP)
- if(conn_config->verifystatus) {
+ if(conn_config->verifystatus && !connssl->reused_session) {
+ /* don't do this after Session ID reuse */
result = verifystatus(cf, data);
if(result) {
+ /* when verifystatus failed, remove the session id from the cache again
+ if present */
+ if(!Curl_ssl_cf_is_proxy(cf)) {
+ void *old_ssl_sessionid = NULL;
+ bool incache;
+ Curl_ssl_sessionid_lock(data);
+ incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL));
+ if(incache) {
+ infof(data, "Remove session ID again from cache");
+ Curl_ssl_delsessionid(data, old_ssl_sessionid);
+ }
+ Curl_ssl_sessionid_unlock(data);
+ }
+
X509_free(backend->server_cert);
backend->server_cert = NULL;
return result;
@@ -4509,10 +4611,10 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
else if(sockerr)
Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
- else {
- strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
- error_buffer[sizeof(error_buffer) - 1] = '\0';
- }
+ else
+ msnprintf(error_buffer, sizeof(error_buffer), "%s",
+ SSL_ERROR_to_str(err));
+
failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d",
error_buffer, sockerr);
*curlcode = CURLE_SEND_ERROR;
@@ -4522,22 +4624,9 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
case SSL_ERROR_SSL: {
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
- struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
- struct ssl_connect_data *connssl_next = cf_ssl_next?
- cf_ssl_next->ctx : NULL;
sslerror = ERR_get_error();
- if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
- ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
- connssl->state == ssl_connection_complete &&
- (connssl_next && connssl_next->state == ssl_connection_complete)
- ) {
- char ver[120];
- (void)ossl_version(ver, sizeof(ver));
- failf(data, "Error: %s does not support double SSL tunneling.", ver);
- }
- else
- failf(data, "SSL_write() error: %s",
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
+ failf(data, "SSL_write() error: %s",
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
*curlcode = CURLE_SEND_ERROR;
rc = -1;
goto out;
@@ -4618,10 +4707,9 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
else if(sockerr && err == SSL_ERROR_SYSCALL)
Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
- else {
- strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
- error_buffer[sizeof(error_buffer) - 1] = '\0';
- }
+ else
+ msnprintf(error_buffer, sizeof(error_buffer), "%s",
+ SSL_ERROR_to_str(err));
failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d",
error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
@@ -4842,7 +4930,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
ossl_cert_status_request, /* cert_status_request */
ossl_connect, /* connect */
ossl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks,/* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
ossl_get_internals, /* get_internals */
ossl_close, /* close_one */
ossl_close_all, /* close_all */
diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h
index 950faab88..e802363a4 100644
--- a/lib/vtls/openssl.h
+++ b/lib/vtls/openssl.h
@@ -31,24 +31,21 @@
* This header should only be needed to get included by vtls.c, openssl.c
* and ngtcp2.c
*/
+#include <openssl/ossl_typ.h>
#include <openssl/ssl.h>
#include "urldata.h"
-/*
- * In an effort to avoid using 'X509 *' here, we instead use the struct
- * x509_st version of the type so that we can forward-declare it here without
- * having to include <openssl/x509v3.h>. Including that header causes name
- * conflicts when libcurl is built with both Schannel and OpenSSL support.
- */
-struct x509_st;
+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
+#define SSL_get1_peer_certificate SSL_get_peer_certificate
+#endif
+
CURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn,
- struct x509_st *server_cert);
+ struct ssl_peer *peer, X509 *server_cert);
extern const struct Curl_ssl Curl_ssl_openssl;
-struct ssl_ctx_st;
CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
- struct ssl_ctx_st *ctx, char *cert_file,
+ SSL_CTX *ctx, char *cert_file,
const struct curl_blob *cert_blob,
const char *cert_type, char *key_file,
const struct curl_blob *key_blob,
@@ -65,5 +62,9 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
SSL_CTX *ssl_ctx);
+CURLcode Curl_ossl_ctx_configure(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ SSL_CTX *ssl_ctx);
+
#endif /* USE_OPENSSL */
#endif /* HEADER_CURL_SSLUSE_H */
diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c
index a3e9d964c..d58970910 100644
--- a/lib/vtls/rustls.c
+++ b/lib/vtls/rustls.c
@@ -39,6 +39,7 @@
#include "select.h"
#include "strerror.h"
#include "multiif.h"
+#include "connect.h" /* for the connect timeout */
struct rustls_ssl_backend_data
{
@@ -75,14 +76,6 @@ cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
return backend->data_pending;
}
-static CURLcode
-cr_connect(struct Curl_cfilter *cf UNUSED_PARAM,
- struct Curl_easy *data UNUSED_PARAM)
-{
- infof(data, "rustls_connect: unimplemented");
- return CURLE_SSL_CONNECT_ERROR;
-}
-
struct io_ctx {
struct Curl_cfilter *cf;
struct Curl_easy *data;
@@ -163,7 +156,7 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf,
size_t errorlen;
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
failf(data, "rustls_connection_process_new_packets: %.*s",
- errorlen, errorbuf);
+ (int)errorlen, errorbuf);
*err = map_error(rresult);
return -1;
}
@@ -232,7 +225,7 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char errorbuf[255];
size_t errorlen;
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
- failf(data, "rustls_connection_read: %.*s", errorlen, errorbuf);
+ failf(data, "rustls_connection_read: %.*s", (int)errorlen, errorbuf);
*err = CURLE_READ_ERROR;
nread = -1;
goto out;
@@ -308,7 +301,7 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
&plainwritten);
if(rresult != RUSTLS_RESULT_OK) {
rustls_error(rresult, errorbuf, sizeof(errorbuf), &errorlen);
- failf(data, "rustls_connection_write: %.*s", errorlen, errorbuf);
+ failf(data, "rustls_connection_write: %.*s", (int)errorlen, errorbuf);
*err = CURLE_WRITE_ERROR;
return -1;
}
@@ -386,7 +379,7 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
/* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
(ca_info_blob ? NULL : conn_config->CAfile);
const bool verifypeer = conn_config->verifypeer;
- const char *hostname = connssl->hostname;
+ const char *hostname = connssl->peer.hostname;
char errorbuf[256];
size_t errorlen;
int result;
@@ -458,16 +451,15 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
backend->config = rustls_client_config_builder_build(config_builder);
DEBUGASSERT(rconn == NULL);
{
- char *snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
- failf(data, "rustls: failed to get SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- result = rustls_client_connection_new(backend->config, snihost, &rconn);
+ /* rustls claims to manage ip address hostnames as well here. So,
+ * if we have an SNI, we use it, otherwise we pass the hostname */
+ char *server = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ result = rustls_client_connection_new(backend->config, server, &rconn);
}
if(result != RUSTLS_RESULT_OK) {
rustls_error(result, errorbuf, sizeof(errorbuf), &errorlen);
- failf(data, "rustls_client_connection_new: %.*s", errorlen, errorbuf);
+ failf(data, "rustls_client_connection_new: %.*s", (int)errorlen, errorbuf);
return CURLE_COULDNT_CONNECT;
}
rustls_connection_set_userdata(rconn, backend);
@@ -486,9 +478,20 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
Curl_alpn_set_negotiated(cf, data, protocol, len);
}
+/* Given an established network connection, do a TLS handshake.
+ *
+ * If `blocking` is true, this function will block until the handshake is
+ * complete. Otherwise it will return as soon as I/O would block.
+ *
+ * For the non-blocking I/O case, this function will set `*done` to true
+ * once the handshake is complete. This function never reads the value of
+ * `*done*`.
+ */
static CURLcode
-cr_connect_nonblocking(struct Curl_cfilter *cf,
- struct Curl_easy *data, bool *done)
+cr_connect_common(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool blocking,
+ bool *done)
{
struct ssl_connect_data *const connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
@@ -502,6 +505,8 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
bool wants_write;
curl_socket_t writefd;
curl_socket_t readfd;
+ timediff_t timeout_ms;
+ timediff_t socket_check_timeout;
DEBUGASSERT(backend);
@@ -539,12 +544,29 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
writefd = wants_write?sockfd:CURL_SOCKET_BAD;
readfd = wants_read?sockfd:CURL_SOCKET_BAD;
- what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 0);
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "rustls: operation timed out before socket check");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ socket_check_timeout = blocking?timeout_ms:0;
+
+ what = Curl_socket_check(
+ readfd, CURL_SOCKET_BAD, writefd, socket_check_timeout);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
+ if(blocking && 0 == what) {
+ failf(data, "rustls connection timeout after %"
+ CURL_FORMAT_TIMEDIFF_T " ms", socket_check_timeout);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
if(0 == what) {
infof(data, "Curl_socket_check: %s would block",
wants_read&&wants_write ? "writing and reading" :
@@ -589,32 +611,43 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
DEBUGASSERT(false);
}
-/* returns a bitmap of flags for this connection's first socket indicating
- whether we want to read or write */
-static int
-cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks)
+static CURLcode
+cr_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data, bool *done)
{
- struct ssl_connect_data *const connssl = cf->ctx;
- curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
- struct rustls_ssl_backend_data *const backend =
- (struct rustls_ssl_backend_data *)connssl->backend;
- struct rustls_connection *rconn = NULL;
+ return cr_connect_common(cf, data, false, done);
+}
- (void)data;
- DEBUGASSERT(backend);
- rconn = backend->conn;
+static CURLcode
+cr_connect_blocking(struct Curl_cfilter *cf UNUSED_PARAM,
+ struct Curl_easy *data UNUSED_PARAM)
+{
+ bool done; /* unused */
+ return cr_connect_common(cf, data, true, &done);
+}
- if(rustls_connection_wants_write(rconn)) {
- socks[0] = sockfd;
- return GETSOCK_WRITESOCK(0);
- }
- if(rustls_connection_wants_read(rconn)) {
- socks[0] = sockfd;
- return GETSOCK_READSOCK(0);
+static void cr_adjust_pollset(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct easy_pollset *ps)
+{
+ if(!cf->connected) {
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ struct ssl_connect_data *const connssl = cf->ctx;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
+ struct rustls_connection *rconn = NULL;
+
+ (void)data;
+ DEBUGASSERT(backend);
+ rconn = backend->conn;
+
+ if(rustls_connection_wants_write(rconn)) {
+ Curl_pollset_add_out(data, ps, sock);
+ }
+ if(rustls_connection_wants_read(rconn)) {
+ Curl_pollset_add_in(data, ps, sock);
+ }
}
-
- return GETSOCK_BLANK;
}
static void *
@@ -675,9 +708,9 @@ const struct Curl_ssl Curl_ssl_rustls = {
cr_data_pending, /* data_pending */
Curl_none_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- cr_connect, /* connect */
+ cr_connect_blocking, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
- cr_get_select_socks, /* get_select_socks */
+ cr_adjust_pollset, /* adjust_pollset */
cr_get_internals, /* get_internals */
cr_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 410a5c4ec..45c337371 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -439,6 +439,12 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
return CURLE_OK;
}
#endif
+
+static bool algo(const char *check, char *namep, size_t nlen)
+{
+ return (strlen(check) == nlen) && !strncmp(check, namep, nlen);
+}
+
static CURLcode
schannel_acquire_credential_handle(struct Curl_cfilter *cf,
struct Curl_easy *data)
@@ -660,7 +666,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
cert_showfilename_error);
else
failf(data, "schannel: Failed to import cert file %s, "
- "last error is 0x%x",
+ "last error is 0x%lx",
cert_showfilename_error, errorcode);
return CURLE_SSL_CERTPROBLEM;
}
@@ -671,7 +677,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
if(!client_certs[0]) {
failf(data, "schannel: Failed to get certificate from file %s"
- ", last error is 0x%x",
+ ", last error is 0x%lx",
cert_showfilename_error, GetLastError());
CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM;
@@ -684,10 +690,15 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
cert_store_path);
if(!cert_store) {
- failf(data, "schannel: Failed to open cert store %x %s, "
- "last error is 0x%x",
- cert_store_name, cert_store_path, GetLastError());
+ char *path_utf8 =
+ curlx_convert_tchar_to_UTF8(cert_store_path);
+ failf(data, "schannel: Failed to open cert store %lx %s, "
+ "last error is 0x%lx",
+ cert_store_name,
+ (path_utf8 ? path_utf8 : "(unknown)"),
+ GetLastError());
free(cert_store_path);
+ curlx_unicodefree(path_utf8);
curlx_unicodefree(cert_path);
return CURLE_SSL_CERTPROBLEM;
}
@@ -790,9 +801,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
char *startCur = ciphers13;
int algCount = 0;
- char tmp[LONGEST_ALG_ID] = { 0 };
char *nameEnd;
- size_t n;
disable_aes_gcm_sha384 = TRUE;
disable_aes_gcm_sha256 = TRUE;
@@ -801,40 +810,34 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
disable_aes_ccm_sha256 = TRUE;
while(startCur && (0 != *startCur) && (algCount < remaining_ciphers)) {
+ size_t n;
+ char *namep;
nameEnd = strchr(startCur, ':');
n = nameEnd ? (size_t)(nameEnd - startCur) : strlen(startCur);
+ namep = startCur;
- /* reject too-long cipher names */
- if(n > (LONGEST_ALG_ID - 1)) {
- failf(data, "schannel: Cipher name too long, not checked");
- return CURLE_SSL_CIPHER;
- }
-
- strncpy(tmp, startCur, n);
- tmp[n] = 0;
-
- if(disable_aes_gcm_sha384
- && !strcmp("TLS_AES_256_GCM_SHA384", tmp)) {
+ if(disable_aes_gcm_sha384 &&
+ algo("TLS_AES_256_GCM_SHA384", namep, n)) {
disable_aes_gcm_sha384 = FALSE;
}
else if(disable_aes_gcm_sha256
- && !strcmp("TLS_AES_128_GCM_SHA256", tmp)) {
+ && algo("TLS_AES_128_GCM_SHA256", namep, n)) {
disable_aes_gcm_sha256 = FALSE;
}
else if(disable_chacha_poly
- && !strcmp("TLS_CHACHA20_POLY1305_SHA256", tmp)) {
+ && algo("TLS_CHACHA20_POLY1305_SHA256", namep, n)) {
disable_chacha_poly = FALSE;
}
else if(disable_aes_ccm_8_sha256
- && !strcmp("TLS_AES_128_CCM_8_SHA256", tmp)) {
+ && algo("TLS_AES_128_CCM_8_SHA256", namep, n)) {
disable_aes_ccm_8_sha256 = FALSE;
}
else if(disable_aes_ccm_sha256
- && !strcmp("TLS_AES_128_CCM_SHA256", tmp)) {
+ && algo("TLS_AES_128_CCM_SHA256", namep, n)) {
disable_aes_ccm_sha256 = FALSE;
}
else {
- failf(data, "schannel: Unknown TLS 1.3 cipher: %s", tmp);
+ failf(data, "schannel: Unknown TLS 1.3 cipher: %.*s", (int)n, namep);
return CURLE_SSL_CIPHER;
}
@@ -1063,17 +1066,12 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
SECURITY_STATUS sspi_status = SEC_E_OK;
struct Curl_schannel_cred *old_cred = NULL;
- struct in_addr addr;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
CURLcode result;
- const char *hostname = connssl->hostname;
DEBUGASSERT(backend);
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 1/3)",
- hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT,
VERSION_LESS_THAN_EQUAL)) {
@@ -1154,22 +1152,14 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
/* A hostname associated with the credential is needed by
InitializeSecurityContext for SNI and other reasons. */
- snihost = Curl_ssl_snihost(data, hostname, NULL);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
+ snihost = connssl->peer.sni? connssl->peer.sni : connssl->peer.hostname;
backend->cred->sni_hostname = curlx_convert_UTF8_to_tchar(snihost);
if(!backend->cred->sni_hostname)
return CURLE_OUT_OF_MEMORY;
}
/* Warn if SNI is disabled due to use of an IP address */
- if(Curl_inet_pton(AF_INET, hostname, &addr)
-#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, hostname, &addr6)
-#endif
- ) {
+ if(connssl->peer.is_ip_address) {
infof(data, "schannel: using IP address, SNI is not supported by OS.");
}
@@ -1208,9 +1198,8 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
cur += proto.len;
*list_len = curlx_uitous(cur - list_start_index);
- *extension_len = *list_len +
- (unsigned short)sizeof(unsigned int) +
- (unsigned short)sizeof(unsigned short);
+ *extension_len = (unsigned int)(*list_len +
+ sizeof(unsigned int) + sizeof(unsigned short));
InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
@@ -1346,7 +1335,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 2/3)",
- connssl->hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(!backend->cred || !backend->ctxt)
return CURLE_SSL_CONNECT_ERROR;
@@ -1700,7 +1689,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %d (step 3/3)",
- connssl->hostname, connssl->port));
+ connssl->peer.hostname, connssl->port));
if(!backend->cred)
return CURLE_SSL_CONNECT_ERROR;
@@ -2345,10 +2334,10 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
else {
#ifndef CURL_DISABLE_VERBOSE_STRINGS
char buffer[STRERROR_LEN];
-#endif
- *err = CURLE_RECV_ERROR;
infof(data, "schannel: failed to read data from server: %s",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+#endif
+ *err = CURLE_RECV_ERROR;
goto cleanup;
}
}
@@ -2498,7 +2487,7 @@ static int schannel_shutdown(struct Curl_cfilter *cf,
if(backend->ctxt) {
infof(data, "schannel: shutting down SSL/TLS connection with %s port %d",
- connssl->hostname, connssl->port);
+ connssl->peer.hostname, connssl->port);
}
if(backend->cred && backend->ctxt) {
@@ -2754,6 +2743,151 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl,
return &backend->ctxt->ctxt_handle;
}
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ struct schannel_multi_ssl_backend_data *mbackend;
+ const struct ssl_general_config *cfg = &data->set.general_ssl;
+ timediff_t timeout_ms;
+ timediff_t elapsed_ms;
+ struct curltime now;
+ unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH];
+
+ DEBUGASSERT(multi);
+
+ if(!multi || !multi->ssl_backend_data) {
+ return NULL;
+ }
+
+ mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+ if(!mbackend->cert_store) {
+ return NULL;
+ }
+
+ /* zero ca_cache_timeout completely disables caching */
+ if(!cfg->ca_cache_timeout) {
+ return NULL;
+ }
+
+ /* check for cache timeout by using the cached_x509_store_expired timediff
+ calculation pattern from openssl.c.
+ negative timeout means retain forever. */
+ timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
+ if(timeout_ms >= 0) {
+ now = Curl_now();
+ elapsed_ms = Curl_timediff(now, mbackend->time);
+ if(elapsed_ms >= timeout_ms) {
+ return NULL;
+ }
+ }
+
+ if(ca_info_blob) {
+ if(!mbackend->CAinfo_blob_digest) {
+ return NULL;
+ }
+ if(mbackend->CAinfo_blob_size != ca_info_blob->len) {
+ return NULL;
+ }
+ schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+ ca_info_blob->len,
+ info_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH);
+ if(memcmp(mbackend->CAinfo_blob_digest,
+ info_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH)) {
+ return NULL;
+ }
+ }
+ else {
+ if(!conn_config->CAfile || !mbackend->CAfile ||
+ strcmp(mbackend->CAfile, conn_config->CAfile)) {
+ return NULL;
+ }
+ }
+
+ return mbackend->cert_store;
+}
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ HCERTSTORE cert_store)
+{
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ struct schannel_multi_ssl_backend_data *mbackend;
+ unsigned char *CAinfo_blob_digest = NULL;
+ size_t CAinfo_blob_size = 0;
+ char *CAfile = NULL;
+
+ DEBUGASSERT(multi);
+
+ if(!multi) {
+ return false;
+ }
+
+ if(!multi->ssl_backend_data) {
+ multi->ssl_backend_data =
+ calloc(1, sizeof(struct schannel_multi_ssl_backend_data));
+ if(!multi->ssl_backend_data) {
+ return false;
+ }
+ }
+
+ mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
+
+
+ if(ca_info_blob) {
+ CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH);
+ if(!CAinfo_blob_digest) {
+ return false;
+ }
+ schannel_sha256sum((const unsigned char *)ca_info_blob->data,
+ ca_info_blob->len,
+ CAinfo_blob_digest,
+ CURL_SHA256_DIGEST_LENGTH);
+ CAinfo_blob_size = ca_info_blob->len;
+ }
+ else {
+ if(conn_config->CAfile) {
+ CAfile = strdup(conn_config->CAfile);
+ if(!CAfile) {
+ return false;
+ }
+ }
+ }
+
+ /* free old cache data */
+ if(mbackend->cert_store) {
+ CertCloseStore(mbackend->cert_store, 0);
+ }
+ free(mbackend->CAinfo_blob_digest);
+ free(mbackend->CAfile);
+
+ mbackend->time = Curl_now();
+ mbackend->cert_store = cert_store;
+ mbackend->CAinfo_blob_digest = CAinfo_blob_digest;
+ mbackend->CAinfo_blob_size = CAinfo_blob_size;
+ mbackend->CAfile = CAfile;
+ return true;
+}
+
+static void schannel_free_multi_ssl_backend_data(
+ struct multi_ssl_backend_data *msbd)
+{
+ struct schannel_multi_ssl_backend_data *mbackend =
+ (struct schannel_multi_ssl_backend_data*)msbd;
+ if(mbackend->cert_store) {
+ CertCloseStore(mbackend->cert_store, 0);
+ }
+ free(mbackend->CAinfo_blob_digest);
+ free(mbackend->CAfile);
+ free(mbackend);
+}
+
const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
@@ -2777,7 +2911,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_cert_status_request, /* cert_status_request */
schannel_connect, /* connect */
schannel_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
schannel_get_internals, /* get_internals */
schannel_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -2789,7 +2923,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
schannel_sha256sum, /* sha256sum */
NULL, /* associate_connection */
NULL, /* disassociate_connection */
- NULL, /* free_multi_ssl_backend_data */
+ schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
schannel_recv, /* recv decrypted data */
schannel_send, /* send data to encrypt */
};
diff --git a/lib/vtls/schannel_int.h b/lib/vtls/schannel_int.h
index a128e04f6..fe7450d45 100644
--- a/lib/vtls/schannel_int.h
+++ b/lib/vtls/schannel_int.h
@@ -149,5 +149,22 @@ struct schannel_ssl_backend_data {
#endif
};
+struct schannel_multi_ssl_backend_data {
+ unsigned char *CAinfo_blob_digest; /* CA info blob digest */
+ size_t CAinfo_blob_size; /* CA info blob size */
+ char *CAfile; /* CAfile path used to generate
+ certificate store */
+ HCERTSTORE cert_store; /* cached certificate store or
+ NULL if none */
+ struct curltime time; /* when the cached store was created */
+};
+
+HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data);
+
+bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data,
+ HCERTSTORE cert_store);
+
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_INT_H */
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index a5d5c98bb..24146d0bd 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -172,7 +172,7 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store,
/* Sanity check that the cert_context object is the right type */
if(CERT_QUERY_CONTENT_CERT != actual_content_type) {
failf(data,
- "schannel: unexpected content type '%d' when extracting "
+ "schannel: unexpected content type '%lu' when extracting "
"certificate from CA file '%s'",
actual_content_type, ca_file_text);
result = CURLE_SSL_CACERT_BADFILE;
@@ -470,7 +470,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf,
CERT_CONTEXT *pCertContextServer = NULL;
TCHAR *cert_hostname_buff = NULL;
size_t cert_hostname_buff_index = 0;
- const char *conn_hostname = connssl->hostname;
+ const char *conn_hostname = connssl->peer.hostname;
size_t hostlen = strlen(conn_hostname);
DWORD len = 0;
DWORD actual_len = 0;
@@ -600,6 +600,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
const CERT_CHAIN_CONTEXT *pChainContext = NULL;
HCERTCHAINENGINE cert_chain_engine = NULL;
HCERTSTORE trust_store = NULL;
+ HCERTSTORE own_trust_store = NULL;
DEBUGASSERT(BACKEND);
@@ -630,31 +631,46 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
result = CURLE_SSL_CACERT_BADFILE;
}
else {
- /* Open the certificate store */
- trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
- 0,
- (HCRYPTPROV)NULL,
- CERT_STORE_CREATE_NEW_FLAG,
- NULL);
- if(!trust_store) {
- char buffer[STRERROR_LEN];
- failf(data, "schannel: failed to create certificate store: %s",
- Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
- result = CURLE_SSL_CACERT_BADFILE;
+ /* try cache */
+ trust_store = Curl_schannel_get_cached_cert_store(cf, data);
+
+ if(trust_store) {
+ infof(data, "schannel: reusing certificate store from cache");
}
else {
- const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
- if(ca_info_blob) {
- result = add_certs_data_to_store(trust_store,
- (const char *)ca_info_blob->data,
- ca_info_blob->len,
- "(memory blob)",
- data);
+ /* Open the certificate store */
+ trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(!trust_store) {
+ char buffer[STRERROR_LEN];
+ failf(data, "schannel: failed to create certificate store: %s",
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
+ result = CURLE_SSL_CACERT_BADFILE;
}
else {
- result = add_certs_file_to_store(trust_store,
- conn_config->CAfile,
- data);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
+ own_trust_store = trust_store;
+
+ if(ca_info_blob) {
+ result = add_certs_data_to_store(trust_store,
+ (const char *)ca_info_blob->data,
+ ca_info_blob->len,
+ "(memory blob)",
+ data);
+ }
+ else {
+ result = add_certs_file_to_store(trust_store,
+ conn_config->CAfile,
+ data);
+ }
+ if(result == CURLE_OK) {
+ if(Curl_schannel_set_cached_cert_store(cf, data, trust_store)) {
+ own_trust_store = NULL;
+ }
+ }
}
}
}
@@ -737,7 +753,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
failf(data, "schannel: CertGetCertificateChain trust error"
" CERT_TRUST_REVOCATION_STATUS_UNKNOWN");
else
- failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+ failf(data, "schannel: CertGetCertificateChain error mask: 0x%08lx",
dwTrustErrorMask);
result = CURLE_PEER_FAILED_VERIFICATION;
}
@@ -754,8 +770,8 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
CertFreeCertificateChainEngine(cert_chain_engine);
}
- if(trust_store) {
- CertCloseStore(trust_store, 0);
+ if(own_trust_store) {
+ CertCloseStore(own_trust_store, 0);
}
if(pChainContext)
diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
index 3378f7619..1f37305ce 100644
--- a/lib/vtls/sectransp.c
+++ b/lib/vtls/sectransp.c
@@ -46,8 +46,10 @@
#endif /* __clang__ */
#ifdef __GNUC__
+#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#pragma GCC diagnostic ignored "-Wundef"
+#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#include <limits.h>
@@ -904,7 +906,6 @@ static OSStatus sectransp_bio_cf_out_write(SSLConnectionRef connection,
return rtn;
}
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
{
/* The first ciphers in the ciphertable are continuous. Here we do small
@@ -923,7 +924,6 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
}
return ciphertable[SSL_NULL_WITH_NULL_NULL].name;
}
-#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
#if CURL_BUILD_MAC
CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
@@ -1013,7 +1013,7 @@ static CURLcode CopyCertSubject(struct Curl_easy *data,
}
else {
size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
- cbuf = calloc(cbuf_size, 1);
+ cbuf = calloc(1, cbuf_size);
if(cbuf) {
if(!CFStringGetCString(c, cbuf, cbuf_size,
kCFStringEncodingUTF8)) {
@@ -1651,11 +1651,6 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
const bool verifypeer = conn_config->verifypeer;
char * const ssl_cert = ssl_config->primary.clientcert;
const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif /* ENABLE_IPV6 */
char *ciphers;
OSStatus err = noErr;
#if CURL_BUILD_MAC
@@ -2003,13 +1998,9 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
* Both hostname check and SNI require SSLSetPeerDomainName().
* Also: the verifyhost setting influences SNI usage */
if(conn_config->verifyhost) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
- if(!snihost) {
- failf(data, "Failed to set SNI");
- return CURLE_SSL_CONNECT_ERROR;
- }
- err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
+ char *server = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server));
if(err != noErr) {
failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
@@ -2017,11 +2008,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
return CURLE_SSL_CONNECT_ERROR;
}
- if((Curl_inet_pton(AF_INET, connssl->hostname, &addr))
- #ifdef ENABLE_IPV6
- || (Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
- #endif
- ) {
+ if(connssl->peer.is_ip_address) {
infof(data, "WARNING: using IP address, SNI is being disabled by "
"the OS.");
}
@@ -2079,7 +2066,7 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
ssl_sessionid =
aprintf("%s:%d:%d:%s:%d",
ssl_cafile ? ssl_cafile : "(blob memory)",
- verifypeer, conn_config->verifyhost, connssl->hostname,
+ verifypeer, conn_config->verifyhost, connssl->peer.hostname,
connssl->port);
ssl_sessionid_len = strlen(ssl_sessionid);
@@ -2380,19 +2367,15 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
const struct curl_blob *ca_info_blob,
SSLContextRef ctx)
{
- int result;
+ CURLcode result;
unsigned char *certbuf;
size_t buflen;
+ bool free_certbuf = FALSE;
if(ca_info_blob) {
CURL_TRC_CF(data, cf, "verify_peer, CA from config blob");
- certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
- if(!certbuf) {
- return CURLE_OUT_OF_MEMORY;
- }
+ certbuf = ca_info_blob->data;
buflen = ca_info_blob->len;
- memcpy(certbuf, ca_info_blob->data, ca_info_blob->len);
- certbuf[ca_info_blob->len]='\0';
}
else if(cafile) {
CURL_TRC_CF(data, cf, "verify_peer, CA from file '%s'", cafile);
@@ -2400,12 +2383,14 @@ static CURLcode verify_cert(struct Curl_cfilter *cf,
failf(data, "SSL: failed to read or invalid CA certificate");
return CURLE_SSL_CACERT_BADFILE;
}
+ free_certbuf = TRUE;
}
else
return CURLE_SSL_CACERT_BADFILE;
result = verify_cert_buf(cf, data, certbuf, buflen, ctx);
- free(certbuf);
+ if(free_certbuf)
+ free(certbuf);
return result;
}
@@ -2665,7 +2650,7 @@ check_handshake:
host name: */
case errSSLHostNameMismatch:
failf(data, "SSL certificate peer verification failed, the "
- "certificate did not match \"%s\"\n", connssl->dispname);
+ "certificate did not match \"%s\"\n", connssl->peer.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
/* Problem with SSL / TLS negotiation */
@@ -2757,7 +2742,7 @@ check_handshake:
default:
/* May also return codes listed in Security Framework Result Codes */
failf(data, "Unknown SSL protocol error in connection to %s:%d",
- connssl->hostname, err);
+ connssl->peer.hostname, err);
break;
}
return CURLE_SSL_CONNECT_ERROR;
@@ -3415,7 +3400,6 @@ again:
}
*curlcode = CURLE_AGAIN;
return -1L;
- break;
/* errSSLClosedGraceful - server gracefully shut down the SSL session
errSSLClosedNoNotify - server hung up on us instead of sending a
@@ -3425,7 +3409,6 @@ again:
case errSSLClosedNoNotify:
*curlcode = CURLE_OK;
return 0;
- break;
/* The below is errSSLPeerAuthCompleted; it's not defined in
Leopard's headers */
@@ -3445,7 +3428,6 @@ again:
failf(data, "SSLRead() return error %d", err);
*curlcode = CURLE_RECV_ERROR;
return -1L;
- break;
}
}
return (ssize_t)processed;
@@ -3483,7 +3465,7 @@ const struct Curl_ssl Curl_ssl_sectransp = {
Curl_none_cert_status_request, /* cert_status_request */
sectransp_connect, /* connect */
sectransp_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
sectransp_get_internals, /* get_internals */
sectransp_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -3500,6 +3482,10 @@ const struct Curl_ssl Curl_ssl_sectransp = {
sectransp_send, /* send data to encrypt */
};
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#ifdef __clang__
#pragma clang diagnostic pop
#endif
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 494b660a9..e928ba5d0 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -67,6 +67,7 @@
#include "warnless.h"
#include "curl_base64.h"
#include "curl_printf.h"
+#include "inet_pton.h"
#include "strdup.h"
/* The last #include files should be: */
@@ -131,9 +132,6 @@ static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
}
#ifdef USE_SSL
-static const struct alpn_spec ALPN_SPEC_H10 = {
- { ALPN_HTTP_1_0 }, 1
-};
static const struct alpn_spec ALPN_SPEC_H11 = {
{ ALPN_HTTP_1_1 }, 1
};
@@ -147,51 +145,83 @@ static const struct alpn_spec *alpn_get_spec(int httpwant, bool use_alpn)
{
if(!use_alpn)
return NULL;
- if(httpwant == CURL_HTTP_VERSION_1_0)
- return &ALPN_SPEC_H10;
#ifdef USE_HTTP2
if(httpwant >= CURL_HTTP_VERSION_2)
return &ALPN_SPEC_H2_H11;
+#else
+ (void)httpwant;
#endif
+ /* Use the ALPN protocol "http/1.1" for HTTP/1.x.
+ Avoid "http/1.0" because some servers don't support it. */
return &ALPN_SPEC_H11;
}
#endif /* USE_SSL */
-bool
-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->ssl_options == needle->ssl_options) &&
- (data->verifypeer == needle->verifypeer) &&
- (data->verifyhost == needle->verifyhost) &&
- (data->verifystatus == needle->verifystatus) &&
- blobcmp(data->cert_blob, needle->cert_blob) &&
- blobcmp(data->ca_info_blob, needle->ca_info_blob) &&
- blobcmp(data->issuercert_blob, needle->issuercert_blob) &&
- Curl_safecmp(data->CApath, needle->CApath) &&
- Curl_safecmp(data->CAfile, needle->CAfile) &&
- Curl_safecmp(data->issuercert, needle->issuercert) &&
- Curl_safecmp(data->clientcert, needle->clientcert) &&
+void Curl_ssl_easy_config_init(struct Curl_easy *data)
+{
+ /*
+ * libcurl 7.10 introduced SSL verification *by default*! This needs to be
+ * switched off unless wanted.
+ */
+ data->set.ssl.primary.verifypeer = TRUE;
+ data->set.ssl.primary.verifyhost = TRUE;
+ data->set.ssl.primary.sessionid = TRUE; /* session ID caching by default */
+#ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl = data->set.ssl;
+#endif
+}
+
+static bool
+match_ssl_primary_config(struct Curl_easy *data,
+ struct ssl_primary_config *c1,
+ struct ssl_primary_config *c2)
+{
+ (void)data;
+ if((c1->version == c2->version) &&
+ (c1->version_max == c2->version_max) &&
+ (c1->ssl_options == c2->ssl_options) &&
+ (c1->verifypeer == c2->verifypeer) &&
+ (c1->verifyhost == c2->verifyhost) &&
+ (c1->verifystatus == c2->verifystatus) &&
+ blobcmp(c1->cert_blob, c2->cert_blob) &&
+ blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
+ blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
+ Curl_safecmp(c1->CApath, c2->CApath) &&
+ Curl_safecmp(c1->CAfile, c2->CAfile) &&
+ Curl_safecmp(c1->issuercert, c2->issuercert) &&
+ Curl_safecmp(c1->clientcert, c2->clientcert) &&
#ifdef USE_TLS_SRP
- !Curl_timestrcmp(data->username, needle->username) &&
- !Curl_timestrcmp(data->password, needle->password) &&
+ !Curl_timestrcmp(c1->username, c2->username) &&
+ !Curl_timestrcmp(c1->password, c2->password) &&
#endif
- strcasecompare(data->cipher_list, needle->cipher_list) &&
- strcasecompare(data->cipher_list13, needle->cipher_list13) &&
- strcasecompare(data->curves, needle->curves) &&
- strcasecompare(data->CRLfile, needle->CRLfile) &&
- strcasecompare(data->pinned_key, needle->pinned_key))
+ strcasecompare(c1->cipher_list, c2->cipher_list) &&
+ strcasecompare(c1->cipher_list13, c2->cipher_list13) &&
+ strcasecompare(c1->curves, c2->curves) &&
+ strcasecompare(c1->CRLfile, c2->CRLfile) &&
+ strcasecompare(c1->pinned_key, c2->pinned_key))
return TRUE;
return FALSE;
}
-bool
-Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
- struct ssl_primary_config *dest)
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+ struct connectdata *candidate,
+ bool proxy)
+{
+#ifndef CURL_DISABLE_PROXY
+ if(proxy)
+ return match_ssl_primary_config(data, &data->set.proxy_ssl.primary,
+ &candidate->proxy_ssl_config);
+#else
+ (void)proxy;
+#endif
+ return match_ssl_primary_config(data, &data->set.ssl.primary,
+ &candidate->ssl_config);
+}
+
+static bool clone_ssl_primary_config(struct ssl_primary_config *source,
+ struct ssl_primary_config *dest)
{
dest->version = source->version;
dest->version_max = source->version_max;
@@ -221,7 +251,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
return TRUE;
}
-void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
+static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
{
Curl_safefree(sslc->CApath);
Curl_safefree(sslc->CAfile);
@@ -241,6 +271,111 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
#endif
}
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
+{
+ data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
+ data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
+ data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+ data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
+ data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
+ data->set.ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST];
+ data->set.ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST];
+ data->set.ssl.primary.pinned_key =
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+ data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
+ data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
+ data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
+#ifdef USE_TLS_SRP
+ data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
+ data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+#endif
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
+ data->set.ssl.key = data->set.str[STRING_KEY];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
+ data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
+
+#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.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.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+ data->set.proxy_ssl.primary.ca_info_blob =
+ data->set.blobs[BLOB_CAINFO_PROXY];
+ data->set.proxy_ssl.primary.issuercert =
+ data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.issuercert_blob =
+ data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
+ data->set.proxy_ssl.primary.CRLfile =
+ data->set.str[STRING_SSL_CRLFILE_PROXY];
+ data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
+ data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
+ data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
+ data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+ data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
+ data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
+#ifdef USE_TLS_SRP
+ data->set.proxy_ssl.primary.username =
+ data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+ data->set.proxy_ssl.primary.password =
+ data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
+#endif
+#endif /* CURL_DISABLE_PROXY */
+
+ return CURLE_OK;
+}
+
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ /* Clone "primary" SSL configurations from the esay handle to
+ * the connection. They are used for connection cache matching and
+ * probably outlive the easy handle */
+ if(!clone_ssl_primary_config(&data->set.ssl.primary, &conn->ssl_config))
+ return CURLE_OUT_OF_MEMORY;
+#ifndef CURL_DISABLE_PROXY
+ if(!clone_ssl_primary_config(&data->set.proxy_ssl.primary,
+ &conn->proxy_ssl_config))
+ return CURLE_OUT_OF_MEMORY;
+#endif
+ return CURLE_OK;
+}
+
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn)
+{
+ Curl_free_primary_ssl_config(&conn->ssl_config);
+#ifndef CURL_DISABLE_PROXY
+ Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+#endif
+}
+
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy)
+{
+ /* May be called on an easy that has no connection yet */
+ if(data->conn) {
+ struct ssl_primary_config *src, *dest;
+#ifndef CURL_DISABLE_PROXY
+ src = for_proxy? &data->set.proxy_ssl.primary : &data->set.ssl.primary;
+ dest = for_proxy? &data->conn->proxy_ssl_config : &data->conn->ssl_config;
+#else
+ (void)for_proxy;
+ src = &data->set.ssl.primary;
+ dest = &data->conn->ssl_config;
+#endif
+ dest->verifyhost = src->verifyhost;
+ dest->verifypeer = src->verifypeer;
+ dest->verifystatus = src->verifystatus;
+ }
+}
+
#ifdef USE_SSL
static int multissl_setup(const struct Curl_ssl *backend);
#endif
@@ -432,7 +567,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
if(!check->sessionid)
/* not session ID means blank entry */
continue;
- if(strcasecompare(connssl->hostname, check->name) &&
+ if(strcasecompare(connssl->peer.hostname, check->name) &&
((!cf->conn->bits.conn_to_host && !check->conn_to_host) ||
(cf->conn->bits.conn_to_host && check->conn_to_host &&
strcasecompare(cf->conn->conn_to_host.name, check->conn_to_host))) &&
@@ -441,7 +576,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
cf->conn->conn_to_port == check->conn_to_port)) &&
(connssl->port == check->remote_port) &&
strcasecompare(cf->conn->handler->scheme, check->scheme) &&
- Curl_ssl_config_matches(conn_config, &check->ssl_config)) {
+ match_ssl_primary_config(data, conn_config, &check->ssl_config)) {
/* yes, we have a session ID! */
(*general_age)++; /* increase general age */
check->age = *general_age; /* set this as used in this age */
@@ -456,7 +591,8 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
no_match? "Didn't find": "Found",
Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
- cf->conn->handler->scheme, connssl->hostname, connssl->port));
+ cf->conn->handler->scheme, connssl->peer.hostname,
+ connssl->port));
return no_match;
}
@@ -532,7 +668,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
(void)ssl_config;
DEBUGASSERT(ssl_config->primary.sessionid);
- clone_host = strdup(connssl->hostname);
+ clone_host = strdup(connssl->peer.hostname);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
@@ -590,7 +726,7 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
store->remote_port = connssl->port;
store->scheme = cf->conn->handler->scheme;
- if(!Curl_clone_primary_ssl_config(conn_config, &store->ssl_config)) {
+ if(!clone_ssl_primary_config(conn_config, &store->ssl_config)) {
Curl_free_primary_ssl_config(&store->ssl_config);
store->sessionid = NULL; /* let caller free sessionid */
free(clone_host);
@@ -629,22 +765,21 @@ void Curl_ssl_close_all(struct Curl_easy *data)
Curl_ssl->close_all(data);
}
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks)
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps)
{
- struct ssl_connect_data *connssl = cf->ctx;
- curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
-
- if(sock == CURL_SOCKET_BAD)
- return GETSOCK_BLANK;
-
- if(connssl->connecting_state == ssl_connect_2_writing) {
- /* we are only interested in writing */
- socks[0] = sock;
- return GETSOCK_WRITESOCK(0);
+ if(!cf->connected) {
+ struct ssl_connect_data *connssl = cf->ctx;
+ curl_socket_t sock = Curl_conn_cf_get_socket(cf->next, data);
+ if(sock != CURL_SOCKET_BAD) {
+ if(connssl->connecting_state == ssl_connect_2_writing) {
+ Curl_pollset_set_out_only(data, ps, sock);
+ }
+ else {
+ Curl_pollset_set_in_only(data, ps, sock);
+ }
+ }
}
- socks[0] = sock;
- return GETSOCK_READSOCK(0);
}
/* Selects an SSL crypto engine
@@ -748,28 +883,21 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
size_t valuelen)
{
struct curl_certinfo *ci = &data->info.certs;
- char *output;
struct curl_slist *nl;
CURLcode result = CURLE_OK;
- size_t labellen = strlen(label);
- size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
-
- output = malloc(outlen);
- if(!output)
- return CURLE_OUT_OF_MEMORY;
+ struct dynbuf build;
- /* sprintf the label and colon */
- msnprintf(output, outlen, "%s:", label);
+ Curl_dyn_init(&build, 10000);
- /* memcpy the value (it might not be null-terminated) */
- memcpy(&output[labellen + 1], value, valuelen);
-
- /* null-terminate the output */
- output[labellen + 1 + valuelen] = 0;
+ if(Curl_dyn_add(&build, label) ||
+ Curl_dyn_addn(&build, ":", 1) ||
+ Curl_dyn_addn(&build, value, valuelen))
+ return CURLE_OUT_OF_MEMORY;
- nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
+ nl = Curl_slist_append_nodup(ci->certinfo[certnum],
+ Curl_dyn_ptr(&build));
if(!nl) {
- free(output);
+ Curl_dyn_free(&build);
curl_slist_free_all(ci->certinfo[certnum]);
result = CURLE_OUT_OF_MEMORY;
}
@@ -786,32 +914,6 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
}
/*
- * Curl_ssl_snihost() converts the input host name to a suitable SNI name put
- * in data->state.buffer. Returns a pointer to the name (or NULL if a problem)
- * and stores the new length in 'olen'.
- *
- * SNI fields must not have any trailing dot and while RFC 6066 section 3 says
- * the SNI field is case insensitive, browsers always send the data lowercase
- * and subsequently there are numerous servers out there that don't work
- * unless the name is lowercased.
- */
-
-char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen)
-{
- size_t len = strlen(host);
- if(len && (host[len-1] == '.'))
- len--;
- if(len >= data->set.buffer_size)
- return NULL;
-
- Curl_strntolower(data->state.buffer, host, len);
- data->state.buffer[len] = 0;
- if(olen)
- *olen = len;
- return data->state.buffer;
-}
-
-/*
* Public key pem to der conversion
*/
@@ -893,7 +995,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
/* only do this if pinnedpubkey starts with "sha256//", length 8 */
if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
CURLcode encode;
- size_t encodedlen = 0, pinkeylen;
+ size_t encodedlen = 0;
char *encoded = NULL, *pinkeycopy, *begin_pos, *end_pos;
unsigned char *sha256sumdigest;
@@ -921,13 +1023,11 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
infof(data, " public key hash: sha256//%s", encoded);
/* it starts with sha256//, copy so we can modify it */
- pinkeylen = strlen(pinnedpubkey) + 1;
- pinkeycopy = malloc(pinkeylen);
+ pinkeycopy = strdup(pinnedpubkey);
if(!pinkeycopy) {
Curl_safefree(encoded);
return CURLE_OUT_OF_MEMORY;
}
- memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
/* point begin_pos to the copy, and start extracting keys */
begin_pos = pinkeycopy;
do {
@@ -1156,13 +1256,13 @@ static CURLcode multissl_connect_nonblocking(struct Curl_cfilter *cf,
return Curl_ssl->connect_nonblocking(cf, data, done);
}
-static int multissl_get_select_socks(struct Curl_cfilter *cf,
+static void multissl_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
if(multissl_setup(NULL))
- return 0;
- return Curl_ssl->get_select_socks(cf, data, socks);
+ return;
+ Curl_ssl->adjust_pollset(cf, data, ps);
}
static void *multissl_get_internals(struct ssl_connect_data *connssl,
@@ -1214,7 +1314,7 @@ static const struct Curl_ssl Curl_ssl_multi = {
Curl_none_cert_status_request, /* cert_status_request */
multissl_connect, /* connect */
multissl_connect_nonblocking, /* connect_nonblocking */
- multissl_get_select_socks, /* getsock */
+ multissl_adjust_pollset, /* adjust_pollset */
multissl_get_internals, /* get_internals */
multissl_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -1313,17 +1413,13 @@ static size_t multissl_version(char *buffer, size_t size)
backends_len = p - backends;
}
- if(!size)
- return 0;
-
- if(size <= backends_len) {
- strncpy(buffer, backends, size - 1);
- buffer[size - 1] = '\0';
- return size - 1;
+ if(size) {
+ if(backends_len < size)
+ strcpy(buffer, backends);
+ else
+ *buffer = 0; /* did not fit */
}
-
- strcpy(buffer, backends);
- return backends_len;
+ return 0;
}
static int multissl_setup(const struct Curl_ssl *backend)
@@ -1409,12 +1505,14 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
#ifdef USE_SSL
-static void free_hostname(struct ssl_connect_data *connssl)
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer)
{
- if(connssl->dispname != connssl->hostname)
- free(connssl->dispname);
- free(connssl->hostname);
- connssl->hostname = connssl->dispname = NULL;
+ if(peer->dispname != peer->hostname)
+ free(peer->dispname);
+ free(peer->sni);
+ free(peer->hostname);
+ peer->hostname = peer->sni = peer->dispname = NULL;
+ peer->is_ip_address = FALSE;
}
static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -1423,12 +1521,26 @@ static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
if(connssl) {
Curl_ssl->close(cf, data);
connssl->state = ssl_connection_none;
- free_hostname(connssl);
+ Curl_ssl_peer_cleanup(&connssl->peer);
}
cf->connected = FALSE;
}
-static CURLcode reinit_hostname(struct Curl_cfilter *cf)
+static int is_ip_address(const char *hostname)
+{
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+ return (hostname && hostname[0] && (Curl_inet_pton(AF_INET, hostname, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, hostname, &addr)
+#endif
+ ));
+}
+
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf)
{
struct ssl_connect_data *connssl = cf->ctx;
const char *ehostname, *edispname;
@@ -1454,23 +1566,43 @@ static CURLcode reinit_hostname(struct Curl_cfilter *cf)
}
/* change if ehostname changed */
- if(ehostname && (!connssl->hostname
- || strcmp(ehostname, connssl->hostname))) {
- free_hostname(connssl);
- connssl->hostname = strdup(ehostname);
- if(!connssl->hostname) {
- free_hostname(connssl);
+ if(ehostname && (!peer->hostname
+ || strcmp(ehostname, peer->hostname))) {
+ Curl_ssl_peer_cleanup(peer);
+ peer->hostname = strdup(ehostname);
+ if(!peer->hostname) {
+ Curl_ssl_peer_cleanup(peer);
return CURLE_OUT_OF_MEMORY;
}
if(!edispname || !strcmp(ehostname, edispname))
- connssl->dispname = connssl->hostname;
+ peer->dispname = peer->hostname;
else {
- connssl->dispname = strdup(edispname);
- if(!connssl->dispname) {
- free_hostname(connssl);
+ peer->dispname = strdup(edispname);
+ if(!peer->dispname) {
+ Curl_ssl_peer_cleanup(peer);
return CURLE_OUT_OF_MEMORY;
}
}
+
+ peer->sni = NULL;
+ peer->is_ip_address = is_ip_address(peer->hostname)? TRUE : FALSE;
+ if(peer->hostname[0] && !peer->is_ip_address) {
+ /* not an IP address, normalize according to RCC 6066 ch. 3,
+ * max len of SNI is 2^16-1, no trailing dot */
+ size_t len = strlen(peer->hostname);
+ if(len && (peer->hostname[len-1] == '.'))
+ len--;
+ if(len < USHRT_MAX) {
+ peer->sni = calloc(1, len + 1);
+ if(!peer->sni) {
+ Curl_ssl_peer_cleanup(peer);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ Curl_strntolower(peer->sni, peer->hostname, len);
+ peer->sni[len] = 0;
+ }
+ }
+
}
connssl->port = eport;
return CURLE_OK;
@@ -1525,7 +1657,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
goto out;
*done = FALSE;
- result = reinit_hostname(cf);
+ result = Curl_ssl_peer_init(&connssl->peer, cf);
if(result)
goto out;
@@ -1583,38 +1715,49 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
{
struct cf_call_data save;
ssize_t nread;
+ size_t ntotal = 0;
CF_DATA_SAVE(save, cf, data);
*err = CURLE_OK;
- nread = Curl_ssl->recv_plain(cf, data, buf, len, err);
- if(nread > 0) {
- DEBUGASSERT((size_t)nread <= len);
- }
- else if(nread == 0) {
- /* eof */
+ /* Do receive until we fill the buffer somehwhat or EGAIN, error or EOF */
+ while(!ntotal || (len - ntotal) > (4*1024)) {
*err = CURLE_OK;
+ nread = Curl_ssl->recv_plain(cf, data, buf + ntotal, len - ntotal, err);
+ if(nread < 0) {
+ if(*err == CURLE_AGAIN && ntotal > 0) {
+ /* we EAGAINed after having reed data, return the success amount */
+ *err = CURLE_OK;
+ break;
+ }
+ /* we have a an error to report */
+ goto out;
+ }
+ else if(nread == 0) {
+ /* eof */
+ break;
+ }
+ ntotal += (size_t)nread;
+ DEBUGASSERT((size_t)ntotal <= len);
}
- CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len, nread, *err);
+ nread = (ssize_t)ntotal;
+out:
+ CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len,
+ nread, *err);
CF_DATA_RESTORE(cf, save);
return nread;
}
-static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
+static void ssl_cf_adjust_pollset(struct Curl_cfilter *cf,
struct Curl_easy *data,
- curl_socket_t *socks)
+ struct easy_pollset *ps)
{
struct cf_call_data save;
- int fds = GETSOCK_BLANK;
- if(!cf->next->connected) {
- fds = cf->next->cft->get_select_socks(cf->next, data, socks);
- }
- else if(!cf->connected) {
+ if(!cf->connected) {
CF_DATA_SAVE(save, cf, data);
- fds = Curl_ssl->get_select_socks(cf, data, socks);
+ Curl_ssl->adjust_pollset(cf, data, ps);
CF_DATA_RESTORE(cf, save);
}
- return fds;
}
static CURLcode ssl_cf_cntrl(struct Curl_cfilter *cf,
@@ -1705,7 +1848,7 @@ struct Curl_cftype Curl_cft_ssl = {
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
- ssl_cf_get_select_socks,
+ ssl_cf_adjust_pollset,
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
@@ -1715,6 +1858,8 @@ struct Curl_cftype Curl_cft_ssl = {
ssl_cf_query,
};
+#ifndef CURL_DISABLE_PROXY
+
struct Curl_cftype Curl_cft_ssl_proxy = {
"SSL-PROXY",
CF_TYPE_SSL,
@@ -1723,7 +1868,7 @@ struct Curl_cftype Curl_cft_ssl_proxy = {
ssl_cf_connect,
ssl_cf_close,
Curl_cf_def_get_host,
- ssl_cf_get_select_socks,
+ ssl_cf_adjust_pollset,
ssl_cf_data_pending,
ssl_cf_send,
ssl_cf_recv,
@@ -1733,6 +1878,8 @@ struct Curl_cftype Curl_cft_ssl_proxy = {
Curl_cf_def_query,
};
+#endif /* !CURL_DISABLE_PROXY */
+
static CURLcode cf_ssl_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn)
@@ -1837,6 +1984,20 @@ bool Curl_ssl_supports(struct Curl_easy *data, int option)
return (Curl_ssl->supports & option)? TRUE : FALSE;
}
+static struct Curl_cfilter *get_ssl_filter(struct Curl_cfilter *cf)
+{
+ for(; cf; cf = cf->next) {
+ if(cf->cft == &Curl_cft_ssl)
+ return cf;
+#ifndef CURL_DISABLE_PROXY
+ if(cf->cft == &Curl_cft_ssl_proxy)
+ return cf;
+#endif
+ }
+ return NULL;
+}
+
+
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
CURLINFO info, int n)
{
@@ -1844,8 +2005,8 @@ void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
(void)n;
if(data->conn) {
struct Curl_cfilter *cf;
- /* get first filter in chain, if any is present */
- cf = Curl_ssl_cf_get_ssl(data->conn->cfilter[sockindex]);
+ /* get first SSL filter in chain, if any is present */
+ cf = get_ssl_filter(data->conn->cfilter[sockindex]);
if(cf) {
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
@@ -1875,26 +2036,14 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data,
return result;
}
-static struct Curl_cfilter *get_ssl_cf_engaged(struct connectdata *conn,
- int sockindex)
-{
- struct Curl_cfilter *cf, *lowest_ssl_cf = NULL;
-
- for(cf = conn->cfilter[sockindex]; cf; cf = cf->next) {
- if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy) {
- lowest_ssl_cf = cf;
- if(cf->connected || (cf->next && cf->next->connected)) {
- /* connected or about to start */
- return cf;
- }
- }
- }
- return lowest_ssl_cf;
-}
-
bool Curl_ssl_cf_is_proxy(struct Curl_cfilter *cf)
{
+#ifndef CURL_DISABLE_PROXY
return (cf->cft == &Curl_cft_ssl_proxy);
+#else
+ (void)cf;
+ return FALSE;
+#endif
}
struct ssl_config_data *
@@ -1908,17 +2057,6 @@ Curl_ssl_cf_get_config(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
}
-struct ssl_config_data *
-Curl_ssl_get_config(struct Curl_easy *data, int sockindex)
-{
- struct Curl_cfilter *cf;
-
- (void)data;
- DEBUGASSERT(data->conn);
- cf = get_ssl_cf_engaged(data->conn, sockindex);
- return cf? Curl_ssl_cf_get_config(cf, data) : &data->set.ssl;
-}
-
struct ssl_primary_config *
Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
{
@@ -1930,15 +2068,6 @@ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf)
#endif
}
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf)
-{
- for(; cf; cf = cf->next) {
- if(cf->cft == &Curl_cft_ssl || cf->cft == &Curl_cft_ssl_proxy)
- return cf;
- }
- return NULL;
-}
-
CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf,
const struct alpn_spec *spec)
{
@@ -2005,10 +2134,6 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
!memcmp(ALPN_HTTP_1_1, proto, ALPN_HTTP_1_1_LENGTH)) {
*palpn = CURL_HTTP_VERSION_1_1;
}
- else if(proto_len == ALPN_HTTP_1_0_LENGTH &&
- !memcmp(ALPN_HTTP_1_0, proto, ALPN_HTTP_1_0_LENGTH)) {
- *palpn = CURL_HTTP_VERSION_1_0;
- }
#ifdef USE_HTTP2
else if(proto_len == ALPN_H2_LENGTH &&
!memcmp(ALPN_H2, proto, ALPN_H2_LENGTH)) {
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index 8ad1cf6de..744bbf8fd 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -65,15 +65,54 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
-char *Curl_ssl_snihost(struct Curl_easy *data, const char *host, size_t *olen);
-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);
-
curl_sslbackend Curl_ssl_backend(void);
+/**
+ * Init ssl config for a new easy handle.
+ */
+void Curl_ssl_easy_config_init(struct Curl_easy *data);
+
+/**
+ * Init the `data->set.ssl` and `data->set.proxy_ssl` for
+ * connection matching use.
+ */
+CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data);
+
+/**
+ * Init SSL configs (main + proxy) for a new connection from the easy handle.
+ */
+CURLcode Curl_ssl_conn_config_init(struct Curl_easy *data,
+ struct connectdata *conn);
+
+/**
+ * Free allocated resources in SSL configs (main + proxy) for
+ * the given connection.
+ */
+void Curl_ssl_conn_config_cleanup(struct connectdata *conn);
+
+/**
+ * Return TRUE iff SSL configuration from `conn` is functionally the
+ * same as the one on `candidate`.
+ * @param proxy match the proxy SSL config or the main one
+ */
+bool Curl_ssl_conn_config_match(struct Curl_easy *data,
+ struct connectdata *candidate,
+ bool proxy);
+
+/* Update certain connection SSL config flags after they have
+ * been changed on the easy handle. Will work for `verifypeer`,
+ * `verifyhost` and `verifystatus`. */
+void Curl_ssl_conn_config_update(struct Curl_easy *data, bool for_proxy);
+
+/**
+ * Init SSL peer information for filter. Can be called repeatedly.
+ */
+CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, struct Curl_cfilter *cf);
+/**
+ * Free all allocated data and reset peer information.
+ */
+void Curl_ssl_peer_cleanup(struct ssl_peer *peer);
+
#ifdef USE_SSL
int Curl_ssl_init(void);
void Curl_ssl_cleanup(void);
@@ -160,18 +199,6 @@ CURLcode Curl_cf_ssl_proxy_insert_after(struct Curl_cfilter *cf_at,
#endif /* !CURL_DISABLE_PROXY */
/**
- * Get the SSL configuration that is used on the connection.
- * This returns NULL if no SSL is configured.
- * Otherwise it returns the config of the first (highest) one that is
- * either connected, in handshake or about to start
- * (e.g. all filters below it are connected). If SSL filters are present,
- * but neither can start operating, return the config of the lowest one
- * that will first come into effect when connecting.
- */
-struct ssl_config_data *Curl_ssl_get_config(struct Curl_easy *data,
- int sockindex);
-
-/**
* True iff the underlying SSL implementation supports the option.
* Option is one of the defined SSLSUPP_* values.
* `data` maybe NULL for the features of the default implementation.
@@ -188,8 +215,22 @@ bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
CURLINFO info, int n);
+/**
+ * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
+ */
+struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
+ struct Curl_easy *data);
+
+/**
+ * Get the primary config relevant for the filter from its connection.
+ */
+struct ssl_primary_config *
+ Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
+
extern struct Curl_cftype Curl_cft_ssl;
+#ifndef CURL_DISABLE_PROXY
extern struct Curl_cftype Curl_cft_ssl_proxy;
+#endif
#else /* if not USE_SSL */
@@ -209,8 +250,9 @@ extern struct Curl_cftype Curl_cft_ssl_proxy;
#define Curl_ssl_get_internals(a,b,c,d) NULL
#define Curl_ssl_supports(a,b) FALSE
#define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN
-#define Curl_ssl_get_config(a,b) NULL
#define Curl_ssl_cfilter_remove(a,b) CURLE_OK
+#define Curl_ssl_cf_get_config(a,b) NULL
+#define Curl_ssl_cf_get_primary_config(a) NULL
#endif
#endif /* HEADER_CURL_VTLS_H */
diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h
index a6e4544a8..af7ae552e 100644
--- a/lib/vtls/vtls_int.h
+++ b/lib/vtls/vtls_int.h
@@ -32,8 +32,6 @@
/* see https://www.iana.org/assignments/tls-extensiontype-values/ */
#define ALPN_HTTP_1_1_LENGTH 8
#define ALPN_HTTP_1_1 "http/1.1"
-#define ALPN_HTTP_1_0_LENGTH 8
-#define ALPN_HTTP_1_0 "http/1.0"
#define ALPN_H2_LENGTH 2
#define ALPN_H2 "h2"
#define ALPN_H3_LENGTH 2
@@ -70,14 +68,14 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf,
struct ssl_connect_data {
ssl_connection_state state;
ssl_connect_state connecting_state;
- char *hostname; /* hostname for verification */
- char *dispname; /* display version of hostname */
+ struct ssl_peer peer;
const struct alpn_spec *alpn; /* ALPN to use or NULL for none */
void *backend; /* vtls backend specific props */
struct cf_call_data call_data; /* data handle used in current call */
struct curltime handshake_done; /* time when handshake finished */
int port; /* remote port at origin */
BIT(use_alpn); /* if ALPN shall be used in handshake */
+ BIT(reused_session); /* session-ID was reused for this */
};
@@ -118,14 +116,11 @@ struct Curl_ssl {
struct Curl_easy *data,
bool *done);
- /* If the SSL backend wants to read or write on this connection during a
- handshake, set socks[0] to the connection's FIRSTSOCKET, and return
- a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
- GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
- Mandatory. */
- int (*get_select_socks)(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks);
-
+ /* During handshake, adjust the pollset to include the socket
+ * for POLLOUT or POLLIN as needed.
+ * Mandatory. */
+ void (*adjust_pollset)(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps);
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
void (*close)(struct Curl_cfilter *cf, struct Curl_easy *data);
void (*close_all)(struct Curl_easy *data);
@@ -169,25 +164,8 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
bool Curl_none_false_start(void);
-int Curl_ssl_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
- curl_socket_t *socks);
-
-/**
- * Get the ssl_config_data in `data` that is relevant for cfilter `cf`.
- */
-struct ssl_config_data *Curl_ssl_cf_get_config(struct Curl_cfilter *cf,
- struct Curl_easy *data);
-
-/**
- * Get the primary config relevant for the filter from its connection.
- */
-struct ssl_primary_config *
- Curl_ssl_cf_get_primary_config(struct Curl_cfilter *cf);
-
-/**
- * Get the first SSL filter in the chain starting with `cf`, or NULL.
- */
-struct Curl_cfilter *Curl_ssl_cf_get_ssl(struct Curl_cfilter *cf);
+void Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data,
+ struct easy_pollset *ps);
/**
* Get the SSL filter below the given one or NULL if there is none.
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index b1384a644..a3c017cea 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -480,6 +480,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
}
#endif
+ default:
break;
}
@@ -513,7 +514,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
-#ifndef NO_FILESYSTEM
+#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
/* load native CA certificates */
if(ssl_config->native_ca_store) {
if(wolfSSL_CTX_load_system_CA_certs(backend->ctx) != WOLFSSL_SUCCESS) {
@@ -582,12 +583,25 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
if(ssl_config->primary.clientcert && ssl_config->key) {
int file_type = do_file_type(ssl_config->cert_type);
- if(wolfSSL_CTX_use_certificate_file(backend->ctx,
- ssl_config->primary.clientcert,
- file_type) != 1) {
- failf(data, "unable to use client certificate (no key or wrong pass"
- " phrase?)");
- return CURLE_SSL_CONNECT_ERROR;
+ if(file_type == WOLFSSL_FILETYPE_PEM) {
+ if(wolfSSL_CTX_use_certificate_chain_file(backend->ctx,
+ ssl_config->primary.clientcert)
+ != 1) {
+ failf(data, "unable to use client certificate");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else if(file_type == WOLFSSL_FILETYPE_ASN1) {
+ if(wolfSSL_CTX_use_certificate_file(backend->ctx,
+ ssl_config->primary.clientcert,
+ file_type) != 1) {
+ failf(data, "unable to use client certificate");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+ else {
+ failf(data, "unknown cert type");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
}
file_type = do_file_type(ssl_config->key_type);
@@ -608,24 +622,12 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
SSL_VERIFY_NONE, NULL);
#ifdef HAVE_SNI
- if(sni) {
- struct in_addr addr4;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
- size_t hostname_len = strlen(connssl->hostname);
-
- if((hostname_len < USHRT_MAX) &&
- !Curl_inet_pton(AF_INET, connssl->hostname, &addr4)
-#ifdef ENABLE_IPV6
- && !Curl_inet_pton(AF_INET6, connssl->hostname, &addr6)
-#endif
- ) {
- size_t snilen;
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, &snilen);
- if(!snihost ||
- wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, snihost,
- (unsigned short)snilen) != 1) {
+ if(sni && connssl->peer.sni) {
+ size_t sni_len = strlen(connssl->peer.sni);
+ if((sni_len < USHRT_MAX)) {
+ if(wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME,
+ connssl->peer.sni,
+ (unsigned short)sni_len) != 1) {
failf(data, "Failed to set SNI");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -763,9 +765,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
/* Enable RFC2818 checks */
if(conn_config->verifyhost) {
- char *snihost = Curl_ssl_snihost(data, connssl->hostname, NULL);
- if(!snihost ||
- (wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE))
+ char *snihost = connssl->peer.sni?
+ connssl->peer.sni : connssl->peer.hostname;
+ if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)
return CURLE_SSL_CONNECT_ERROR;
}
@@ -813,7 +815,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
failf(data, " subject alt name(s) or common name do not match \"%s\"",
- connssl->dispname);
+ connssl->peer.dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
/* When the wolfssl_check_domain_name() is used and you desire to
@@ -1095,9 +1097,7 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
*curlcode = CURLE_OK;
return 0;
case SSL_ERROR_NONE:
- /* FALLTHROUGH */
case SSL_ERROR_WANT_READ:
- /* FALLTHROUGH */
case SSL_ERROR_WANT_WRITE:
/* there's data pending, re-invoke wolfSSL_read() */
CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
@@ -1398,7 +1398,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
Curl_none_cert_status_request, /* cert_status_request */
wolfssl_connect, /* connect */
wolfssl_connect_nonblocking, /* connect_nonblocking */
- Curl_ssl_get_select_socks, /* getsock */
+ Curl_ssl_adjust_pollset, /* adjust_pollset */
wolfssl_get_internals, /* get_internals */
wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
diff --git a/lib/vtls/x509asn1.c b/lib/vtls/x509asn1.c
index c3fd3a30b..da079361d 100644
--- a/lib/vtls/x509asn1.c
+++ b/lib/vtls/x509asn1.c
@@ -97,6 +97,11 @@
#define CURL_ASN1_CHARACTER_STRING 29
#define CURL_ASN1_BMP_STRING 30
+/* Max sixes */
+
+#define MAX_X509_STR 10000
+#define MAX_X509_CERT 100000
+
#ifdef WANT_EXTRACT_CERTINFO
/* ASN.1 OID table entry. */
struct Curl_OID {
@@ -255,61 +260,61 @@ static const struct Curl_OID *searchOID(const char *oid)
}
/*
- * Convert an ASN.1 Boolean value into its string representation. Return the
- * dynamically allocated string, or NULL if source is not an ASN.1 Boolean
- * value.
+ * Convert an ASN.1 Boolean value into its string representation.
+ *
+ * Return error code.
*/
-static const char *bool2str(const char *beg, const char *end)
+static CURLcode bool2str(struct dynbuf *store,
+ const char *beg, const char *end)
{
if(end - beg != 1)
- return NULL;
- return strdup(*beg? "TRUE": "FALSE");
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return Curl_dyn_add(store, *beg? "TRUE": "FALSE");
}
/*
* Convert an ASN.1 octet string to a printable string.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ *
+ * Return error code.
*/
-static const char *octet2str(const char *beg, const char *end)
+static CURLcode octet2str(struct dynbuf *store,
+ const char *beg, const char *end)
{
- struct dynbuf buf;
- CURLcode result;
-
- Curl_dyn_init(&buf, 3 * CURL_ASN1_MAX + 1);
- result = Curl_dyn_addn(&buf, "", 0);
+ CURLcode result = CURLE_OK;
while(!result && beg < end)
- result = Curl_dyn_addf(&buf, "%02x:", (unsigned char) *beg++);
+ result = Curl_dyn_addf(store, "%02x:", (unsigned char) *beg++);
- return Curl_dyn_ptr(&buf);
+ return result;
}
-static const char *bit2str(const char *beg, const char *end)
+static CURLcode bit2str(struct dynbuf *store,
+ const char *beg, const char *end)
{
- /* Convert an ASN.1 bit string to a printable string.
- Return the dynamically allocated string, or NULL if an error occurs. */
+ /* Convert an ASN.1 bit string to a printable string. */
if(++beg > end)
- return NULL;
- return octet2str(beg, end);
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ return octet2str(store, beg, end);
}
/*
* Convert an ASN.1 integer value into its string representation.
- * Return the dynamically allocated string, or NULL if source is not an
- * ASN.1 integer value.
+ *
+ * Returns error.
*/
-static const char *int2str(const char *beg, const char *end)
+static CURLcode int2str(struct dynbuf *store,
+ const char *beg, const char *end)
{
unsigned int val = 0;
size_t n = end - beg;
if(!n)
- return NULL;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
if(n > 4)
- return octet2str(beg, end);
+ return octet2str(store, beg, end);
/* Represent integers <= 32-bit as a single value. */
if(*beg & 0x80)
@@ -318,25 +323,24 @@ static const char *int2str(const char *beg, const char *end)
do
val = (val << 8) | *(const unsigned char *) beg++;
while(beg < end);
- return curl_maprintf("%s%x", val >= 10? "0x": "", val);
+ return Curl_dyn_addf(store, "%s%x", val >= 10? "0x": "", val);
}
/*
- * Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
- * destination buffer dynamically. The allocation size will normally be too
- * large: this is to avoid buffer overflows.
- * Terminate the string with a nul byte and return the converted
- * string length.
+ * Convert from an ASN.1 typed string to UTF8.
+ *
+ * The result is stored in a dynbuf that is inited by the user of this
+ * function.
+ *
+ * Returns error.
*/
-static ssize_t
-utf8asn1str(char **to, int type, const char *from, const char *end)
+static CURLcode
+utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end)
{
size_t inlength = end - from;
int size = 1;
- size_t outlength;
- char *buf;
+ CURLcode result = CURLE_OK;
- *to = NULL;
switch(type) {
case CURL_ASN1_BMP_STRING:
size = 2;
@@ -352,133 +356,85 @@ utf8asn1str(char **to, int type, const char *from, const char *end)
case CURL_ASN1_UTF8_STRING:
break;
default:
- return -1; /* Conversion not supported. */
+ return CURLE_BAD_FUNCTION_ARGUMENT; /* Conversion not supported. */
}
if(inlength % size)
- return -1; /* Length inconsistent with character size. */
- if(inlength / size > (SIZE_T_MAX - 1) / 4)
- return -1; /* Too big. */
- buf = malloc(4 * (inlength / size) + 1);
- if(!buf)
- return -1; /* Not enough memory. */
+ /* Length inconsistent with character size. */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
if(type == CURL_ASN1_UTF8_STRING) {
/* Just copy. */
- outlength = inlength;
- if(outlength)
- memcpy(buf, from, outlength);
+ if(inlength)
+ result = Curl_dyn_addn(to, from, inlength);
}
else {
- for(outlength = 0; from < end;) {
- int charsize;
- unsigned int wc;
+ while(!result && (from < end)) {
+ char buf[4]; /* decode buffer */
+ int charsize = 1;
+ unsigned int wc = 0;
- wc = 0;
switch(size) {
case 4:
wc = (wc << 8) | *(const unsigned char *) from++;
wc = (wc << 8) | *(const unsigned char *) from++;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case 2:
wc = (wc << 8) | *(const unsigned char *) from++;
- /* FALLTHROUGH */
+ FALLTHROUGH();
default: /* case 1: */
wc = (wc << 8) | *(const unsigned char *) from++;
}
- charsize = 1;
if(wc >= 0x00000080) {
if(wc >= 0x00000800) {
if(wc >= 0x00010000) {
if(wc >= 0x00200000) {
free(buf);
- return -1; /* Invalid char. size for target encoding. */
+ /* Invalid char. size for target encoding. */
+ return CURLE_WEIRD_SERVER_REPLY;
}
- buf[outlength + 3] = (char) (0x80 | (wc & 0x3F));
+ buf[3] = (char) (0x80 | (wc & 0x3F));
wc = (wc >> 6) | 0x00010000;
charsize++;
}
- buf[outlength + 2] = (char) (0x80 | (wc & 0x3F));
+ buf[2] = (char) (0x80 | (wc & 0x3F));
wc = (wc >> 6) | 0x00000800;
charsize++;
}
- buf[outlength + 1] = (char) (0x80 | (wc & 0x3F));
+ buf[1] = (char) (0x80 | (wc & 0x3F));
wc = (wc >> 6) | 0x000000C0;
charsize++;
}
- buf[outlength] = (char) wc;
- outlength += charsize;
+ buf[0] = (char) wc;
+ result = Curl_dyn_addn(to, buf, charsize);
}
}
- buf[outlength] = '\0';
- *to = buf;
- return outlength;
-}
-
-/*
- * Convert an ASN.1 String into its UTF-8 string representation.
- * Return the dynamically allocated string, or NULL if an error occurs.
- */
-static const char *string2str(int type, const char *beg, const char *end)
-{
- char *buf;
- if(utf8asn1str(&buf, type, beg, end) < 0)
- return NULL;
- return buf;
-}
-
-/*
- * Decimal ASCII encode unsigned integer `x' into the buflen sized buffer at
- * buf. Return the total number of encoded digits, even if larger than
- * `buflen'.
- */
-static size_t encodeUint(char *buf, size_t buflen, unsigned int x)
-{
- size_t i = 0;
- unsigned int y = x / 10;
-
- if(y) {
- i = encodeUint(buf, buflen, y);
- x -= y * 10;
- }
- if(i < buflen)
- buf[i] = (char) ('0' + x);
- i++;
- if(i < buflen)
- buf[i] = '\0'; /* Store a terminator if possible. */
- return i;
+ return result;
}
/*
* Convert an ASN.1 OID into its dotted string representation.
- * Store the result in th `n'-byte buffer at `buf'.
- * Return the converted string length, or 0 on errors.
+ *
+ * Return error code.
*/
-static size_t encodeOID(char *buf, size_t buflen,
- const char *beg, const char *end)
+static CURLcode encodeOID(struct dynbuf *store,
+ const char *beg, const char *end)
{
- size_t i;
unsigned int x;
unsigned int y;
+ CURLcode result = CURLE_OK;
/* Process the first two numbers. */
y = *(const unsigned char *) beg++;
x = y / 40;
y -= x * 40;
- i = encodeUint(buf, buflen, x);
- if(i < buflen)
- buf[i] = '.';
- i++;
- if(i >= buflen)
- i += encodeUint(NULL, 0, y);
- else
- i += encodeUint(buf + i, buflen - i, y);
+
+ result = Curl_dyn_addf(store, "%u.%u", x, y);
+ if(result)
+ return result;
/* Process the trailing numbers. */
while(beg < end) {
- if(i < buflen)
- buf[i] = '.';
- i++;
x = 0;
do {
if(x & 0xFF000000)
@@ -486,46 +442,42 @@ static size_t encodeOID(char *buf, size_t buflen,
y = *(const unsigned char *) beg++;
x = (x << 7) | (y & 0x7F);
} while(y & 0x80);
- if(i >= buflen)
- i += encodeUint(NULL, 0, x);
- else
- i += encodeUint(buf + i, buflen - i, x);
+ result = Curl_dyn_addf(store, ".%u", x);
}
- if(i < buflen)
- buf[i] = '\0';
- return i;
+ return result;
}
/*
* Convert an ASN.1 OID into its dotted or symbolic string representation.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ *
+ * Return error code.
*/
-static const char *OID2str(const char *beg, const char *end, bool symbolic)
+static CURLcode OID2str(struct dynbuf *store,
+ const char *beg, const char *end, bool symbolic)
{
- char *buf = NULL;
+ CURLcode result = CURLE_OK;
if(beg < end) {
- size_t buflen = encodeOID(NULL, 0, beg, end);
- if(buflen) {
- buf = malloc(buflen + 1); /* one extra for the zero byte */
- if(buf) {
- encodeOID(buf, buflen, beg, end);
- buf[buflen] = '\0';
-
- if(symbolic) {
- const struct Curl_OID *op = searchOID(buf);
- if(op) {
- free(buf);
- buf = strdup(op->textoid);
- }
- }
+ if(symbolic) {
+ struct dynbuf buf;
+ Curl_dyn_init(&buf, MAX_X509_STR);
+ result = encodeOID(&buf, beg, end);
+
+ if(!result) {
+ const struct Curl_OID *op = searchOID(Curl_dyn_ptr(&buf));
+ if(op)
+ result = Curl_dyn_add(store, op->textoid);
+ Curl_dyn_free(&buf);
}
}
+ else
+ result = encodeOID(store, beg, end);
}
- return buf;
+ return result;
}
-static const char *GTime2str(const char *beg, const char *end)
+static CURLcode GTime2str(struct dynbuf *store,
+ const char *beg, const char *end)
{
const char *tzp;
const char *fracp;
@@ -548,12 +500,12 @@ static const char *GTime2str(const char *beg, const char *end)
break;
case 2:
sec1 = fracp[-2];
- /* FALLTHROUGH */
+ FALLTHROUGH();
case 1:
sec2 = fracp[-1];
break;
default:
- return NULL;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
}
/* Scan for timezone, measure fractional seconds. */
@@ -582,7 +534,8 @@ static const char *GTime2str(const char *beg, const char *end)
}
tzl = end - tzp;
- return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
+ return Curl_dyn_addf(store,
+ "%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s",
beg, beg + 4, beg + 6,
beg + 8, beg + 10, sec1, sec2,
fracl? ".": "", (int)fracl, fracp,
@@ -590,10 +543,12 @@ static const char *GTime2str(const char *beg, const char *end)
}
/*
- * Convert an ASN.1 UTC time to a printable string.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ * Convert an ASN.1 UTC time to a printable string.
+ *
+ * Return error code.
*/
-static const char *UTime2str(const char *beg, const char *end)
+static CURLcode UTime2str(struct dynbuf *store,
+ const char *beg, const char *end)
{
const char *tzp;
size_t tzl;
@@ -606,15 +561,16 @@ static const char *UTime2str(const char *beg, const char *end)
switch(tzp - sec) {
case 0:
sec = "00";
+ FALLTHROUGH();
case 2:
break;
default:
- return NULL;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
}
/* Process timezone. */
if(tzp >= end)
- return NULL;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
if(*tzp == 'Z') {
tzp = "GMT";
end = tzp + 3;
@@ -623,7 +579,7 @@ static const char *UTime2str(const char *beg, const char *end)
tzp++;
tzl = end - tzp;
- return curl_maprintf("%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
+ return Curl_dyn_addf(store, "%u%.2s-%.2s-%.2s %.2s:%.2s:%.2s %.*s",
20 - (*beg >= '5'), beg, beg + 2, beg + 4,
beg + 6, beg + 8, sec,
(int)tzl, tzp);
@@ -631,34 +587,45 @@ 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.
+ *
+ * Return error
*/
-static const char *ASN1tostr(struct Curl_asn1Element *elem, int type)
+static CURLcode ASN1tostr(struct dynbuf *store,
+ struct Curl_asn1Element *elem, int type)
{
+ CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
if(elem->constructed)
- return NULL; /* No conversion of structured elements. */
+ return CURLE_OK; /* No conversion of structured elements. */
if(!type)
type = elem->tag; /* Type not forced: use element tag as type. */
switch(type) {
case CURL_ASN1_BOOLEAN:
- return bool2str(elem->beg, elem->end);
+ result = bool2str(store, elem->beg, elem->end);
+ break;
case CURL_ASN1_INTEGER:
case CURL_ASN1_ENUMERATED:
- return int2str(elem->beg, elem->end);
+ result = int2str(store, elem->beg, elem->end);
+ break;
case CURL_ASN1_BIT_STRING:
- return bit2str(elem->beg, elem->end);
+ result = bit2str(store, elem->beg, elem->end);
+ break;
case CURL_ASN1_OCTET_STRING:
- return octet2str(elem->beg, elem->end);
+ result = octet2str(store, elem->beg, elem->end);
+ break;
case CURL_ASN1_NULL:
- return strdup("");
+ result = Curl_dyn_addn(store, "", 1);
+ break;
case CURL_ASN1_OBJECT_IDENTIFIER:
- return OID2str(elem->beg, elem->end, TRUE);
+ result = OID2str(store, elem->beg, elem->end, TRUE);
+ break;
case CURL_ASN1_UTC_TIME:
- return UTime2str(elem->beg, elem->end);
+ result = UTime2str(store, elem->beg, elem->end);
+ break;
case CURL_ASN1_GENERALIZED_TIME:
- return GTime2str(elem->beg, elem->end);
+ result = GTime2str(store, elem->beg, elem->end);
+ break;
case CURL_ASN1_UTF8_STRING:
case CURL_ASN1_NUMERIC_STRING:
case CURL_ASN1_PRINTABLE_STRING:
@@ -667,87 +634,96 @@ static const char *ASN1tostr(struct Curl_asn1Element *elem, int type)
case CURL_ASN1_VISIBLE_STRING:
case CURL_ASN1_UNIVERSAL_STRING:
case CURL_ASN1_BMP_STRING:
- return string2str(type, elem->beg, elem->end);
+ result = utf8asn1str(store, type, elem->beg, elem->end);
+ break;
}
- return NULL; /* Unsupported. */
+ return result;
}
/*
- * ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at
- * `buf'.
+ * ASCII encode distinguished name at `dn' into the store dynbuf.
*
- * Returns the total string length, even if larger than `buflen' or -1 on
- * error.
+ * Returns error.
*/
-static ssize_t encodeDN(char *buf, size_t buflen, struct Curl_asn1Element *dn)
+static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
{
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;
const char *p3;
const char *str;
+ CURLcode result = CURLE_OK;
+ bool added = FALSE;
+ struct dynbuf temp;
+ Curl_dyn_init(&temp, MAX_X509_STR);
for(p1 = dn->beg; p1 < dn->end;) {
p1 = getASN1Element(&rdn, p1, dn->end);
- if(!p1)
- return -1;
+ if(!p1) {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto error;
+ }
for(p2 = rdn.beg; p2 < rdn.end;) {
p2 = getASN1Element(&atv, p2, rdn.end);
- if(!p2)
- return -1;
+ if(!p2) {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto error;
+ }
p3 = getASN1Element(&oid, atv.beg, atv.end);
- if(!p3)
- return -1;
- if(!getASN1Element(&value, p3, atv.end))
- return -1;
- str = ASN1tostr(&oid, 0);
- if(!str)
- return -1;
+ if(!p3) {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto error;
+ }
+ if(!getASN1Element(&value, p3, atv.end)) {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto error;
+ }
+ Curl_dyn_reset(&temp);
+ result = ASN1tostr(&temp, &oid, 0);
+ if(result)
+ goto error;
+
+ str = Curl_dyn_ptr(&temp);
/* Encode delimiter.
If attribute has a short uppercase name, delimiter is ", ". */
- if(l) {
- for(p3 = str; ISUPPER(*p3); p3++)
- ;
- for(p3 = (*p3 || p3 - str > 2)? "/": ", "; *p3; p3++) {
- if(l < buflen)
- buf[l] = *p3;
- l++;
- }
+ for(p3 = str; ISUPPER(*p3); p3++)
+ ;
+ if(added) {
+ if(p3 - str > 2)
+ result = Curl_dyn_addn(store, "/", 1);
+ else
+ result = Curl_dyn_addn(store, ", ", 2);
+ if(result)
+ goto error;
}
/* Encode attribute name. */
- for(p3 = str; *p3; p3++) {
- if(l < buflen)
- buf[l] = *p3;
- l++;
- }
- free((char *) str);
+ result = Curl_dyn_add(store, str);
+ if(result)
+ goto error;
/* Generate equal sign. */
- if(l < buflen)
- buf[l] = '=';
- l++;
+ result = Curl_dyn_addn(store, "=", 1);
+ if(result)
+ goto error;
/* Generate value. */
- str = ASN1tostr(&value, 0);
- if(!str)
- return -1;
- for(p3 = str; *p3; p3++) {
- if(l < buflen)
- buf[l] = *p3;
- l++;
- }
- free((char *) str);
+ result = ASN1tostr(store, &value, 0);
+ if(result)
+ goto error;
+ Curl_dyn_reset(&temp);
+ added = TRUE; /* use separator for next */
}
}
+error:
+ Curl_dyn_free(&temp);
- return l;
+ return result;
}
#endif /* WANT_EXTRACT_CERTINFO */
@@ -876,25 +852,9 @@ int Curl_parseX509(struct Curl_X509certificate *cert,
#ifdef WANT_EXTRACT_CERTINFO
-/*
- * Copy at most 64-characters, terminate with a newline and returns the
- * effective number of stored characters.
- */
-static size_t copySubstring(char *to, const char *from)
-{
- size_t i;
- for(i = 0; i < 64; i++) {
- to[i] = *from;
- if(!*from++)
- break;
- }
-
- to[i++] = '\n';
- return i;
-}
-
-static const char *dumpAlgo(struct Curl_asn1Element *param,
- const char *beg, const char *end)
+static CURLcode dumpAlgo(struct dynbuf *store,
+ struct Curl_asn1Element *param,
+ const char *beg, const char *end)
{
struct Curl_asn1Element oid;
@@ -902,14 +862,16 @@ static const char *dumpAlgo(struct Curl_asn1Element *param,
beg = getASN1Element(&oid, beg, end);
if(!beg)
- return NULL;
+ return CURLE_BAD_FUNCTION_ARGUMENT;
param->header = NULL;
param->tag = 0;
param->beg = param->end = end;
- if(beg < end)
- if(!getASN1Element(param, beg, end))
- return NULL;
- return OID2str(oid.beg, oid.end, TRUE);
+ if(beg < end) {
+ const char *p = getASN1Element(param, beg, end);
+ if(!p)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ return OID2str(store, oid.beg, oid.end, TRUE);
}
/*
@@ -926,24 +888,47 @@ static CURLcode ssl_push_certinfo(struct Curl_easy *data,
return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
}
-/* return 0 on success, 1 on error */
-static int do_pubkey_field(struct Curl_easy *data, int certnum,
- const char *label, struct Curl_asn1Element *elem)
+/*
+ * This is a convenience function for push_certinfo_len that takes a
+ * dynbuf value.
+ *
+ * It also does the verbose output if !certnum.
+ */
+static CURLcode ssl_push_certinfo_dyn(struct Curl_easy *data,
+ int certnum,
+ const char *label,
+ struct dynbuf *ptr)
{
- const char *output;
- CURLcode result = CURLE_OK;
+ size_t valuelen = Curl_dyn_len(ptr);
+ char *value = Curl_dyn_ptr(ptr);
+
+ CURLcode result = Curl_ssl_push_certinfo_len(data, certnum, label,
+ value, valuelen);
+
+ if(!certnum && !result)
+ infof(data, " %s: %s", label, value);
+
+ return result;
+}
+
+static CURLcode do_pubkey_field(struct Curl_easy *data, int certnum,
+ const char *label,
+ struct Curl_asn1Element *elem)
+{
+ CURLcode result;
+ struct dynbuf out;
+
+ Curl_dyn_init(&out, MAX_X509_STR);
/* Generate a certificate information record for the public key. */
- output = ASN1tostr(elem, 0);
- if(output) {
+ result = ASN1tostr(&out, elem, 0);
+ if(!result) {
if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, label, output);
- if(!certnum && !result)
- infof(data, " %s: %s", label, output);
- free((char *) output);
+ result = ssl_push_certinfo_dyn(data, certnum, label, &out);
+ Curl_dyn_free(&out);
}
- return result ? 1 : 0;
+ return result;
}
/* return 0 on success, 1 on error */
@@ -964,7 +949,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
*/
const size_t len = ((pubkey->end - pubkey->beg - 2) * 4);
if(!certnum)
- infof(data, " ECC Public Key (%lu bits)", len);
+ infof(data, " ECC Public Key (%zu bits)", len);
if(data->set.ssl.certinfo) {
char q[sizeof(len) * 8 / 3 + 1];
(void)msnprintf(q, sizeof(q), "%zu", len);
@@ -998,7 +983,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
if(len > 32)
elem.beg = q; /* Strip leading zero bytes. */
if(!certnum)
- infof(data, " RSA Public Key (%lu bits)", len);
+ infof(data, " RSA Public Key (%zu bits)", len);
if(data->set.ssl.certinfo) {
char r[sizeof(len) * 8 / 3 + 1];
msnprintf(r, sizeof(r), "%zu", len);
@@ -1049,24 +1034,12 @@ static int do_pubkey(struct Curl_easy *data, int certnum,
/*
* Convert an ASN.1 distinguished name into a printable string.
- * Return the dynamically allocated string, or NULL if an error occurs.
+ * Return error.
*/
-static const char *DNtostr(struct Curl_asn1Element *dn)
+static CURLcode DNtostr(struct dynbuf *store,
+ struct Curl_asn1Element *dn)
{
- char *buf = NULL;
- ssize_t buflen = encodeDN(NULL, 0, dn);
-
- if(buflen >= 0) {
- buf = malloc(buflen + 1);
- if(buf) {
- if(encodeDN(buf, buflen + 1, dn) == -1) {
- free(buf);
- return NULL;
- }
- buf[buflen] = '\0';
- }
- }
- return buf;
+ return encodeDN(store, dn);
}
CURLcode Curl_extract_certinfo(struct Curl_easy *data,
@@ -1076,19 +1049,19 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
{
struct Curl_X509certificate cert;
struct Curl_asn1Element param;
- const char *ccp;
- char *cp1;
- size_t cl1;
- char *cp2;
+ char *certptr;
+ size_t clen;
+ struct dynbuf out;
CURLcode result = CURLE_OK;
unsigned int version;
- size_t i;
- size_t j;
+ const char *ptr;
+ int rc;
if(!data->set.ssl.certinfo)
if(certnum)
return CURLE_OK;
+ Curl_dyn_init(&out, MAX_X509_STR);
/* Prepare the certificate information for curl_easy_getinfo(). */
/* Extract the certificate ASN.1 elements. */
@@ -1096,135 +1069,126 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
return CURLE_PEER_FAILED_VERIFICATION;
/* Subject. */
- ccp = DNtostr(&cert.subject);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
+ result = DNtostr(&out, &cert.subject);
+ if(result)
+ goto done;
if(data->set.ssl.certinfo) {
- result = ssl_push_certinfo(data, certnum, "Subject", ccp);
+ result = ssl_push_certinfo_dyn(data, certnum, "Subject", &out);
if(result)
- return result;
+ goto done;
}
- if(!certnum)
- infof(data, "%2d Subject: %s", certnum, ccp);
- free((char *) ccp);
+ Curl_dyn_reset(&out);
/* Issuer. */
- ccp = DNtostr(&cert.issuer);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
+ result = DNtostr(&out, &cert.issuer);
+ if(result)
+ goto done;
if(data->set.ssl.certinfo) {
- result = ssl_push_certinfo(data, certnum, "Issuer", ccp);
+ result = ssl_push_certinfo_dyn(data, certnum, "Issuer", &out);
+ if(result)
+ goto done;
}
- if(!certnum)
- infof(data, " Issuer: %s", ccp);
- free((char *) ccp);
- if(result)
- return result;
+ Curl_dyn_reset(&out);
/* Version (always fits in less than 32 bits). */
version = 0;
- for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
- version = (version << 8) | *(const unsigned char *) ccp;
+ for(ptr = cert.version.beg; ptr < cert.version.end; ptr++)
+ version = (version << 8) | *(const unsigned char *) ptr;
if(data->set.ssl.certinfo) {
- ccp = curl_maprintf("%x", version);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
- result = ssl_push_certinfo(data, certnum, "Version", ccp);
- free((char *) ccp);
+ result = Curl_dyn_addf(&out, "%x", version);
+ if(result)
+ goto done;
+ result = ssl_push_certinfo_dyn(data, certnum, "Version", &out);
if(result)
- return result;
+ goto done;
+ Curl_dyn_reset(&out);
}
- if(!certnum)
- infof(data, " Version: %u (0x%x)", version + 1, version);
/* Serial number. */
- ccp = ASN1tostr(&cert.serialNumber, 0);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
- if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, "Serial Number", ccp);
- if(!certnum)
- infof(data, " Serial Number: %s", ccp);
- free((char *) ccp);
+ result = ASN1tostr(&out, &cert.serialNumber, 0);
if(result)
- return result;
+ goto done;
+ if(data->set.ssl.certinfo) {
+ result = ssl_push_certinfo_dyn(data, certnum, "Serial Number", &out);
+ if(result)
+ goto done;
+ }
+ Curl_dyn_reset(&out);
/* Signature algorithm .*/
- ccp = dumpAlgo(&param, cert.signatureAlgorithm.beg,
- cert.signatureAlgorithm.end);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
- if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
- if(!certnum)
- infof(data, " Signature Algorithm: %s", ccp);
- free((char *) ccp);
+ result = dumpAlgo(&out, &param, cert.signatureAlgorithm.beg,
+ cert.signatureAlgorithm.end);
if(result)
- return result;
+ goto done;
+ if(data->set.ssl.certinfo) {
+ result = ssl_push_certinfo_dyn(data, certnum, "Signature Algorithm",
+ &out);
+ if(result)
+ goto done;
+ }
+ Curl_dyn_reset(&out);
/* Start Date. */
- ccp = ASN1tostr(&cert.notBefore, 0);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
- if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, "Start Date", ccp);
- if(!certnum)
- infof(data, " Start Date: %s", ccp);
- free((char *) ccp);
+ result = ASN1tostr(&out, &cert.notBefore, 0);
if(result)
- return result;
+ goto done;
+ if(data->set.ssl.certinfo) {
+ result = ssl_push_certinfo_dyn(data, certnum, "Start Date", &out);
+ if(result)
+ goto done;
+ }
+ Curl_dyn_reset(&out);
/* Expire Date. */
- ccp = ASN1tostr(&cert.notAfter, 0);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
- if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, "Expire Date", ccp);
- if(!certnum)
- infof(data, " Expire Date: %s", ccp);
- free((char *) ccp);
+ result = ASN1tostr(&out, &cert.notAfter, 0);
if(result)
- return result;
+ goto done;
+ if(data->set.ssl.certinfo) {
+ result = ssl_push_certinfo_dyn(data, certnum, "Expire Date", &out);
+ if(result)
+ goto done;
+ }
+ Curl_dyn_reset(&out);
/* Public Key Algorithm. */
- ccp = dumpAlgo(&param, cert.subjectPublicKeyAlgorithm.beg,
- cert.subjectPublicKeyAlgorithm.end);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
- if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, "Public Key Algorithm",
- ccp);
- if(!result) {
- int ret;
- if(!certnum)
- infof(data, " Public Key Algorithm: %s", ccp);
- ret = do_pubkey(data, certnum, ccp, &param, &cert.subjectPublicKey);
- if(ret)
- result = CURLE_OUT_OF_MEMORY; /* the most likely error */
- }
- free((char *) ccp);
+ result = dumpAlgo(&out, &param, cert.subjectPublicKeyAlgorithm.beg,
+ cert.subjectPublicKeyAlgorithm.end);
if(result)
- return result;
+ goto done;
+ if(data->set.ssl.certinfo) {
+ result = ssl_push_certinfo_dyn(data, certnum, "Public Key Algorithm",
+ &out);
+ if(result)
+ goto done;
+ }
+
+ rc = do_pubkey(data, certnum, Curl_dyn_ptr(&out),
+ &param, &cert.subjectPublicKey);
+ if(rc) {
+ result = CURLE_OUT_OF_MEMORY; /* the most likely error */
+ goto done;
+ }
+ Curl_dyn_reset(&out);
/* Signature. */
- ccp = ASN1tostr(&cert.signature, 0);
- if(!ccp)
- return CURLE_OUT_OF_MEMORY;
- if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, "Signature", ccp);
- if(!certnum)
- infof(data, " Signature: %s", ccp);
- free((char *) ccp);
+ result = ASN1tostr(&out, &cert.signature, 0);
if(result)
- return result;
+ goto done;
+ if(data->set.ssl.certinfo) {
+ result = ssl_push_certinfo_dyn(data, certnum, "Signature", &out);
+ if(result)
+ goto done;
+ }
+ Curl_dyn_reset(&out);
/* Generate PEM certificate. */
result = Curl_base64_encode(cert.certificate.beg,
cert.certificate.end - cert.certificate.beg,
- &cp1, &cl1);
+ &certptr, &clen);
if(result)
- return result;
- /* Compute the number of characters in final certificate string. Format is:
+ goto done;
+
+ /* Generate the final output certificate string. Format is:
-----BEGIN CERTIFICATE-----\n
<max 64 base64 characters>\n
.
@@ -1232,207 +1196,34 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
.
-----END CERTIFICATE-----\n
*/
- i = 28 + cl1 + (cl1 + 64 - 1) / 64 + 26;
- cp2 = malloc(i + 1);
- if(!cp2) {
- free(cp1);
- return CURLE_OUT_OF_MEMORY;
- }
- /* Build the certificate string. */
- i = copySubstring(cp2, "-----BEGIN CERTIFICATE-----");
- for(j = 0; j < cl1; j += 64)
- i += copySubstring(cp2 + i, cp1 + j);
- i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
- cp2[i] = '\0';
- free(cp1);
- if(data->set.ssl.certinfo)
- result = ssl_push_certinfo(data, certnum, "Cert", cp2);
- if(!certnum)
- infof(data, "%s", cp2);
- free(cp2);
- return result;
-}
-#endif /* WANT_EXTRACT_CERTINFO */
-
-#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
+ Curl_dyn_reset(&out);
-#ifdef WANT_VERIFYHOST
-
-static const char *checkOID(const char *beg, const char *end,
- const char *oid)
-{
- struct Curl_asn1Element e;
- const char *ccp;
- const char *p;
- bool matched;
-
- /* Check if first ASN.1 element at `beg' is the given OID.
- Return a pointer in the source after the OID if found, else NULL. */
-
- ccp = getASN1Element(&e, beg, end);
- if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
- return NULL;
-
- p = OID2str(e.beg, e.end, FALSE);
- if(!p)
- return NULL;
-
- matched = !strcmp(p, oid);
- free((char *) p);
- return matched? ccp: NULL;
-}
-
-CURLcode Curl_verifyhost(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const char *beg, const char *end)
-{
- struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- 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;
- size_t hostlen;
-
-#ifdef ENABLE_IPV6
- struct in6_addr addr;
-#else
- struct in_addr addr;
-#endif
-
- /* Verify that connection server matches info in X509 certificate at
- `beg'..`end'. */
-
- if(!conn_config->verifyhost)
- return CURLE_OK;
-
- if(Curl_parseX509(&cert, beg, end))
- return CURLE_PEER_FAILED_VERIFICATION;
-
- hostlen = strlen(connssl->hostname);
-
- /* Get the server IP address. */
-#ifdef ENABLE_IPV6
- if(cf->conn->bits.ipv6_ip &&
- Curl_inet_pton(AF_INET6, connssl->hostname, &addr))
- addrlen = sizeof(struct in6_addr);
- else
-#endif
- if(Curl_inet_pton(AF_INET, connssl->hostname, &addr))
- addrlen = sizeof(struct in_addr);
-
- /* Process extensions. */
- for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
- p = getASN1Element(&ext, p, cert.extensions.end);
- if(!p)
- return CURLE_PEER_FAILED_VERIFICATION;
-
- /* Check if extension is a subjectAlternativeName. */
- ext.beg = checkOID(ext.beg, ext.end, sanOID);
- if(ext.beg) {
- ext.beg = getASN1Element(&elem, ext.beg, ext.end);
- if(!ext.beg)
- return CURLE_PEER_FAILED_VERIFICATION;
- /* Skip critical if present. */
- if(elem.tag == CURL_ASN1_BOOLEAN) {
- ext.beg = getASN1Element(&elem, ext.beg, ext.end);
- if(!ext.beg)
- return CURLE_PEER_FAILED_VERIFICATION;
- }
- /* Parse the octet string contents: is a single sequence. */
- if(!getASN1Element(&elem, elem.beg, elem.end))
- return CURLE_PEER_FAILED_VERIFICATION;
- /* Check all GeneralNames. */
- for(q = elem.beg; matched != 1 && q < elem.end;) {
- q = getASN1Element(&name, q, elem.end);
- if(!q)
- break;
- switch(name.tag) {
- case 2: /* DNS name. */
- len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
- name.beg, name.end);
- if(len > 0 && (size_t)len == strlen(dnsname))
- matched = Curl_cert_hostcheck(dnsname, (size_t)len,
- connssl->hostname, hostlen);
- else
- matched = 0;
- free(dnsname);
- break;
-
- case 7: /* IP address. */
- matched = (size_t)(name.end - name.beg) == addrlen &&
- !memcmp(&addr, name.beg, addrlen);
- break;
- }
- }
- }
- }
-
- switch(matched) {
- case 1:
- /* an alternative name matched the server hostname */
- infof(data, " subjectAltName: %s matched", connssl->dispname);
- return CURLE_OK;
- case 0:
- /* an alternative name field existed, but didn't match and then
- we MUST fail */
- infof(data, " subjectAltName does not match %s", connssl->dispname);
- return CURLE_PEER_FAILED_VERIFICATION;
- }
-
- /* Process subject. */
- name.header = NULL;
- name.beg = name.end = "";
- q = cert.subject.beg;
- /* we have to look to the last occurrence of a commonName in the
- distinguished one to get the most significant one. */
- while(q < cert.subject.end) {
- q = getASN1Element(&dn, q, cert.subject.end);
- if(!q)
- break;
- for(p = dn.beg; p < dn.end;) {
- p = getASN1Element(&elem, p, dn.end);
- if(!p)
- return CURLE_PEER_FAILED_VERIFICATION;
- /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
- elem.beg = checkOID(elem.beg, elem.end, cnOID);
- if(elem.beg)
- name = elem; /* Latch CN. */
- }
- }
-
- /* Check the CN if found. */
- if(!getASN1Element(&elem, name.beg, name.end))
- failf(data, "SSL: unable to obtain common name from peer certificate");
- else {
- len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
- if(len < 0) {
- free(dnsname);
- return CURLE_OUT_OF_MEMORY;
- }
- if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */
- failf(data, "SSL: illegal cert name field");
- else if(Curl_cert_hostcheck((const char *) dnsname,
- len, connssl->hostname, hostlen)) {
- infof(data, " common name: %s (matched)", dnsname);
- free(dnsname);
- return CURLE_OK;
+ /* Build the certificate string. */
+ result = Curl_dyn_add(&out, "-----BEGIN CERTIFICATE-----\n");
+ if(!result) {
+ size_t j = 0;
+
+ while(!result && (j < clen)) {
+ size_t chunksize = (clen - j) > 64 ? 64 : (clen - j);
+ result = Curl_dyn_addn(&out, &certptr[j], chunksize);
+ if(!result)
+ result = Curl_dyn_addn(&out, "\n", 1);
+ j += chunksize;
}
- else
- failf(data, "SSL: certificate subject name '%s' does not match "
- "target host name '%s'", dnsname, connssl->dispname);
- free(dnsname);
+ if(!result)
+ result = Curl_dyn_add(&out, "-----END CERTIFICATE-----\n");
}
+ free(certptr);
+ if(!result)
+ if(data->set.ssl.certinfo)
+ result = ssl_push_certinfo_dyn(data, certnum, "Cert", &out);
- return CURLE_PEER_FAILED_VERIFICATION;
+done:
+ Curl_dyn_free(&out);
+ return result;
}
-#endif /* WANT_VERIFYHOST */
+#endif /* WANT_EXTRACT_CERTINFO */
+
+#endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */
diff --git a/lib/warnless.c b/lib/warnless.c
index 7e077f8d8..c80937b84 100644
--- a/lib/warnless.c
+++ b/lib/warnless.c
@@ -37,7 +37,7 @@
#include "warnless.h"
-#ifdef WIN32
+#ifdef _WIN32
#undef read
#undef write
#endif
@@ -367,7 +367,7 @@ curl_socket_t curlx_sitosk(int i)
#endif /* USE_WINSOCK */
-#if defined(WIN32)
+#if defined(_WIN32)
ssize_t curlx_read(int fd, void *buf, size_t count)
{
@@ -379,8 +379,8 @@ ssize_t curlx_write(int fd, const void *buf, size_t count)
return (ssize_t)write(fd, buf, curlx_uztoui(count));
}
-/* Ensure that warnless.h continues to have an effect in "unity" builds. */
-#undef HEADER_CURL_WARNLESS_H
-
-#endif /* WIN32 */
+#endif /* _WIN32 */
+/* Ensure that warnless.h redefinitions continue to have an effect
+ in "unity" builds. */
+#undef HEADER_CURL_WARNLESS_H_REDEFS
diff --git a/lib/warnless.h b/lib/warnless.h
index 2a5301628..e5a02c8d9 100644
--- a/lib/warnless.h
+++ b/lib/warnless.h
@@ -69,18 +69,13 @@ curl_socket_t curlx_sitosk(int i);
#endif /* USE_WINSOCK */
-#if defined(WIN32)
+#if defined(_WIN32)
ssize_t curlx_read(int fd, void *buf, size_t count);
ssize_t curlx_write(int fd, const void *buf, size_t count);
-#undef read
-#define read(fd, buf, count) curlx_read(fd, buf, count)
-#undef write
-#define write(fd, buf, count) curlx_write(fd, buf, count)
-
-#endif /* WIN32 */
+#endif /* _WIN32 */
#if defined(__INTEL_COMPILER) && defined(__unix__)
@@ -97,3 +92,15 @@ unsigned short curlx_ntohs(unsigned short usnum);
#endif /* __INTEL_COMPILER && __unix__ */
#endif /* HEADER_CURL_WARNLESS_H */
+
+#ifndef HEADER_CURL_WARNLESS_H_REDEFS
+#define HEADER_CURL_WARNLESS_H_REDEFS
+
+#if defined(_WIN32)
+#undef read
+#define read(fd, buf, count) curlx_read(fd, buf, count)
+#undef write
+#define write(fd, buf, count) curlx_write(fd, buf, count)
+#endif
+
+#endif /* HEADER_CURL_WARNLESS_H_REDEFS */
diff --git a/lib/ws.c b/lib/ws.c
index 3c1964b86..d9765182d 100644
--- a/lib/ws.c
+++ b/lib/ws.c
@@ -24,7 +24,7 @@
#include "curl_setup.h"
#include <curl/curl.h>
-#ifdef USE_WEBSOCKETS
+#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#include "urldata.h"
#include "bufq.h"
@@ -225,6 +225,10 @@ static CURLcode ws_dec_read_head(struct ws_decoder *dec,
dec->payload_len = (dec->head[2] << 8) | dec->head[3];
break;
case 10:
+ if(dec->head[2] > 127) {
+ failf(data, "WS: frame length longer than 64 signed not supported");
+ return CURLE_RECV_ERROR;
+ }
dec->payload_len = ((curl_off_t)dec->head[2] << 56) |
(curl_off_t)dec->head[3] << 48 |
(curl_off_t)dec->head[4] << 40 |
@@ -274,8 +278,8 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec,
dec->payload_offset += (curl_off_t)nwritten;
remain = dec->payload_len - dec->payload_offset;
/* infof(data, "WS-DEC: passed %zd bytes payload, %"
- CURL_FORMAT_CURL_OFF_T " remain",
- nwritten, remain); */
+ CURL_FORMAT_CURL_OFF_T " remain",
+ nwritten, remain); */
}
return remain? CURLE_AGAIN : CURLE_OK;
@@ -296,7 +300,7 @@ static CURLcode ws_dec_pass(struct ws_decoder *dec,
case WS_DEC_INIT:
ws_dec_reset(dec);
dec->state = WS_DEC_HEAD;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case WS_DEC_HEAD:
result = ws_dec_read_head(dec, data, inraw);
if(result) {
@@ -321,7 +325,7 @@ static CURLcode ws_dec_pass(struct ws_decoder *dec,
dec->state = WS_DEC_INIT;
break;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case WS_DEC_PAYLOAD:
result = ws_dec_pass_payload(dec, data, inraw, write_payload, write_ctx);
ws_dec_info(dec, data, "passing");
@@ -350,6 +354,136 @@ static void update_meta(struct websocket *ws,
ws->frame.bytesleft = (payload_len - payload_offset - cur_len);
}
+/* WebSockets decoding client writer */
+struct ws_cw_ctx {
+ struct Curl_cwriter super;
+ struct bufq buf;
+};
+
+static CURLcode ws_cw_init(struct Curl_easy *data,
+ struct Curl_cwriter *writer)
+{
+ struct ws_cw_ctx *ctx = (struct ws_cw_ctx *)writer;
+ (void)data;
+ Curl_bufq_init2(&ctx->buf, WS_CHUNK_SIZE, 1, BUFQ_OPT_SOFT_LIMIT);
+ return CURLE_OK;
+}
+
+static void ws_cw_close(struct Curl_easy *data, struct Curl_cwriter *writer)
+{
+ struct ws_cw_ctx *ctx = (struct ws_cw_ctx *)writer;
+ (void) data;
+ Curl_bufq_free(&ctx->buf);
+}
+
+struct ws_cw_dec_ctx {
+ struct Curl_easy *data;
+ struct websocket *ws;
+ struct Curl_cwriter *next_writer;
+ int cw_type;
+};
+
+static ssize_t ws_cw_dec_next(const unsigned char *buf, size_t buflen,
+ int frame_age, int frame_flags,
+ curl_off_t payload_offset,
+ curl_off_t payload_len,
+ void *user_data,
+ CURLcode *err)
+{
+ struct ws_cw_dec_ctx *ctx = user_data;
+ struct Curl_easy *data = ctx->data;
+ struct websocket *ws = ctx->ws;
+ curl_off_t remain = (payload_len - (payload_offset + buflen));
+
+ (void)frame_age;
+ if((frame_flags & CURLWS_PING) && !remain) {
+ /* auto-respond to PINGs, only works for single-frame payloads atm */
+ size_t bytes;
+ infof(data, "WS: auto-respond to PING with a PONG");
+ /* send back the exact same content as a PONG */
+ *err = curl_ws_send(data, buf, buflen, &bytes, 0, CURLWS_PONG);
+ if(*err)
+ return -1;
+ }
+ else if(buflen || !remain) {
+ /* forward the decoded frame to the next client writer. */
+ update_meta(ws, frame_age, frame_flags, payload_offset,
+ payload_len, buflen);
+
+ *err = Curl_cwriter_write(data, ctx->next_writer, ctx->cw_type,
+ (const char *)buf, buflen);
+ if(*err)
+ return -1;
+ }
+ *err = CURLE_OK;
+ return (ssize_t)buflen;
+}
+
+static CURLcode ws_cw_write(struct Curl_easy *data,
+ struct Curl_cwriter *writer, int type,
+ const char *buf, size_t nbytes)
+{
+ struct ws_cw_ctx *ctx = (struct ws_cw_ctx *)writer;
+ struct websocket *ws;
+ CURLcode result;
+
+ if(!(type & CLIENTWRITE_BODY) || data->set.ws_raw_mode)
+ return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
+
+ ws = data->conn->proto.ws;
+ if(!ws) {
+ failf(data, "WS: not a websocket transfer");
+ return CURLE_FAILED_INIT;
+ }
+
+ if(nbytes) {
+ ssize_t nwritten;
+ nwritten = Curl_bufq_write(&ctx->buf, (const unsigned char *)buf,
+ nbytes, &result);
+ if(nwritten < 0) {
+ infof(data, "WS: error adding data to buffer %d", result);
+ return result;
+ }
+ }
+
+ while(!Curl_bufq_is_empty(&ctx->buf)) {
+ struct ws_cw_dec_ctx pass_ctx;
+ pass_ctx.data = data;
+ pass_ctx.ws = ws;
+ pass_ctx.next_writer = writer->next;
+ pass_ctx.cw_type = type;
+ result = ws_dec_pass(&ws->dec, data, &ctx->buf,
+ ws_cw_dec_next, &pass_ctx);
+ if(result == CURLE_AGAIN)
+ /* insufficient amount of data, keep it for later.
+ * we pretend to have written all since we have a copy */
+ return CURLE_OK;
+ else if(result) {
+ infof(data, "WS: decode error %d", (int)result);
+ return result;
+ }
+ }
+
+ if((type & CLIENTWRITE_EOS) && !Curl_bufq_is_empty(&ctx->buf)) {
+ infof(data, "WS: decode ending with %zd frame bytes remaining",
+ Curl_bufq_len(&ctx->buf));
+ return CURLE_RECV_ERROR;
+ }
+
+ return CURLE_OK;
+}
+
+/* WebSocket payload decoding client writer. */
+static const struct Curl_cwtype ws_cw_decode = {
+ "ws-decode",
+ NULL,
+ ws_cw_init,
+ ws_cw_write,
+ ws_cw_close,
+ sizeof(struct ws_cw_ctx)
+};
+
+
static void ws_enc_info(struct ws_encoder *enc, struct Curl_easy *data,
const char *msg)
{
@@ -410,6 +544,13 @@ static ssize_t ws_enc_write_head(struct Curl_easy *data,
size_t hlen;
ssize_t n;
+ if(payload_len < 0) {
+ failf(data, "WS: starting new frame with negative payload length %"
+ CURL_FORMAT_CURL_OFF_T, payload_len);
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+
if(enc->payload_remain > 0) {
/* trying to write a new frame before the previous one is finished */
failf(data, "WS: starting new frame with %zd bytes from last one"
@@ -607,6 +748,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
{
struct SingleRequest *k = &data->req;
struct websocket *ws;
+ struct Curl_cwriter *ws_dec_writer;
CURLcode result;
DEBUGASSERT(data->conn);
@@ -616,7 +758,8 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
if(!ws)
return CURLE_OUT_OF_MEMORY;
data->conn->proto.ws = ws;
- Curl_bufq_init(&ws->recvbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT);
+ Curl_bufq_init2(&ws->recvbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT,
+ BUFQ_OPT_SOFT_LIMIT);
Curl_bufq_init2(&ws->sendbuf, WS_CHUNK_SIZE, WS_CHUNK_COUNT,
BUFQ_OPT_SOFT_LIMIT);
ws_dec_init(&ws->dec);
@@ -655,6 +798,18 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
infof(data, "Received 101, switch to WebSocket; mask %02x%02x%02x%02x",
ws->enc.mask[0], ws->enc.mask[1], ws->enc.mask[2], ws->enc.mask[3]);
+ /* Install our client writer that decodes WS frames payload */
+ result = Curl_cwriter_create(&ws_dec_writer, data, &ws_cw_decode,
+ CURL_CW_CONTENT_DECODE);
+ if(result)
+ return result;
+
+ result = Curl_cwriter_add(data, ws_dec_writer);
+ if(result) {
+ Curl_cwriter_free(data, ws_dec_writer);
+ return result;
+ }
+
if(data->set.connect_only) {
ssize_t nwritten;
/* In CONNECT_ONLY setup, the payloads from `mem` need to be received
@@ -666,105 +821,15 @@ CURLcode Curl_ws_accept(struct Curl_easy *data,
return result;
infof(data, "%zu bytes websocket payload", nread);
}
- k->upgr101 = UPGR101_RECEIVED;
-
- return result;
-}
-
-static ssize_t ws_client_write(const unsigned char *buf, size_t buflen,
- int frame_age, int frame_flags,
- curl_off_t payload_offset,
- curl_off_t payload_len,
- void *userp,
- CURLcode *err)
-{
- struct Curl_easy *data = userp;
- struct websocket *ws;
- size_t wrote;
- curl_off_t remain = (payload_len - (payload_offset + buflen));
-
- (void)frame_age;
- if(!data->conn || !data->conn->proto.ws) {
- *err = CURLE_FAILED_INIT;
- return -1;
- }
- ws = data->conn->proto.ws;
-
- if((frame_flags & CURLWS_PING) && !remain) {
- /* auto-respond to PINGs, only works for single-frame payloads atm */
- size_t bytes;
- infof(data, "WS: auto-respond to PING with a PONG");
- /* send back the exact same content as a PONG */
- *err = curl_ws_send(data, buf, buflen, &bytes, 0, CURLWS_PONG);
- if(*err)
- return -1;
- }
- else if(buflen || !remain) {
- /* deliver the decoded frame to the user callback. The application
- * may invoke curl_ws_meta() to access frame information. */
- update_meta(ws, frame_age, frame_flags, payload_offset,
- payload_len, buflen);
- Curl_set_in_callback(data, true);
- wrote = data->set.fwrite_func((char *)buf, 1,
- buflen, data->set.out);
- Curl_set_in_callback(data, false);
- if(wrote != buflen) {
- *err = CURLE_RECV_ERROR;
- return -1;
+ else { /* !connect_only */
+ /* And pass any additional data to the writers */
+ if(nread) {
+ result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)mem, nread);
}
}
- *err = CURLE_OK;
- return (ssize_t)buflen;
-}
-
-/* Curl_ws_writecb() is the write callback for websocket traffic. The
- websocket data is provided to this raw, in chunks. This function should
- handle/decode the data and call the "real" underlying callback accordingly.
-*/
-size_t Curl_ws_writecb(char *buffer, size_t size /* 1 */,
- size_t nitems, void *userp)
-{
- struct Curl_easy *data = userp;
-
- if(data->set.ws_raw_mode)
- return data->set.fwrite_func(buffer, size, nitems, data->set.out);
- else if(nitems) {
- struct websocket *ws;
- CURLcode result;
-
- if(!data->conn || !data->conn->proto.ws) {
- failf(data, "WS: not a websocket transfer");
- return nitems - 1;
- }
- ws = data->conn->proto.ws;
-
- if(buffer) {
- ssize_t nwritten;
-
- nwritten = Curl_bufq_write(&ws->recvbuf, (const unsigned char *)buffer,
- nitems, &result);
- if(nwritten < 0) {
- infof(data, "WS: error adding data to buffer %d", (int)result);
- return nitems - 1;
- }
- buffer = NULL;
- }
-
- while(!Curl_bufq_is_empty(&ws->recvbuf)) {
+ k->upgr101 = UPGR101_RECEIVED;
- result = ws_dec_pass(&ws->dec, data, &ws->recvbuf,
- ws_client_write, data);
- if(result == CURLE_AGAIN)
- /* insufficient amount of data, keep it for later.
- * we pretend to have written all since we have a copy */
- return nitems;
- else if(result) {
- infof(data, "WS: decode error %d", (int)result);
- return nitems - 1;
- }
- }
- }
- return nitems;
+ return result;
}
struct ws_collect {
@@ -925,8 +990,8 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
*metap = &ws->frame;
*nread = ws->frame.len;
/* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %"
- CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
- buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
+ CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
+ buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
return CURLE_OK;
}
@@ -997,8 +1062,11 @@ CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
ws = data->conn->proto.ws;
if(data->set.ws_raw_mode) {
- if(fragsize || flags)
+ if(fragsize || flags) {
+ DEBUGF(infof(data, "ws_send: "
+ "fragsize and flags cannot be non-zero in raw mode"));
return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
if(!buflen)
/* nothing to do */
return CURLE_OK;
@@ -1071,14 +1139,23 @@ static void ws_free(struct connectdata *conn)
}
}
+static CURLcode ws_setup_conn(struct Curl_easy *data,
+ struct connectdata *conn)
+{
+ /* websockets is 1.1 only (for now) */
+ data->state.httpwant = CURL_HTTP_VERSION_1_1;
+ return Curl_http_setup_conn(data, conn);
+}
+
+
void Curl_ws_done(struct Curl_easy *data)
{
(void)data;
}
-CURLcode Curl_ws_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection)
+static CURLcode ws_disconnect(struct Curl_easy *data,
+ struct connectdata *conn,
+ bool dead_connection)
{
(void)data;
(void)dead_connection;
@@ -1096,6 +1173,57 @@ CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
return NULL;
}
+const struct Curl_handler Curl_handler_ws = {
+ "WS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ ZERO_NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ ZERO_NULL, /* proto_getsock */
+ Curl_http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ws_disconnect, /* disconnect */
+ Curl_http_write_resp, /* write_resp */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTP, /* defport */
+ CURLPROTO_WS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_CREDSPERREQUEST | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+
+#ifdef USE_SSL
+const struct Curl_handler Curl_handler_wss = {
+ "WSS", /* scheme */
+ ws_setup_conn, /* setup_connection */
+ Curl_http, /* do_it */
+ Curl_http_done, /* done */
+ ZERO_NULL, /* do_more */
+ Curl_http_connect, /* connect_it */
+ NULL, /* connecting */
+ ZERO_NULL, /* doing */
+ NULL, /* proto_getsock */
+ Curl_http_getsock_do, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
+ ZERO_NULL, /* perform_getsock */
+ ws_disconnect, /* disconnect */
+ Curl_http_write_resp, /* write_resp */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ PORT_HTTPS, /* defport */
+ CURLPROTO_WSS, /* protocol */
+ CURLPROTO_HTTP, /* family */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */
+ PROTOPT_USERPWDCTRL
+};
+#endif
+
+
#else
CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
diff --git a/lib/ws.h b/lib/ws.h
index 0308a4254..5f40d4528 100644
--- a/lib/ws.h
+++ b/lib/ws.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
-#ifdef USE_WEBSOCKETS
+#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#ifdef USE_HYPER
#define REQTYPE void
@@ -75,11 +75,14 @@ struct websocket {
CURLcode Curl_ws_request(struct Curl_easy *data, REQTYPE *req);
CURLcode Curl_ws_accept(struct Curl_easy *data, const char *mem, size_t len);
-size_t Curl_ws_writecb(char *buffer, size_t size, size_t nitems, void *userp);
void Curl_ws_done(struct Curl_easy *data);
-CURLcode Curl_ws_disconnect(struct Curl_easy *data,
- struct connectdata *conn,
- bool dead_connection);
+
+extern const struct Curl_handler Curl_handler_ws;
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_wss;
+#endif
+
+
#else
#define Curl_ws_request(x,y) CURLE_OK
#define Curl_ws_done(x) Curl_nop_stmt
diff --git a/ltmain.sh b/ltmain.sh
index 9b12fbb7f..4266fda22 100755
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -31,7 +31,7 @@
PROGRAM=libtool
PACKAGE=libtool
-VERSION="2.4.7 Debian-2.4.7-5"
+VERSION="2.4.7 Debian-2.4.7-7+build1"
package_revision=2.4.7
@@ -572,27 +572,15 @@ func_require_term_colors ()
# ---------------------
# Append VALUE onto the existing contents of VAR.
- # We should try to minimise forks, especially on Windows where they are
- # unreasonably slow, so skip the feature probes when bash or zsh are
- # being used:
- if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then
- : ${_G_HAVE_ARITH_OP="yes"}
- : ${_G_HAVE_XSI_OPS="yes"}
- # The += operator was introduced in bash 3.1
- case $BASH_VERSION in
- [12].* | 3.0 | 3.0*) ;;
- *)
- : ${_G_HAVE_PLUSEQ_OP="yes"}
- ;;
- esac
- fi
-
# _G_HAVE_PLUSEQ_OP
# Can be empty, in which case the shell is probed, "yes" if += is
# useable or anything else if it does not work.
- test -z "$_G_HAVE_PLUSEQ_OP" \
- && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
- && _G_HAVE_PLUSEQ_OP=yes
+ if test -z "$_G_HAVE_PLUSEQ_OP" && \
+ __PLUSEQ_TEST="a" && \
+ __PLUSEQ_TEST+=" b" 2>/dev/null && \
+ test "a b" = "$__PLUSEQ_TEST"; then
+ _G_HAVE_PLUSEQ_OP=yes
+ fi
if test yes = "$_G_HAVE_PLUSEQ_OP"
then
@@ -2308,7 +2296,7 @@ include the following information:
compiler: $LTCC
compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld)
- version: $progname $scriptversion Debian-2.4.7-5
+ version: $progname $scriptversion Debian-2.4.7-7+build1
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
diff --git a/m4/curl-amissl.m4 b/m4/curl-amissl.m4
index 95208f0c2..48067e720 100644
--- a/m4/curl-amissl.m4
+++ b/m4/curl-amissl.m4
@@ -33,7 +33,7 @@ if test "$HAVE_PROTO_BSDSOCKET_H" = "1"; then
#include <openssl/opensslv.h>
]],[[
#if defined(AMISSL_CURRENT_VERSION) && defined(AMISSL_V3xx) && \
- defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
+ (OPENSSL_VERSION_NUMBER >= 0x30000000L) && \
defined(PROTO_AMISSL_H)
return 0;
#else
diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4
index caa2b14cb..9a4547709 100644
--- a/m4/curl-compilers.m4
+++ b/m4/curl-compilers.m4
@@ -48,7 +48,6 @@ AC_DEFUN([CURL_CHECK_COMPILER], [
CURL_CHECK_COMPILER_INTEL_C
CURL_CHECK_COMPILER_CLANG
CURL_CHECK_COMPILER_GNU_C
- CURL_CHECK_COMPILER_LCC
CURL_CHECK_COMPILER_SGI_MIPSPRO_C
CURL_CHECK_COMPILER_SGI_MIPS_C
CURL_CHECK_COMPILER_SUNPRO_C
@@ -92,19 +91,40 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [
AC_MSG_RESULT([no])
compiler_id="CLANG"
fi
+ AC_MSG_CHECKING([compiler version])
fullclangver=`$CC -v 2>&1 | grep version`
+ if echo $fullclangver | grep 'Apple' >/dev/null; then
+ appleclang=1
+ else
+ appleclang=0
+ fi
clangver=`echo $fullclangver | grep "based on LLVM " | "$SED" 's/.*(based on LLVM \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*)/\1/'`
if test -z "$clangver"; then
- if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then
- dnl Starting with XCode 7 / clang 3.7, Apple clang won't tell its upstream version
- clangver="3.7"
- else
- clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'`
- fi
+ clangver=`echo $fullclangver | "$SED" 's/.*version \(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'`
+ oldapple=0
+ else
+ oldapple=1
fi
clangvhi=`echo $clangver | cut -d . -f1`
clangvlo=`echo $clangver | cut -d . -f2`
compiler_num=`(expr $clangvhi "*" 100 + $clangvlo) 2>/dev/null`
+ if test "$appleclang" = '1' && test "$oldapple" = '0'; then
+ dnl Starting with Xcode 7 / clang 3.7, Apple clang won't tell its upstream version
+ if test "$compiler_num" -ge '1300'; then compiler_num='1200'
+ elif test "$compiler_num" -ge '1205'; then compiler_num='1101'
+ elif test "$compiler_num" -ge '1204'; then compiler_num='1000'
+ elif test "$compiler_num" -ge '1107'; then compiler_num='900'
+ elif test "$compiler_num" -ge '1103'; then compiler_num='800'
+ elif test "$compiler_num" -ge '1003'; then compiler_num='700'
+ elif test "$compiler_num" -ge '1001'; then compiler_num='600'
+ elif test "$compiler_num" -ge '904'; then compiler_num='500'
+ elif test "$compiler_num" -ge '902'; then compiler_num='400'
+ elif test "$compiler_num" -ge '803'; then compiler_num='309'
+ elif test "$compiler_num" -ge '703'; then compiler_num='308'
+ else compiler_num='307'
+ fi
+ fi
+ AC_MSG_RESULT([clang '$compiler_num' (raw: '$fullclangver' / '$clangver')])
flags_dbg_yes="-g"
flags_opt_all="-O -O0 -O1 -O2 -Os -O3 -O4"
flags_opt_yes="-O2"
@@ -159,15 +179,21 @@ AC_DEFUN([CURL_CHECK_COMPILER_GNU_C], [
test "$compiler_id" = "unknown"; then
AC_MSG_RESULT([yes])
compiler_id="GNU_C"
- gccver=`$CC -dumpversion`
+ AC_MSG_CHECKING([compiler version])
+ # strip '-suffix' parts, e.g. Ubuntu Windows cross-gcc returns '10-win32'
+ gccver=`$CC -dumpversion | sed -E 's/-.+$//'`
gccvhi=`echo $gccver | cut -d . -f1`
- gccvlo=`echo $gccver | cut -d . -f2`
+ if echo $gccver | grep -F '.' >/dev/null; then
+ gccvlo=`echo $gccver | cut -d . -f2`
+ else
+ gccvlo="0"
+ fi
compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null`
+ AC_MSG_RESULT([gcc '$compiler_num' (raw: '$gccver')])
flags_dbg_yes="-g"
flags_opt_all="-O -O0 -O1 -O2 -O3 -Os -Og -Ofast"
flags_opt_yes="-O2"
flags_opt_off="-O0"
- CURL_CHECK_DEF([_WIN32], [], [silent])
else
AC_MSG_RESULT([no])
fi
@@ -232,7 +258,9 @@ AC_DEFUN([CURL_CHECK_COMPILER_INTEL_C], [
CURL_CHECK_DEF([__INTEL_COMPILER], [], [silent])
if test "$curl_cv_have_def___INTEL_COMPILER" = "yes"; then
AC_MSG_RESULT([yes])
+ AC_MSG_CHECKING([compiler version])
compiler_num="$curl_cv_def___INTEL_COMPILER"
+ AC_MSG_RESULT([Intel C '$compiler_num'])
CURL_CHECK_DEF([__unix__], [], [silent])
if test "$curl_cv_have_def___unix__" = "yes"; then
compiler_id="INTEL_UNIX_C"
@@ -253,26 +281,6 @@ AC_DEFUN([CURL_CHECK_COMPILER_INTEL_C], [
])
-dnl CURL_CHECK_COMPILER_LCC
-dnl -------------------------------------------------
-dnl Verify if compiler being used is LCC.
-
-AC_DEFUN([CURL_CHECK_COMPILER_LCC], [
- AC_MSG_CHECKING([if compiler is LCC])
- CURL_CHECK_DEF([__LCC__], [], [silent])
- if test "$curl_cv_have_def___LCC__" = "yes"; then
- AC_MSG_RESULT([yes])
- compiler_id="LCC"
- flags_dbg_yes="-g"
- flags_opt_all=""
- flags_opt_yes=""
- flags_opt_off=""
- else
- AC_MSG_RESULT([no])
- fi
-])
-
-
dnl CURL_CHECK_COMPILER_SGI_MIPS_C
dnl -------------------------------------------------
dnl Verify if compiler being used is SGI MIPS C.
@@ -580,12 +588,6 @@ AC_DEFUN([CURL_SET_COMPILER_BASIC_OPTS], [
tmp_CFLAGS="$tmp_CFLAGS"
;;
#
- LCC)
- #
- dnl Disallow run-time dereferencing of null pointers
- tmp_CFLAGS="$tmp_CFLAGS -n"
- ;;
- #
SGI_MIPS_C)
#
dnl Placeholder
@@ -787,7 +789,8 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-prototypes])
tmp_CFLAGS="$tmp_CFLAGS -Wno-long-long"
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [float-equal])
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [no-multichar sign-compare])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-compare])
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-multichar"
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [undef])
tmp_CFLAGS="$tmp_CFLAGS -Wno-format-nonliteral"
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [endif-labels strict-prototypes])
@@ -801,29 +804,48 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused])
fi
#
+ dnl Only clang 2.7 or later
+ if test "$compiler_num" -ge "207"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [address])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [attributes])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [bad-function-cast])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [div-by-zero format-security])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [empty-body])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-field-initializers])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-noreturn])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [old-style-definition])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [redundant-decls])
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits])
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) # Not practical
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code unused-parameter])
+ fi
+ #
dnl Only clang 2.8 or later
if test "$compiler_num" -ge "208"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [ignored-qualifiers])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [vla])
fi
#
dnl Only clang 2.9 or later
if test "$compiler_num" -ge "209"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-conversion])
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shift-sign-overflow])
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs
fi
#
- dnl Only clang 3.0 or later (possibly earlier)
+ dnl Only clang 3.0 or later
if test "$compiler_num" -ge "300"; then
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [bad-function-cast])
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion])
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [empty-body])
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [ignored-qualifiers])
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits])
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [no-sign-conversion])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [language-extension-token])
+ tmp_CFLAGS="$tmp_CFLAGS -Wformat=2"
fi
#
dnl Only clang 3.2 or later
if test "$compiler_num" -ge "302"; then
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [enum-conversion])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sometimes-uninitialized])
case $host_os in
cygwin* | mingw*)
dnl skip missing-variable-declarations warnings for cygwin and
@@ -837,9 +859,16 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
#
dnl Only clang 3.4 or later
if test "$compiler_num" -ge "304"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [header-guard])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-const-variable])
fi
#
+ dnl Only clang 3.5 or later
+ if test "$compiler_num" -ge "305"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pragmas])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code-break])
+ fi
+ #
dnl Only clang 3.6 or later
if test "$compiler_num" -ge "306"; then
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [double-promotion])
@@ -859,6 +888,10 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [assign-enum])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [extra-semi-stmt])
fi
+ dnl clang 10 or later
+ if test "$compiler_num" -ge "1000"; then
+ tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough" # we have silencing markup for clang 10.0 and above only
+ fi
fi
dnl Disable pointer to bool conversion warnings since they cause
dnl lib/securetransp.c cause several warnings for checks we want.
@@ -877,7 +910,6 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
GNU_C)
#
if test "$want_warnings" = "yes"; then
- tmp_CFLAGS="$tmp_CFLAGS -std=gnu89"
#
dnl Do not enable -pedantic when cross-compiling with a gcc older
dnl than 3.0, to avoid warnings from third party system headers.
@@ -958,6 +990,26 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
tmp_CFLAGS="$tmp_CFLAGS -Wstrict-aliasing=3"
fi
#
+ dnl Only gcc 4.1 or later
+ if test "$compiler_num" -ge "401"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [attributes])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [div-by-zero format-security])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-field-initializers])
+ case $host in
+ *-*-msys*)
+ ;;
+ *)
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-noreturn]) # Seen to clash with libtool-generated stub code
+ ;;
+ esac
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unreachable-code unused-parameter])
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [padded]) # Not used because we cannot change public structs
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pragmas])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [redundant-decls])
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [switch-enum]) # Not used because this basically disallows default case
+ # CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused-macros]) # Not practical
+ fi
+ #
dnl Only gcc 4.2 or later
if test "$compiler_num" -ge "402"; then
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [cast-align])
@@ -965,11 +1017,13 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
#
dnl Only gcc 4.3 or later
if test "$compiler_num" -ge "403"; then
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [address])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [type-limits old-style-declaration])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-parameter-type empty-body])
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [clobbered ignored-qualifiers])
- CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion])
- tmp_CFLAGS="$tmp_CFLAGS -Wno-sign-conversion"
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [conversion trampolines])
+ CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [sign-conversion])
+ tmp_CFLAGS="$tmp_CFLAGS -Wno-error=sign-conversion" # FIXME
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [vla])
dnl required for -Warray-bounds, included in -Wall
tmp_CFLAGS="$tmp_CFLAGS -ftree-vrp"
@@ -978,7 +1032,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
dnl Only gcc 4.5 or later
if test "$compiler_num" -ge "405"; then
dnl Only windows targets
- if test "$curl_cv_have_def__WIN32" = "yes"; then
+ if test "$curl_cv_native_windows" = "yes"; then
tmp_CFLAGS="$tmp_CFLAGS -Wno-pedantic-ms-format"
fi
fi
@@ -1015,10 +1069,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [alloc-zero])
tmp_CFLAGS="$tmp_CFLAGS -Wformat-overflow=2"
tmp_CFLAGS="$tmp_CFLAGS -Wformat-truncation=2"
- if test "$compiler_num" -lt "1200"; then
- dnl gcc 12 doesn't acknowledge our comment markups
- tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough=4"
- fi
+ tmp_CFLAGS="$tmp_CFLAGS -Wimplicit-fallthrough"
fi
#
dnl Only gcc 10 or later
@@ -1105,17 +1156,6 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
tmp_CFLAGS="$tmp_CFLAGS"
;;
#
- LCC)
- #
- if test "$want_warnings" = "yes"; then
- dnl Highest warning level is double -A, next is single -A.
- dnl Due to the big number of warnings these trigger on third
- dnl party header files it is impractical for us to use any of
- dnl them here. If you want them simply define it in CPPFLAGS.
- tmp_CFLAGS="$tmp_CFLAGS"
- fi
- ;;
- #
SGI_MIPS_C)
#
if test "$want_warnings" = "yes"; then
diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4
index 7fefa3967..425d9f96f 100644
--- a/m4/curl-functions.m4
+++ b/m4/curl-functions.m4
@@ -46,7 +46,7 @@ curl_includes_arpa_inet="\
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
-#ifdef HAVE_WINSOCK2_H
+#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
@@ -108,35 +108,6 @@ curl_includes_ifaddrs="\
])
-dnl CURL_INCLUDES_INTTYPES
-dnl -------------------------------------------------
-dnl Set up variable with list of headers that must be
-dnl included when inttypes.h is to be included.
-
-AC_DEFUN([CURL_INCLUDES_INTTYPES], [
-curl_includes_inttypes="\
-/* includes start */
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-/* includes end */"
- case $host_os in
- irix*)
- ac_cv_header_stdint_h="no"
- ;;
- esac
- AC_CHECK_HEADERS(
- sys/types.h stdint.h inttypes.h,
- [], [], [$curl_includes_inttypes])
-])
-
-
dnl CURL_INCLUDES_LIBGEN
dnl -------------------------------------------------
dnl Set up variable with list of headers that must be
@@ -443,18 +414,14 @@ dnl included when winsock2.h is to be included.
AC_DEFUN([CURL_INCLUDES_WINSOCK2], [
curl_includes_winsock2="\
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# endif
+# include <winsock2.h>
#endif
/* includes end */"
- CURL_CHECK_HEADER_WINDOWS
- CURL_CHECK_HEADER_WINSOCK2
+ CURL_CHECK_NATIVE_WINDOWS
])
@@ -466,22 +433,15 @@ dnl included when ws2tcpip.h is to be included.
AC_DEFUN([CURL_INCLUDES_WS2TCPIP], [
curl_includes_ws2tcpip="\
/* includes start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
-# include <windows.h>
-# ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-# ifdef HAVE_WS2TCPIP_H
-# include <ws2tcpip.h>
-# endif
-# endif
+# include <winsock2.h>
+# include <ws2tcpip.h>
#endif
/* includes end */"
- CURL_CHECK_HEADER_WINDOWS
- CURL_CHECK_HEADER_WINSOCK2
- CURL_CHECK_HEADER_WS2TCPIP
+ CURL_CHECK_NATIVE_WINDOWS
])
@@ -539,7 +499,7 @@ dnl defines function calling convention.
AC_DEFUN([CURL_PREPROCESS_CALLCONV], [
curl_preprocess_callconv="\
/* preprocess start */
-#ifdef HAVE_WINDOWS_H
+#ifdef _WIN32
# define FUNCALLCONV __stdcall
#else
# define FUNCALLCONV
@@ -1823,10 +1783,10 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [
struct addrinfo *ai = 0;
int error;
- #ifdef HAVE_WINSOCK2_H
+ #ifdef _WIN32
WSADATA wsa;
- if (WSAStartup(MAKEWORD(2,2), &wsa))
- exit(2);
+ if(WSAStartup(MAKEWORD(2, 2), &wsa))
+ exit(2);
#endif
memset(&hints, 0, sizeof(hints));
diff --git a/m4/curl-gnutls.m4 b/m4/curl-gnutls.m4
index 48813dfad..d4f553d69 100644
--- a/m4/curl-gnutls.m4
+++ b/m4/curl-gnutls.m4
@@ -104,6 +104,7 @@ if test "x$OPT_GNUTLS" != xno; then
GNUTLS_ENABLED=1
USE_GNUTLS="yes"
ssl_msg="GnuTLS"
+ QUIC_ENABLED=yes
test gnutls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
diff --git a/m4/curl-openssl.m4 b/m4/curl-openssl.m4
index a4811d2a3..2fb2abecc 100644
--- a/m4/curl-openssl.m4
+++ b/m4/curl-openssl.m4
@@ -271,6 +271,7 @@ if test "x$OPT_OPENSSL" != xno; then
],[
AC_MSG_RESULT([yes])
ssl_msg="BoringSSL"
+ OPENSSL_IS_BORINGSSL=1
],[
AC_MSG_RESULT([no])
])
@@ -287,6 +288,7 @@ if test "x$OPT_OPENSSL" != xno; then
],[
AC_MSG_RESULT([yes])
ssl_msg="AWS-LC"
+ OPENSSL_IS_BORINGSSL=1
],[
AC_MSG_RESULT([no])
])
@@ -312,7 +314,7 @@ if test "x$OPT_OPENSSL" != xno; then
AC_LANG_PROGRAM([[
#include <openssl/opensslv.h>
]],[[
- #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+ #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
return 0;
#else
#error older than 3
@@ -328,6 +330,15 @@ if test "x$OPT_OPENSSL" != xno; then
])
fi
+ dnl is this OpenSSL (fork) providing the original QUIC API?
+ AC_CHECK_FUNCS([SSL_set_quic_use_legacy_codepoint],
+ [QUIC_ENABLED=yes])
+ if test "$QUIC_ENABLED" = "yes"; then
+ AC_MSG_NOTICE([OpenSSL fork speaks QUIC API])
+ else
+ AC_MSG_NOTICE([OpenSSL version does not speak QUIC API])
+ fi
+
if test "$OPENSSL_ENABLED" = "1"; then
if test -n "$LIB_OPENSSL"; then
dnl when the ssl shared libs were found in a path that the run-time
@@ -413,4 +424,23 @@ AS_HELP_STRING([--disable-openssl-auto-load-config],[Disable automatic loading o
])
fi
+dnl ---
+dnl We may use OpenSSL QUIC.
+dnl ---
+if test "$OPENSSL_ENABLED" = "1"; then
+ AC_MSG_CHECKING([for QUIC support in OpenSSL])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[
+#include <openssl/ssl.h>
+ ]],[[
+ OSSL_QUIC_client_method();
+ ]])
+ ],[
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_OPENSSL_QUIC, 1, [if you have the functions OSSL_QUIC_client_method])
+ AC_SUBST(HAVE_OPENSSL_QUIC, [1])
+ ],[
+ AC_MSG_RESULT([no])
+ ])
+fi
])
diff --git a/m4/curl-wolfssl.m4 b/m4/curl-wolfssl.m4
index f630685bc..1da47a91e 100644
--- a/m4/curl-wolfssl.m4
+++ b/m4/curl-wolfssl.m4
@@ -107,6 +107,7 @@ if test "x$OPT_WOLFSSL" != xno; then
WOLFSSL_ENABLED=1
USE_WOLFSSL="yes"
ssl_msg="WolfSSL"
+ QUIC_ENABLED=yes
test wolfssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
],
[
diff --git a/maketgz b/maketgz
index a0fcd878f..4ebda82a9 100755
--- a/maketgz
+++ b/maketgz
@@ -145,13 +145,8 @@ fi
############################################################################
#
-# Modify the man pages to display the version number and date.
-#
-
-echo "update man pages"
-./scripts/updatemanpages.pl $version >/dev/null
-
# make the generated file newer than the man page
+
touch src/tool_hugehelp.c
############################################################################
diff --git a/packages/OS400/.gitattributes b/packages/OS400/.gitattributes
new file mode 100644
index 000000000..e9b8201b5
--- /dev/null
+++ b/packages/OS400/.gitattributes
@@ -0,0 +1,6 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+# OS400 .cmd files are not windows scripts.
+*.cmd text eol=auto
diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c
index 48f1f5fbd..596c1f1e1 100644
--- a/packages/OS400/ccsidcurl.c
+++ b/packages/OS400/ccsidcurl.c
@@ -1282,7 +1282,7 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...)
result = curl_easy_setopt(easy, tag, &blob);
break;
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
case CURLOPT_ERRORBUFFER: /* This is an output buffer. */
result = Curl_vsetopt(easy, tag, arg);
break;
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index d1254ce49..b3a4e9efd 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -667,6 +667,8 @@
d c 98
d CURLE_UNRECOVERABLE_POLL...
d c 99
+ d CURLE_TOO_LARGE...
+ d c 100
*
/if not defined(CURL_NO_OLDIES)
d CURLE_URL_MALFORMAT_USER...
@@ -1655,6 +1657,10 @@
d c 00321
d CURLOPT_QUICK_EXIT...
d c 00322
+ d CURLOPT_HAPROXY_CLIENT_IP...
+ d c 10323
+ d CURLOPT_SERVER_RESPONSE_TIMEOUT_MS...
+ d c 00324
*
/if not defined(CURL_NO_OLDIES)
d CURLOPT_FILE c 10001
@@ -1890,6 +1896,12 @@
d c X'0010003D'
d CURLINFO_CAPATH... CURLINFO_STRING + 62
d c X'0010003E'
+ d CURLINFO_XFER_ID... CURLINFO_OFF_T + 63
+ d c X'0060003F'
+ d CURLINFO_CONN_ID... CURLINFO_OFF_T + 64
+ d c X'00600040'
+ d CURLINFO_QUEUE_TIME_T... CURLINFO_OFF_T + 65
+ d c X'00600041'
*
d CURLINFO_HTTP_CODE... Old ...RESPONSE_CODE
d c X'00200002'
@@ -2251,6 +2263,8 @@
d c 29
d CURLUE_LACKS_IDN...
d c 30
+ d CURLUE_TOO_LARGE...
+ d c 31
*
d CURLUPart s 10i 0 based(######ptr######) Enum
d CURLUPART_URL c 0
@@ -3062,6 +3076,10 @@
d sockfd value like(curl_socket_t)
d sockp * value void *
*
+ d curl_multi_get_handles...
+ d pr * extproc('curl_multi_get_handles') CURL **
+ d multi_handle * value CURLM *
+ *
d curl_url pr * extproc('curl_url') CURLU *
*
d curl_url_cleanup...
diff --git a/packages/vms/config_h.com b/packages/vms/config_h.com
index 6e4e03963..6378802ad 100644
--- a/packages/vms/config_h.com
+++ b/packages/vms/config_h.com
@@ -1386,38 +1386,6 @@ $ write tf "#define ''key2' 1"
$ write tf "#endif"
$ goto cfgh_in_loop1
$ endif
-$!
-$! This is really do we have the newer MIT Kerberos
-$!----------------------------------------------------------------------
-$ if (key2 .eqs. "HAVE_GSSMIT")
-$ then
-$ if f$search(test_mit) .nes. ""
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' 1"
-$ else
-$ write tf "#ifdef ''key2'"
-$ write tf "#undef ''key2'"
-$ endif
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
-$!
-$! Older MIT looks like Heimdal
-$!------------------------------------------------
-$ if (key2 .eqs. "HAVE_HEIMDAL")
-$ then
-$ if f$search(test_mit) .eqs. ""
-$ then
-$ write tf "#ifndef ''key2'"
-$ write tf "#define ''key2' 1"
-$ else
-$ write tf "#ifdef ''key2'"
-$ write tf "#undef ''key2'"
-$ endif
-$ write tf "#endif"
-$ goto cfgh_in_loop1
-$ endif
$ endif
$!
$ endif
diff --git a/projects/Windows/VC14.20/.gitignore b/projects/Windows/VC14.20/.gitignore
new file mode 100644
index 000000000..11504d2c1
--- /dev/null
+++ b/projects/Windows/VC14.20/.gitignore
@@ -0,0 +1,9 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+/*.opendb
+/*.opensdf
+/*.sdf
+/*.vc.db
+/.vs
diff --git a/projects/Windows/VC14.20/curl-all.sln b/projects/Windows/VC14.20/curl-all.sln
new file mode 100644
index 000000000..992310090
--- /dev/null
+++ b/projects/Windows/VC14.20/curl-all.sln
@@ -0,0 +1,298 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 16
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "curl", "src\curl.vcxproj", "{5228E9CE-A216-422F-A5E6-58E95E2DD71D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB} = {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "lib\libcurl.vcxproj", "{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ DLL Debug - DLL OpenSSL|Win32 = DLL Debug - DLL OpenSSL|Win32
+ DLL Debug - DLL OpenSSL|x64 = DLL Debug - DLL OpenSSL|x64
+ DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ DLL Debug - DLL Windows SSPI|Win32 = DLL Debug - DLL Windows SSPI|Win32
+ DLL Debug - DLL Windows SSPI|x64 = DLL Debug - DLL Windows SSPI|x64
+ DLL Debug - DLL wolfSSL|Win32 = DLL Debug - DLL wolfSSL|Win32
+ DLL Debug - DLL wolfSSL|x64 = DLL Debug - DLL wolfSSL|x64
+ DLL Debug|Win32 = DLL Debug|Win32
+ DLL Debug|x64 = DLL Debug|x64
+ DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ DLL Release - DLL OpenSSL - DLL LibSSH2|x64 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ DLL Release - DLL OpenSSL|Win32 = DLL Release - DLL OpenSSL|Win32
+ DLL Release - DLL OpenSSL|x64 = DLL Release - DLL OpenSSL|x64
+ DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ DLL Release - DLL Windows SSPI - DLL WinIDN|x64 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ DLL Release - DLL Windows SSPI|Win32 = DLL Release - DLL Windows SSPI|Win32
+ DLL Release - DLL Windows SSPI|x64 = DLL Release - DLL Windows SSPI|x64
+ DLL Release - DLL wolfSSL|Win32 = DLL Release - DLL wolfSSL|Win32
+ DLL Release - DLL wolfSSL|x64 = DLL Release - DLL wolfSSL|x64
+ DLL Release|Win32 = DLL Release|Win32
+ DLL Release|x64 = DLL Release|x64
+ LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ LIB Debug - DLL OpenSSL|Win32 = LIB Debug - DLL OpenSSL|Win32
+ LIB Debug - DLL OpenSSL|x64 = LIB Debug - DLL OpenSSL|x64
+ LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ LIB Debug - DLL Windows SSPI|Win32 = LIB Debug - DLL Windows SSPI|Win32
+ LIB Debug - DLL Windows SSPI|x64 = LIB Debug - DLL Windows SSPI|x64
+ LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ LIB Debug - LIB OpenSSL|Win32 = LIB Debug - LIB OpenSSL|Win32
+ LIB Debug - LIB OpenSSL|x64 = LIB Debug - LIB OpenSSL|x64
+ LIB Debug - LIB wolfSSL|Win32 = LIB Debug - LIB wolfSSL|Win32
+ LIB Debug - LIB wolfSSL|x64 = LIB Debug - LIB wolfSSL|x64
+ LIB Debug|Win32 = LIB Debug|Win32
+ LIB Debug|x64 = LIB Debug|x64
+ LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ LIB Release - DLL OpenSSL - DLL LibSSH2|x64 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ LIB Release - DLL OpenSSL|Win32 = LIB Release - DLL OpenSSL|Win32
+ LIB Release - DLL OpenSSL|x64 = LIB Release - DLL OpenSSL|x64
+ LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ LIB Release - DLL Windows SSPI - DLL WinIDN|x64 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ LIB Release - DLL Windows SSPI|Win32 = LIB Release - DLL Windows SSPI|Win32
+ LIB Release - DLL Windows SSPI|x64 = LIB Release - DLL Windows SSPI|x64
+ LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ LIB Release - LIB OpenSSL - LIB LibSSH2|x64 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ LIB Release - LIB OpenSSL|Win32 = LIB Release - LIB OpenSSL|Win32
+ LIB Release - LIB OpenSSL|x64 = LIB Release - LIB OpenSSL|x64
+ LIB Release - LIB wolfSSL|Win32 = LIB Release - LIB wolfSSL|Win32
+ LIB Release - LIB wolfSSL|x64 = LIB Release - LIB wolfSSL|x64
+ LIB Release|Win32 = LIB Release|Win32
+ LIB Release|x64 = LIB Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.Build.0 = DLL Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.Build.0 = DLL Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.ActiveCfg = DLL Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.Build.0 = DLL Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.ActiveCfg = DLL Release|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.Build.0 = DLL Release|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.Build.0 = LIB Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.ActiveCfg = LIB Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.Build.0 = LIB Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.ActiveCfg = LIB Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.Build.0 = LIB Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.ActiveCfg = LIB Release|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.Build.0 = LIB Release|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.Build.0 = DLL Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.Build.0 = DLL Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.ActiveCfg = DLL Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.Build.0 = DLL Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.ActiveCfg = DLL Release|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.Build.0 = DLL Release|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.Build.0 = LIB Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.ActiveCfg = LIB Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.Build.0 = LIB Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.ActiveCfg = LIB Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.Build.0 = LIB Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.ActiveCfg = LIB Release|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.Build.0 = LIB Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/projects/Windows/VC14.20/lib/.gitignore b/projects/Windows/VC14.20/lib/.gitignore
new file mode 100644
index 000000000..5baee8342
--- /dev/null
+++ b/projects/Windows/VC14.20/lib/.gitignore
@@ -0,0 +1,10 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+/*.opensdf
+/*.sdf
+/*.user
+/*.vc.db
+/*.vcxproj
+/.vs
diff --git a/projects/Windows/VC14.20/lib/libcurl.sln b/projects/Windows/VC14.20/lib/libcurl.sln
new file mode 100644
index 000000000..e34b5eb5d
--- /dev/null
+++ b/projects/Windows/VC14.20/lib/libcurl.sln
@@ -0,0 +1,181 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 17
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "libcurl.vcxproj", "{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ DLL Debug - DLL OpenSSL|Win32 = DLL Debug - DLL OpenSSL|Win32
+ DLL Debug - DLL OpenSSL|x64 = DLL Debug - DLL OpenSSL|x64
+ DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ DLL Debug - DLL Windows SSPI|Win32 = DLL Debug - DLL Windows SSPI|Win32
+ DLL Debug - DLL Windows SSPI|x64 = DLL Debug - DLL Windows SSPI|x64
+ DLL Debug - DLL wolfSSL|Win32 = DLL Debug - DLL wolfSSL|Win32
+ DLL Debug - DLL wolfSSL|x64 = DLL Debug - DLL wolfSSL|x64
+ DLL Debug|Win32 = DLL Debug|Win32
+ DLL Debug|x64 = DLL Debug|x64
+ DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ DLL Release - DLL OpenSSL - DLL LibSSH2|x64 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ DLL Release - DLL OpenSSL|Win32 = DLL Release - DLL OpenSSL|Win32
+ DLL Release - DLL OpenSSL|x64 = DLL Release - DLL OpenSSL|x64
+ DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ DLL Release - DLL Windows SSPI - DLL WinIDN|x64 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ DLL Release - DLL Windows SSPI|Win32 = DLL Release - DLL Windows SSPI|Win32
+ DLL Release - DLL Windows SSPI|x64 = DLL Release - DLL Windows SSPI|x64
+ DLL Release - DLL wolfSSL|Win32 = DLL Release - DLL wolfSSL|Win32
+ DLL Release - DLL wolfSSL|x64 = DLL Release - DLL wolfSSL|x64
+ DLL Release|Win32 = DLL Release|Win32
+ DLL Release|x64 = DLL Release|x64
+ LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ LIB Debug - DLL OpenSSL|Win32 = LIB Debug - DLL OpenSSL|Win32
+ LIB Debug - DLL OpenSSL|x64 = LIB Debug - DLL OpenSSL|x64
+ LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ LIB Debug - DLL Windows SSPI|Win32 = LIB Debug - DLL Windows SSPI|Win32
+ LIB Debug - DLL Windows SSPI|x64 = LIB Debug - DLL Windows SSPI|x64
+ LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ LIB Debug - LIB OpenSSL|Win32 = LIB Debug - LIB OpenSSL|Win32
+ LIB Debug - LIB OpenSSL|x64 = LIB Debug - LIB OpenSSL|x64
+ LIB Debug - LIB wolfSSL|Win32 = LIB Debug - LIB wolfSSL|Win32
+ LIB Debug - LIB wolfSSL|x64 = LIB Debug - LIB wolfSSL|x64
+ LIB Debug|Win32 = LIB Debug|Win32
+ LIB Debug|x64 = LIB Debug|x64
+ LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ LIB Release - DLL OpenSSL - DLL LibSSH2|x64 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ LIB Release - DLL OpenSSL|Win32 = LIB Release - DLL OpenSSL|Win32
+ LIB Release - DLL OpenSSL|x64 = LIB Release - DLL OpenSSL|x64
+ LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ LIB Release - DLL Windows SSPI - DLL WinIDN|x64 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ LIB Release - DLL Windows SSPI|Win32 = LIB Release - DLL Windows SSPI|Win32
+ LIB Release - DLL Windows SSPI|x64 = LIB Release - DLL Windows SSPI|x64
+ LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ LIB Release - LIB OpenSSL - LIB LibSSH2|x64 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ LIB Release - LIB OpenSSL|Win32 = LIB Release - LIB OpenSSL|Win32
+ LIB Release - LIB OpenSSL|x64 = LIB Release - LIB OpenSSL|x64
+ LIB Release - LIB wolfSSL|Win32 = LIB Release - LIB wolfSSL|Win32
+ LIB Release - LIB wolfSSL|x64 = LIB Release - LIB wolfSSL|x64
+ LIB Release|Win32 = LIB Release|Win32
+ LIB Release|x64 = LIB Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|Win32.Build.0 = DLL Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Debug|x64.Build.0 = DLL Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.ActiveCfg = DLL Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|Win32.Build.0 = DLL Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.ActiveCfg = DLL Release|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.DLL Release|x64.Build.0 = DLL Release|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|Win32.Build.0 = LIB Debug|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.ActiveCfg = LIB Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Debug|x64.Build.0 = LIB Debug|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.ActiveCfg = LIB Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|Win32.Build.0 = LIB Release|Win32
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.ActiveCfg = LIB Release|x64
+ {DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}.LIB Release|x64.Build.0 = LIB Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/projects/Windows/VC14.20/lib/libcurl.tmpl b/projects/Windows/VC14.20/lib/libcurl.tmpl
new file mode 100644
index 000000000..ff88b4220
--- /dev/null
+++ b/projects/Windows/VC14.20/lib/libcurl.tmpl
@@ -0,0 +1,2381 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="DLL Debug - DLL wolfSSL|Win32">
+ <Configuration>DLL Debug - DLL wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL wolfSSL|x64">
+ <Configuration>DLL Debug - DLL wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>DLL Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>DLL Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL|Win32">
+ <Configuration>DLL Debug - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL|x64">
+ <Configuration>DLL Debug - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>DLL Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>DLL Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI|Win32">
+ <Configuration>DLL Debug - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI|x64">
+ <Configuration>DLL Debug - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug|Win32">
+ <Configuration>DLL Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug|x64">
+ <Configuration>DLL Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL wolfSSL|Win32">
+ <Configuration>DLL Release - DLL wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL wolfSSL|x64">
+ <Configuration>DLL Release - DLL wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>DLL Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>DLL Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL|Win32">
+ <Configuration>DLL Release - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL|x64">
+ <Configuration>DLL Release - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>DLL Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>DLL Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI|Win32">
+ <Configuration>DLL Release - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI|x64">
+ <Configuration>DLL Release - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release|Win32">
+ <Configuration>DLL Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release|x64">
+ <Configuration>DLL Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>LIB Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>LIB Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL|Win32">
+ <Configuration>LIB Debug - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL|x64">
+ <Configuration>LIB Debug - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>LIB Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>LIB Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI|Win32">
+ <Configuration>LIB Debug - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI|x64">
+ <Configuration>LIB Debug - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB wolfSSL|Win32">
+ <Configuration>LIB Debug - LIB wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB wolfSSL|x64">
+ <Configuration>LIB Debug - LIB wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32">
+ <Configuration>LIB Debug - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL - LIB LibSSH2|x64">
+ <Configuration>LIB Debug - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL|Win32">
+ <Configuration>LIB Debug - LIB OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL|x64">
+ <Configuration>LIB Debug - LIB OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug|Win32">
+ <Configuration>LIB Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug|x64">
+ <Configuration>LIB Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>LIB Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>LIB Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL|Win32">
+ <Configuration>LIB Release - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL|x64">
+ <Configuration>LIB Release - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>LIB Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>LIB Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI|Win32">
+ <Configuration>LIB Release - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI|x64">
+ <Configuration>LIB Release - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB wolfSSL|Win32">
+ <Configuration>LIB Release - LIB wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB wolfSSL|x64">
+ <Configuration>LIB Release - LIB wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL - LIB LibSSH2|Win32">
+ <Configuration>LIB Release - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL - LIB LibSSH2|x64">
+ <Configuration>LIB Release - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL|Win32">
+ <Configuration>LIB Release - LIB OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL|x64">
+ <Configuration>LIB Release - LIB OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release|Win32">
+ <Configuration>LIB Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release|x64">
+ <Configuration>LIB Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{DA6F56B4-06A4-441D-AD70-AC5A7D51FADB}</ProjectGuid>
+ <RootNamespace>libcurl</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)lib\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">$(OutDir)lib\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">$(OutDir)lib\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">$(OutDir)lib\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">$(ProjectName)d</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\wolfssl\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\wolfssl\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\wolfssl\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WOLFSSL;USE_IPV6;WOLFSSL_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\wolfssl\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\wolfssl;..\..\..\..\..\wolfssl\wolfssl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WOLFSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>4214</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ManifestFile>$(IntDir)$(TargetFileName).intermediate.manifest</ManifestFile>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(OutDir)$(ProjectName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Debug\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;BUILDING_LIBCURL;DEBUGBUILD;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\DLL Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_WINDOWS_SSPI;USE_SCHANNEL;USE_WIN32_IDN;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win32\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;..\..\..\..\..\openssl\include\..\build\Win64\VC14.20\LIB Release\include;..\..\..\..\..\openssl\include;..\..\..\..\..\libssh2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BUILDING_LIBCURL;CURL_STATICLIB;USE_OPENSSL;USE_LIBSSH2;USE_IPV6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Lib>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+CURL_LIB_C_FILES
+CURL_LIB_VAUTH_C_FILES
+CURL_LIB_VQUIC_C_FILES
+CURL_LIB_VSSH_C_FILES
+CURL_LIB_VTLS_C_FILES
+ </ItemGroup>
+ <ItemGroup>
+CURL_LIB_H_FILES
+CURL_LIB_VAUTH_H_FILES
+CURL_LIB_VQUIC_H_FILES
+CURL_LIB_VSSH_H_FILES
+CURL_LIB_VTLS_H_FILES
+ </ItemGroup>
+ <ItemGroup>
+CURL_LIB_RC_FILES
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/projects/Windows/VC14.20/lib/libcurl.vcxproj.filters b/projects/Windows/VC14.20/lib/libcurl.vcxproj.filters
new file mode 100644
index 000000000..4d6341d74
--- /dev/null
+++ b/projects/Windows/VC14.20/lib/libcurl.vcxproj.filters
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/projects/Windows/VC14.20/src/.gitignore b/projects/Windows/VC14.20/src/.gitignore
new file mode 100644
index 000000000..5baee8342
--- /dev/null
+++ b/projects/Windows/VC14.20/src/.gitignore
@@ -0,0 +1,10 @@
+# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# SPDX-License-Identifier: curl
+
+/*.opensdf
+/*.sdf
+/*.user
+/*.vc.db
+/*.vcxproj
+/.vs
diff --git a/projects/Windows/VC14.20/src/curl.sln b/projects/Windows/VC14.20/src/curl.sln
new file mode 100644
index 000000000..5cfa4ce24
--- /dev/null
+++ b/projects/Windows/VC14.20/src/curl.sln
@@ -0,0 +1,181 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 16
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "curl", "curl.vcxproj", "{5228E9CE-A216-422F-A5E6-58E95E2DD71D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ DLL Debug - DLL OpenSSL - DLL LibSSH2|x64 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ DLL Debug - DLL OpenSSL|Win32 = DLL Debug - DLL OpenSSL|Win32
+ DLL Debug - DLL OpenSSL|x64 = DLL Debug - DLL OpenSSL|x64
+ DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ DLL Debug - DLL Windows SSPI - DLL WinIDN|x64 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ DLL Debug - DLL Windows SSPI|Win32 = DLL Debug - DLL Windows SSPI|Win32
+ DLL Debug - DLL Windows SSPI|x64 = DLL Debug - DLL Windows SSPI|x64
+ DLL Debug - DLL wolfSSL|Win32 = DLL Debug - DLL wolfSSL|Win32
+ DLL Debug - DLL wolfSSL|x64 = DLL Debug - DLL wolfSSL|x64
+ DLL Debug|Win32 = DLL Debug|Win32
+ DLL Debug|x64 = DLL Debug|x64
+ DLL Release - DLL OpenSSL - DLL LibSSH2|Win32 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ DLL Release - DLL OpenSSL - DLL LibSSH2|x64 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ DLL Release - DLL OpenSSL|Win32 = DLL Release - DLL OpenSSL|Win32
+ DLL Release - DLL OpenSSL|x64 = DLL Release - DLL OpenSSL|x64
+ DLL Release - DLL Windows SSPI - DLL WinIDN|Win32 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ DLL Release - DLL Windows SSPI - DLL WinIDN|x64 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ DLL Release - DLL Windows SSPI|Win32 = DLL Release - DLL Windows SSPI|Win32
+ DLL Release - DLL Windows SSPI|x64 = DLL Release - DLL Windows SSPI|x64
+ DLL Release - DLL wolfSSL|Win32 = DLL Release - DLL wolfSSL|Win32
+ DLL Release - DLL wolfSSL|x64 = DLL Release - DLL wolfSSL|x64
+ DLL Release|Win32 = DLL Release|Win32
+ DLL Release|x64 = DLL Release|x64
+ LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ LIB Debug - DLL OpenSSL - DLL LibSSH2|x64 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ LIB Debug - DLL OpenSSL|Win32 = LIB Debug - DLL OpenSSL|Win32
+ LIB Debug - DLL OpenSSL|x64 = LIB Debug - DLL OpenSSL|x64
+ LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ LIB Debug - DLL Windows SSPI - DLL WinIDN|x64 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ LIB Debug - DLL Windows SSPI|Win32 = LIB Debug - DLL Windows SSPI|Win32
+ LIB Debug - DLL Windows SSPI|x64 = LIB Debug - DLL Windows SSPI|x64
+ LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ LIB Debug - LIB OpenSSL - LIB LibSSH2|x64 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ LIB Debug - LIB OpenSSL|Win32 = LIB Debug - LIB OpenSSL|Win32
+ LIB Debug - LIB OpenSSL|x64 = LIB Debug - LIB OpenSSL|x64
+ LIB Debug - LIB wolfSSL|Win32 = LIB Debug - LIB wolfSSL|Win32
+ LIB Debug - LIB wolfSSL|x64 = LIB Debug - LIB wolfSSL|x64
+ LIB Debug|Win32 = LIB Debug|Win32
+ LIB Debug|x64 = LIB Debug|x64
+ LIB Release - DLL OpenSSL - DLL LibSSH2|Win32 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ LIB Release - DLL OpenSSL - DLL LibSSH2|x64 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ LIB Release - DLL OpenSSL|Win32 = LIB Release - DLL OpenSSL|Win32
+ LIB Release - DLL OpenSSL|x64 = LIB Release - DLL OpenSSL|x64
+ LIB Release - DLL Windows SSPI - DLL WinIDN|Win32 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ LIB Release - DLL Windows SSPI - DLL WinIDN|x64 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ LIB Release - DLL Windows SSPI|Win32 = LIB Release - DLL Windows SSPI|Win32
+ LIB Release - DLL Windows SSPI|x64 = LIB Release - DLL Windows SSPI|x64
+ LIB Release - LIB OpenSSL - LIB LibSSH2|Win32 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ LIB Release - LIB OpenSSL - LIB LibSSH2|x64 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ LIB Release - LIB OpenSSL|Win32 = LIB Release - LIB OpenSSL|Win32
+ LIB Release - LIB OpenSSL|x64 = LIB Release - LIB OpenSSL|x64
+ LIB Release - LIB wolfSSL|Win32 = LIB Release - LIB wolfSSL|Win32
+ LIB Release - LIB wolfSSL|x64 = LIB Release - LIB wolfSSL|x64
+ LIB Release|Win32 = LIB Release|Win32
+ LIB Release|x64 = LIB Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.ActiveCfg = DLL Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|Win32.Build.0 = DLL Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.ActiveCfg = DLL Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL OpenSSL|x64.Build.0 = DLL Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.ActiveCfg = DLL Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|Win32.Build.0 = DLL Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.ActiveCfg = DLL Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL Windows SSPI|x64.Build.0 = DLL Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.ActiveCfg = DLL Debug - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|Win32.Build.0 = DLL Debug - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.ActiveCfg = DLL Debug - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug - DLL wolfSSL|x64.Build.0 = DLL Debug - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.ActiveCfg = DLL Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|Win32.Build.0 = DLL Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.ActiveCfg = DLL Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Debug|x64.Build.0 = DLL Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = DLL Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.ActiveCfg = DLL Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|Win32.Build.0 = DLL Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.ActiveCfg = DLL Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL OpenSSL|x64.Build.0 = DLL Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = DLL Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.ActiveCfg = DLL Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|Win32.Build.0 = DLL Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.ActiveCfg = DLL Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL Windows SSPI|x64.Build.0 = DLL Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.ActiveCfg = DLL Release - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|Win32.Build.0 = DLL Release - DLL wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.ActiveCfg = DLL Release - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release - DLL wolfSSL|x64.Build.0 = DLL Release - DLL wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.ActiveCfg = DLL Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|Win32.Build.0 = DLL Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.ActiveCfg = DLL Release|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.DLL Release|x64.Build.0 = DLL Release|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Debug - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.ActiveCfg = LIB Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|Win32.Build.0 = LIB Debug - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.ActiveCfg = LIB Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL OpenSSL|x64.Build.0 = LIB Debug - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Debug - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.ActiveCfg = LIB Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|Win32.Build.0 = LIB Debug - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.ActiveCfg = LIB Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - DLL Windows SSPI|x64.Build.0 = LIB Debug - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Debug - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.ActiveCfg = LIB Debug - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|Win32.Build.0 = LIB Debug - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.ActiveCfg = LIB Debug - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB OpenSSL|x64.Build.0 = LIB Debug - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.ActiveCfg = LIB Debug - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|Win32.Build.0 = LIB Debug - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.ActiveCfg = LIB Debug - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug - LIB wolfSSL|x64.Build.0 = LIB Debug - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.ActiveCfg = LIB Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|Win32.Build.0 = LIB Debug|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.ActiveCfg = LIB Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Debug|x64.Build.0 = LIB Debug|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|Win32.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL - DLL LibSSH2|x64.Build.0 = LIB Release - DLL OpenSSL - DLL LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.ActiveCfg = LIB Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|Win32.Build.0 = LIB Release - DLL OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.ActiveCfg = LIB Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL OpenSSL|x64.Build.0 = LIB Release - DLL OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|Win32.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.ActiveCfg = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI - DLL WinIDN|x64.Build.0 = LIB Release - DLL Windows SSPI - DLL WinIDN|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.ActiveCfg = LIB Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|Win32.Build.0 = LIB Release - DLL Windows SSPI|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.ActiveCfg = LIB Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - DLL Windows SSPI|x64.Build.0 = LIB Release - DLL Windows SSPI|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|Win32.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.ActiveCfg = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL - LIB LibSSH2|x64.Build.0 = LIB Release - LIB OpenSSL - LIB LibSSH2|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.ActiveCfg = LIB Release - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|Win32.Build.0 = LIB Release - LIB OpenSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.ActiveCfg = LIB Release - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB OpenSSL|x64.Build.0 = LIB Release - LIB OpenSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.ActiveCfg = LIB Release - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|Win32.Build.0 = LIB Release - LIB wolfSSL|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.ActiveCfg = LIB Release - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release - LIB wolfSSL|x64.Build.0 = LIB Release - LIB wolfSSL|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.ActiveCfg = LIB Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|Win32.Build.0 = LIB Release|Win32
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.ActiveCfg = LIB Release|x64
+ {5228E9CE-A216-422F-A5E6-58E95E2DD71D}.LIB Release|x64.Build.0 = LIB Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/projects/Windows/VC14.20/src/curl.tmpl b/projects/Windows/VC14.20/src/curl.tmpl
new file mode 100644
index 000000000..85c71768b
--- /dev/null
+++ b/projects/Windows/VC14.20/src/curl.tmpl
@@ -0,0 +1,2671 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="DLL Debug - DLL wolfSSL|Win32">
+ <Configuration>DLL Debug - DLL wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL wolfSSL|x64">
+ <Configuration>DLL Debug - DLL wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>DLL Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>DLL Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL|Win32">
+ <Configuration>DLL Debug - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL OpenSSL|x64">
+ <Configuration>DLL Debug - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>DLL Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>DLL Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI|Win32">
+ <Configuration>DLL Debug - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug - DLL Windows SSPI|x64">
+ <Configuration>DLL Debug - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug|Win32">
+ <Configuration>DLL Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Debug|x64">
+ <Configuration>DLL Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL wolfSSL|Win32">
+ <Configuration>DLL Release - DLL wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL wolfSSL|x64">
+ <Configuration>DLL Release - DLL wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>DLL Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>DLL Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL|Win32">
+ <Configuration>DLL Release - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL OpenSSL|x64">
+ <Configuration>DLL Release - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>DLL Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>DLL Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI|Win32">
+ <Configuration>DLL Release - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release - DLL Windows SSPI|x64">
+ <Configuration>DLL Release - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release|Win32">
+ <Configuration>DLL Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="DLL Release|x64">
+ <Configuration>DLL Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>LIB Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>LIB Debug - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL|Win32">
+ <Configuration>LIB Debug - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL OpenSSL|x64">
+ <Configuration>LIB Debug - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>LIB Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>LIB Debug - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI|Win32">
+ <Configuration>LIB Debug - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - DLL Windows SSPI|x64">
+ <Configuration>LIB Debug - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB wolfSSL|Win32">
+ <Configuration>LIB Debug - LIB wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB wolfSSL|x64">
+ <Configuration>LIB Debug - LIB wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32">
+ <Configuration>LIB Debug - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL - LIB LibSSH2|x64">
+ <Configuration>LIB Debug - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL|Win32">
+ <Configuration>LIB Debug - LIB OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug - LIB OpenSSL|x64">
+ <Configuration>LIB Debug - LIB OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug|Win32">
+ <Configuration>LIB Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Debug|x64">
+ <Configuration>LIB Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL - DLL LibSSH2|Win32">
+ <Configuration>LIB Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL - DLL LibSSH2|x64">
+ <Configuration>LIB Release - DLL OpenSSL - DLL LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL|Win32">
+ <Configuration>LIB Release - DLL OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL OpenSSL|x64">
+ <Configuration>LIB Release - DLL OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI - DLL WinIDN|Win32">
+ <Configuration>LIB Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI - DLL WinIDN|x64">
+ <Configuration>LIB Release - DLL Windows SSPI - DLL WinIDN</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI|Win32">
+ <Configuration>LIB Release - DLL Windows SSPI</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - DLL Windows SSPI|x64">
+ <Configuration>LIB Release - DLL Windows SSPI</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB wolfSSL|Win32">
+ <Configuration>LIB Release - LIB wolfSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB wolfSSL|x64">
+ <Configuration>LIB Release - LIB wolfSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL - LIB LibSSH2|Win32">
+ <Configuration>LIB Release - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL - LIB LibSSH2|x64">
+ <Configuration>LIB Release - LIB OpenSSL - LIB LibSSH2</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL|Win32">
+ <Configuration>LIB Release - LIB OpenSSL</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release - LIB OpenSSL|x64">
+ <Configuration>LIB Release - LIB OpenSSL</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release|Win32">
+ <Configuration>LIB Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="LIB Release|x64">
+ <Configuration>LIB Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5228E9CE-A216-422F-A5E6-58E95E2DD71D}</ProjectGuid>
+ <RootNamespace>curl</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">..\..\..\..\build\Win32\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">..\..\..\..\build\Win64\VC14.20\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">$(OutDir)src\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">$(OutDir)src\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">false</LinkIncremental>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">$(ProjectName)d</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL wolfSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win32\VC14.20\LIB Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB wolfSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win64\VC14.20\LIB Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win32\VC14.20\LIB Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB wolfSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;wolfssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\wolfssl\build\Win64\VC14.20\LIB Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL wolfSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Debug - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DLL Release - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Debug;..\..\..\..\..\libssh2\build\Win32\VC14.20\LIB Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - LIB OpenSSL - LIB LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Debug;..\..\..\..\..\libssh2\build\Win64\VC14.20\LIB Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\LIB Release;..\..\..\..\..\libssh2\build\Win32\VC14.20\LIB Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - LIB OpenSSL - LIB LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\LIB Release;..\..\..\..\..\libssh2\build\Win64\VC14.20\LIB Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurld.lib;libcrypto.lib;libssl.lib;libssh2d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Debug;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libcrypto.lib;libssl.lib;libssh2.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win32\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win32\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL OpenSSL - DLL LibSSH2|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>crypt32.lib;ws2_32.lib;wldap32.lib;libcurl.lib;libssh2.lib;libcrypto.lib;libssl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);..\..\..\..\..\openssl\build\Win64\VC14.20\DLL Release;..\..\..\..\..\libssh2\build\Win64\VC14.20\DLL Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Debug - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;DEBUGBUILD;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurld.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|Win32'">
+ <Midl>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win32\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='LIB Release - DLL Windows SSPI - DLL WinIDN|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>$(TargetDir)$(TargetName).tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>..\..\..\..\include;..\..\..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level4</WarningLevel>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ <AdditionalIncludeDirectories>..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wldap32.lib;crypt32.lib;normaliz.lib;libcurl.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\..\build\Win64\VC14.20\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+CURL_SRC_X_C_FILES
+CURL_SRC_C_FILES
+ </ItemGroup>
+ <ItemGroup>
+CURL_SRC_X_H_FILES
+CURL_SRC_H_FILES
+ </ItemGroup>
+ <ItemGroup>
+CURL_SRC_RC_FILES
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/projects/Windows/VC14.20/src/curl.vcxproj.filters b/projects/Windows/VC14.20/src/curl.vcxproj.filters
new file mode 100644
index 000000000..4d6341d74
--- /dev/null
+++ b/projects/Windows/VC14.20/src/curl.vcxproj.filters
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/projects/Windows/VC14.30/src/curl.sln b/projects/Windows/VC14.30/src/curl.sln
index 2af095916..2c16858fd 100644
--- a/projects/Windows/VC14.30/src/curl.sln
+++ b/projects/Windows/VC14.30/src/curl.sln
@@ -1,5 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
+# Visual Studio 17
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "curl", "curl.vcxproj", "{5228E9CE-A216-422F-A5E6-58E95E2DD71D}"
EndProject
Global
diff --git a/projects/generate.bat b/projects/generate.bat
index d57d4ebb9..a110adffc 100644
--- a/projects/generate.bat
+++ b/projects/generate.bat
@@ -56,6 +56,8 @@ rem ***************************************************************************
set VERSION=VC14
) else if /i "%~1" == "vc14.10" (
set VERSION=VC14.10
+ ) else if /i "%~1" == "vc14.20" (
+ set VERSION=VC14.20
) else if /i "%~1" == "vc14.30" (
set VERSION=VC14.30
) else if /i "%~1" == "-clean" (
@@ -88,6 +90,7 @@ rem ***************************************************************************
if "%VERSION%" == "VC12" goto vc12
if "%VERSION%" == "VC14" goto vc14
if "%VERSION%" == "VC14.10" goto vc14.10
+ if "%VERSION%" == "VC14.20" goto vc14.20
if "%VERSION%" == "VC14.30" goto vc14.30
:vc10
@@ -165,6 +168,21 @@ rem ***************************************************************************
if not "%VERSION%" == "ALL" goto success
+:vc14.20
+ echo.
+
+ if "%MODE%" == "GENERATE" (
+ echo Generating VC14.20 project files
+ call :generate vcxproj Windows\VC14.20\src\curl.tmpl Windows\VC14.20\src\curl.vcxproj
+ call :generate vcxproj Windows\VC14.20\lib\libcurl.tmpl Windows\VC14.20\lib\libcurl.vcxproj
+ ) else (
+ echo Removing VC14.20 project files
+ call :clean Windows\VC14.20\src\curl.vcxproj
+ call :clean Windows\VC14.20\lib\libcurl.vcxproj
+ )
+
+ if not "%VERSION%" == "ALL" goto success
+
:vc14.30
echo.
@@ -182,7 +200,7 @@ rem ***************************************************************************
rem Main generate function.
rem
-rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10 and VC14.30)
+rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10, VC14.20 and VC14.30)
rem %2 - Input template file
rem %3 - Output project file
rem
@@ -263,7 +281,7 @@ rem
rem Generates a single file xml element.
rem
-rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10 and VC14.30)
+rem %1 - Project Type (vcxproj for VC10, VC11, VC12, VC14, VC14.10, VC14.20 and VC14.30)
rem %2 - Directory (src, lib, lib\vauth, lib\vquic, lib\vssh, lib\vtls)
rem %3 - Source filename
rem %4 - Output project file
@@ -359,6 +377,7 @@ rem
echo vc12 - Use Visual Studio 2013
echo vc14 - Use Visual Studio 2015
echo vc14.10 - Use Visual Studio 2017
+ echo vc14.20 - Use Visual Studio 2019
echo vc14.30 - Use Visual Studio 2022
echo.
echo -clean - Removes the project files
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index fcb78eabf..ae95e85ac 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -22,8 +22,8 @@
#
###########################################################################
-EXTRA_DIST = updatemanpages.pl coverage.sh completion.pl firefox-db2pem.sh \
- checksrc.pl mk-ca-bundle.pl
+EXTRA_DIST = coverage.sh completion.pl firefox-db2pem.sh checksrc.pl \
+ mk-ca-bundle.pl schemetable.c cd2nroff nroff2cd cdall cd2cd
ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@
FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@
diff --git a/scripts/cd2cd b/scripts/cd2cd
new file mode 100755
index 000000000..a4de2f875
--- /dev/null
+++ b/scripts/cd2cd
@@ -0,0 +1,226 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+=begin comment
+
+This script updates a curldown file to current/better curldown.
+
+Example: cd2cd [--in-place] <file.md> > <file.md>
+
+--in-place: if used, it replaces the original file with the cleaned up
+ version. When this is used, cd2cd accepts multiple files to work
+ on and it ignores errors on single files.
+
+=end comment
+=cut
+
+my $cd2cd = "0.1"; # to keep check
+my $dir;
+my $extension;
+my $inplace = 0;
+
+while(1) {
+ if($ARGV[0] eq "--in-place") {
+ shift @ARGV;
+ $inplace = 1;
+ }
+ else {
+ last;
+ }
+}
+
+
+use POSIX qw(strftime);
+my @ts;
+if (defined($ENV{SOURCE_DATE_EPOCH})) {
+ @ts = localtime($ENV{SOURCE_DATE_EPOCH});
+} else {
+ @ts = localtime;
+}
+my $date = strftime "%B %d %Y", @ts;
+
+sub outseealso {
+ my (@sa) = @_;
+ my $comma = 0;
+ my @o;
+ push @o, ".SH SEE ALSO\n";
+ for my $s (sort @sa) {
+ push @o, sprintf "%s.BR $s", $comma ? ",\n": "";
+ $comma = 1;
+ }
+ push @o, "\n";
+ return @o;
+}
+
+sub single {
+ my @head;
+ my @seealso;
+ my ($f)=@_;
+ my $title;
+ my $section;
+ my $source;
+ my $start = 0;
+ my $d;
+ my $line = 0;
+ open(F, "<:crlf", "$f") ||
+ return 1;
+ while(<F>) {
+ $line++;
+ $d = $_;
+ if(!$start) {
+ if(/^---/) {
+ # header starts here
+ $start = 1;
+ push @head, $d;
+ }
+ next;
+ }
+ if(/^Title: *(.*)/i) {
+ $title=$1;
+ }
+ elsif(/^Section: *(.*)/i) {
+ $section=$1;
+ }
+ elsif(/^Source: *(.*)/i) {
+ $source=$1;
+ }
+ elsif(/^See-also: +(.*)/i) {
+ $salist = 0;
+ push @seealso, $1;
+ }
+ elsif(/^See-also: */i) {
+ if($seealso[0]) {
+ print STDERR "$f:$line:1:ERROR: bad See-Also, needs list\n";
+ return 2;
+ }
+ $salist = 1;
+ }
+ elsif(/^ +- (.*)/i) {
+ # the only list we support is the see-also
+ if($salist) {
+ push @seealso, $1;
+ }
+ }
+ # REUSE-IgnoreStart
+ elsif(/^C: (.*)/i) {
+ $copyright=$1;
+ }
+ elsif(/^SPDX-License-Identifier: (.*)/i) {
+ $spdx=$1;
+ }
+ # REUSE-IgnoreEnd
+ elsif(/^---/) {
+ # end of the header section
+ if(!$title) {
+ print STDERR "ERROR: no 'Title:' in $f\n";
+ return 1;
+ }
+ if(!$section) {
+ print STDERR "ERROR: no 'Section:' in $f\n";
+ return 2;
+ }
+ if(!$seealso[0]) {
+ print STDERR "$f:$line:1:ERROR: no 'See-also:' present\n";
+ return 2;
+ }
+ if(!$copyright) {
+ print STDERR "$f:$line:1:ERROR: no 'C:' field present\n";
+ return 2;
+ }
+ if(!$spdx) {
+ print STDERR "$f:$line:1:ERROR: no 'SPDX-License-Identifier:' field present\n";
+ return 2;
+ }
+ last;
+ }
+ else {
+ chomp;
+ print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
+ }
+ }
+
+ if(!$start) {
+ print STDERR "$f:$line:1:ERROR: no header present\n";
+ return 2;
+ }
+
+ my @desc;
+
+ push @desc, sprintf <<HEAD
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: $title
+Section: $section
+Source: $source
+HEAD
+ ;
+ push @desc, "See-also:\n";
+ for my $s (sort @seealso) {
+ push @desc, " - $s\n" if($s);
+ }
+ push @desc, "---\n";
+
+ my $blankline = 0;
+ while(<F>) {
+ $d = $_;
+ $line++;
+ if($d =~ /^[ \t]*\n/) {
+ $blankline++;
+ }
+ else {
+ $blankline = 0;
+ }
+ # *italics* for curl symbol links get the asterisks removed
+ $d =~ s/\*((lib|)curl[^ ]*\(3\))\*/$1/gi;
+
+ if(length($d) > 90) {
+ print STDERR "$f:$line:1:WARN: excessive line length\n";
+ }
+
+ push @desc, $d if($blankline < 2);
+ }
+ close(F);
+
+ if($inplace) {
+ open(O, ">$f") || return 1;
+ print O @desc;
+ close(O);
+ }
+ else {
+ print @desc;
+ }
+ return 0;
+}
+
+if($inplace) {
+ for my $a (@ARGV) {
+ # this ignores errors
+ single($a);
+ }
+}
+else {
+ exit single($ARGV[0]);
+}
diff --git a/scripts/cd2nroff b/scripts/cd2nroff
new file mode 100755
index 000000000..17a83b49c
--- /dev/null
+++ b/scripts/cd2nroff
@@ -0,0 +1,373 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+=begin comment
+
+Converts a curldown file to nroff (man page).
+
+=end comment
+=cut
+
+use strict;
+use warnings;
+
+my $cd2nroff = "0.1"; # to keep check
+my $dir;
+my $extension;
+my $keepfilename;
+
+while(@ARGV) {
+ if($ARGV[0] eq "-d") {
+ shift @ARGV;
+ $dir = shift @ARGV;
+ }
+ elsif($ARGV[0] eq "-e") {
+ shift @ARGV;
+ $extension = shift @ARGV;
+ }
+ elsif($ARGV[0] eq "-k") {
+ shift @ARGV;
+ $keepfilename = 1;
+ }
+ elsif($ARGV[0] eq "-h") {
+ print <<HELP
+Usage: cd2nroff [options] [file.md]
+
+-d <dir> Write the output to the file name from the meta-data in the
+ specified directory, instead of writing to stdout
+-e <ext> If -d is used, this option can provide an added "extension", arbitrary
+ text really, to append to the file name.
+-h This help text,
+-v Show version then exit
+HELP
+ ;
+ exit 0;
+ }
+ elsif($ARGV[0] eq "-v") {
+ print "cd2nroff version $cd2nroff\n";
+ exit 0;
+ }
+ else {
+ last;
+ }
+}
+
+use POSIX qw(strftime);
+my @ts;
+if (defined($ENV{SOURCE_DATE_EPOCH})) {
+ @ts = localtime($ENV{SOURCE_DATE_EPOCH});
+} else {
+ @ts = localtime;
+}
+my $date = strftime "%B %d %Y", @ts;
+
+sub outseealso {
+ my (@sa) = @_;
+ my $comma = 0;
+ my @o;
+ push @o, ".SH SEE ALSO\n";
+ for my $s (sort @sa) {
+ push @o, sprintf "%s.BR $s", $comma ? ",\n": "";
+ $comma = 1;
+ }
+ push @o, "\n";
+ return @o;
+}
+
+sub single {
+ my @seealso;
+ my $d;
+ my ($f)=@_;
+ my $copyright;
+ my $errors = 0;
+ my $fh;
+ my $line;
+ my $salist;
+ my $section;
+ my $source;
+ my $spdx;
+ my $start = 0;
+ my $title;
+
+ if(defined($f)) {
+ if(!open($fh, "<:crlf", "$f")) {
+ print STDERR "Failed to open $f : $!\n";
+ return 1;
+ }
+ }
+ else {
+ $f = "STDIN";
+ $fh = \*STDIN;
+ binmode($fh, ":crlf");
+ }
+ while(<$fh>) {
+ $line++;
+ if(!$start) {
+ if(/^---/) {
+ # header starts here
+ $start = 1;
+ }
+ next;
+ }
+ if(/^Title: *(.*)/i) {
+ $title=$1;
+ }
+ elsif(/^Section: *(.*)/i) {
+ $section=$1;
+ }
+ elsif(/^Source: *(.*)/i) {
+ $source=$1;
+ }
+ elsif(/^See-also: +(.*)/i) {
+ $salist = 0;
+ push @seealso, $1;
+ }
+ elsif(/^See-also: */i) {
+ if($seealso[0]) {
+ print STDERR "$f:$line:1:ERROR: bad See-Also, needs list\n";
+ return 2;
+ }
+ $salist = 1;
+ }
+ elsif(/^ +- (.*)/i) {
+ # the only list we support is the see-also
+ if($salist) {
+ push @seealso, $1;
+ }
+ }
+ # REUSE-IgnoreStart
+ elsif(/^C: (.*)/i) {
+ $copyright=$1;
+ }
+ elsif(/^SPDX-License-Identifier: (.*)/i) {
+ $spdx=$1;
+ }
+ # REUSE-IgnoreEnd
+ elsif(/^---/) {
+ # end of the header section
+ if(!$title) {
+ print STDERR "ERROR: no 'Title:' in $f\n";
+ return 1;
+ }
+ if(!$section) {
+ print STDERR "ERROR: no 'Section:' in $f\n";
+ return 2;
+ }
+ if(!$seealso[0]) {
+ print STDERR "$f:$line:1:ERROR: no 'See-also:' present\n";
+ return 2;
+ }
+ if(!$copyright) {
+ print STDERR "$f:$line:1:ERROR: no 'C:' field present\n";
+ return 2;
+ }
+ if(!$spdx) {
+ print STDERR "$f:$line:1:ERROR: no 'SPDX-License-Identifier:' field present\n";
+ return 2;
+ }
+ last;
+ }
+ else {
+ chomp;
+ print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
+ }
+ }
+
+ if(!$start) {
+ print STDERR "$f:$line:1:ERROR: no header present\n";
+ return 2;
+ }
+
+ my @desc;
+ my $quote = 0;
+ my $blankline = 0;
+ my $header = 0;
+
+ # cut off the leading path from the file name, if any
+ $f =~ s/^(.*[\\\/])//;
+
+ push @desc, ".\\\" generated by cd2nroff $cd2nroff from $f\n";
+ push @desc, ".TH $title $section \"$date\" $source\n";
+ while(<$fh>) {
+ $line++;
+
+ $d = $_;
+
+ if($quote) {
+ if($quote == 4) {
+ # remove the indentation
+ if($d =~ /^ (.*)/) {
+ push @desc, "$1\n";
+ next;
+ }
+ else {
+ # end of quote
+ $quote = 0;
+ push @desc, ".fi\n";
+ next;
+ }
+ }
+ if(/^~~~/) {
+ # end of quote
+ $quote = 0;
+ push @desc, ".fi\n";
+ next;
+ }
+ # convert single backslahes to doubles
+ $d =~ s/\\/\\\\/g;
+ # lines starting with a period needs it escaped
+ $d =~ s/^\./\\&./;
+ push @desc, $d;
+ next;
+ }
+
+ # **bold**
+ $d =~ s/\*\*(\S.*?)\*\*/\\fB$1\\fP/g;
+ # *italics*
+ $d =~ s/\*(\S.*?)\*/\\fI$1\\fP/g;
+
+ # mentions of curl symbols with man pages use italics by default
+ $d =~ s/((lib|)curl([^ ]*\(3\)))/\\fI$1\\fP/gi;
+
+ # backticked becomes italics
+ $d =~ s/\`(.*?)\`/\\fI$1\\fP/g;
+
+ if(/^## (.*)/) {
+ my $word = $1;
+ # if there are enclosing quotes, remove them first
+ $word =~ s/[\"\'](.*)[\"\']\z/$1/;
+
+ # enclose in double quotes if there is a space present
+ if($word =~ / /) {
+ push @desc, ".IP \"$word\"\n";
+ }
+ else {
+ push @desc, ".IP $word\n";
+ }
+ $header = 1;
+ }
+ elsif(/^# (.*)/) {
+ my $word = $1;
+ # if there are enclosing quotes, remove them first
+ $word =~ s/[\"\'](.*)[\"\']\z/$1/;
+ push @desc, ".SH $word\n";
+ $header = 1;
+ }
+ elsif(/^~~~c/) {
+ # start of a code section, not indented
+ $quote = 1;
+ push @desc, "\n" if($blankline && !$header);
+ $header = 0;
+ push @desc, ".nf\n";
+ }
+ elsif(/^~~~/) {
+ # start of a quote section; not code, not indented
+ $quote = 1;
+ push @desc, "\n" if($blankline && !$header);
+ $header = 0;
+ push @desc, ".nf\n";
+ }
+ elsif(/^ (.*)/) {
+ # quoted, indented by 4 space
+ $quote = 4;
+ push @desc, "\n" if($blankline && !$header);
+ $header = 0;
+ push @desc, ".nf\n$1\n";
+ }
+ elsif(/^[ \t]*\n/) {
+ # count and ignore blank lines
+ $blankline++;
+ }
+ else {
+ # don't output newlines if this is the first content after a
+ # header
+ push @desc, "\n" if($blankline && !$header);
+ $blankline = 0;
+ $header = 0;
+
+ # remove single line HTML comments
+ $d =~ s/<!--.*?-->//g;
+
+ # quote minuses in the output
+ $d =~ s/([^\\])-/$1\\-/g;
+ # replace single quotes
+ $d =~ s/\'/\\(aq/g;
+ # handle double quotes first on the line
+ $d =~ s/^(\s*)\"/$1\\&\"/;
+
+ # lines starting with a period needs it escaped
+ $d =~ s/^\./\\&./;
+
+ if($d =~ /^(.*) /) {
+ printf STDERR "$f:$line:%d:ERROR: 2 spaces detected\n",
+ length($1);
+ $errors++;
+ }
+ if($d =~ /^[ \t]*\n/) {
+ # replaced away all contents
+ $blankline= 1;
+ }
+ else {
+ push @desc, $d;
+ }
+ }
+ }
+ if($fh != \*STDIN) {
+ close($fh);
+ }
+ push @desc, outseealso(@seealso);
+ if($dir) {
+ if($keepfilename) {
+ $title = $f;
+ $title =~ s/\.[^.]*$//;
+ }
+ my $outfile = "$dir/$title.$section";
+ if(defined($extension)) {
+ $outfile .= $extension;
+ }
+ if(!open(O, ">", $outfile)) {
+ print STDERR "Failed to open $outfile : $!\n";
+ return 1;
+ }
+ print O @desc;
+ close(O);
+ }
+ else {
+ print @desc;
+ }
+ return $errors;
+}
+
+if(@ARGV) {
+ for my $f (@ARGV) {
+ my $r = single($f);
+ if($r) {
+ exit $r;
+ }
+ }
+}
+else {
+ exit single();
+}
diff --git a/scripts/cdall b/scripts/cdall
new file mode 100755
index 000000000..507ccc6be
--- /dev/null
+++ b/scripts/cdall
@@ -0,0 +1,44 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# provide all dir names to scan on the cmdline
+
+sub convert {
+ my ($dir)=@_;
+ opendir(my $dh, $dir) || die "could not open $dir";
+ my @cd = grep { /\.md\z/ && -f "$dir/$_" } readdir($dh);
+ closedir $dh;
+
+ for my $cd (@cd) {
+ my $nroff = "$cd";
+ $nroff =~ s/\.md\z/.3/;
+ print "$dir/$cd = $dir/$nroff\n";
+ system("./scripts/cd2nroff -d $dir $dir/$cd");
+ }
+}
+
+for my $d (sort @ARGV) {
+ convert($d);
+}
diff --git a/scripts/checksrc.pl b/scripts/checksrc.pl
index b85b56b43..76f466081 100755
--- a/scripts/checksrc.pl
+++ b/scripts/checksrc.pl
@@ -59,6 +59,7 @@ my %warnings = (
'ASTERISKSPACE' => 'pointer declared with space after asterisk',
'BADCOMMAND' => 'bad !checksrc! instruction',
'BANNEDFUNC' => 'a banned function was used',
+ 'BANNEDPREPROC' => 'a banned symbol was used on a preprocessor line',
'BRACEELSE' => '} else on the same line',
'BRACEPOS' => 'wrong position for an open brace',
'BRACEWHILE' => 'A single space between open brace and while',
@@ -402,6 +403,13 @@ sub scanfile {
checksrc($cmd, $line, $file, $l)
}
+ if($l =~ /^#line (\d+) \"([^\"]*)\"/) {
+ # a #line instruction
+ $file = $2;
+ $line = $1;
+ next;
+ }
+
# check for a copyright statement and save the years
if($l =~ /\* +copyright .* (\d\d\d\d|)/i) {
my $count = 0;
@@ -892,6 +900,18 @@ sub scanfile {
"multiple spaces");
}
preproc:
+ if($prep) {
+ # scan for use of banned symbols on a preprocessor line
+ if($l =~ /^(^|.*\W)
+ (WIN32)
+ (\W|$)
+ /x) {
+ checkwarn("BANNEDPREPROC",
+ $line, length($1), $file, $ol,
+ "use of $2 is banned from preprocessor lines" .
+ (($2 eq "WIN32") ? ", use _WIN32 instead" : ""));
+ }
+ }
$line++;
$prevp = $prep;
$prevl = $ol if(!$prep);
diff --git a/scripts/ciconfig.pl b/scripts/ciconfig.pl
index 7c31f8e4a..e232e3e5e 100755
--- a/scripts/ciconfig.pl
+++ b/scripts/ciconfig.pl
@@ -58,7 +58,12 @@ my %defaulton = (
'threaded-resolver' => 1,
'pthreads' => 1,
'verbose' => 1,
- 'crypto-auth' => 1,
+ 'basic-auth' => 1,
+ 'bearer-auth' => 1,
+ 'digest-auth' => 1,
+ 'kerberos-auth' => 1,
+ 'negotiate-auth' => 1,
+ 'aws' => 1,
'ntlm' => 1,
'ntlm-wb' => 1,
'tls-srp' => 1,
diff --git a/scripts/cijobs.pl b/scripts/cijobs.pl
index a73b3f5bf..4c047973a 100755
--- a/scripts/cijobs.pl
+++ b/scripts/cijobs.pl
@@ -232,7 +232,7 @@ sub appveyor {
while(<G>) {
$line++;
- if($_ =~ /^( - |install)/) {
+ if($_ =~ /^( - |install)/) {
if($job{'image'}) {
$job{'os'} = "windows";
submit(\%job);
@@ -240,37 +240,37 @@ sub appveyor {
}
}
$job{'line'} = $line;
- if($_ =~ /^ APPVEYOR_BUILD_WORKER_IMAGE: \"(.*)\"/) {
+ if($_ =~ /^ APPVEYOR_BUILD_WORKER_IMAGE: \'(.*)\'/) {
$job{'image'}= $1;
}
- elsif($_ =~ /^ BUILD_SYSTEM: (.*)/) {
+ elsif($_ =~ /^ BUILD_SYSTEM: (.*)/) {
$job{'build'} = lc($1);
}
- elsif($_ =~ /^ PRJ_GEN: \"(.*)\"/) {
+ elsif($_ =~ /^ PRJ_GEN: \'(.*)\'/) {
$job{'compiler'} = $1;
}
- elsif($_ =~ /^ PRJ_CFG: (.*)/) {
+ elsif($_ =~ /^ PRJ_CFG: (.*)/) {
$job{'config'} = $1;
}
- elsif($_ =~ /^ OPENSSL: (.*)/) {
+ elsif($_ =~ /^ OPENSSL: \'(.*)\'/) {
$job{'openssl'} = $1 eq "ON" ? "true": "false";
}
- elsif($_ =~ /^ SCHANNEL: (.*)/) {
+ elsif($_ =~ /^ SCHANNEL: \'(.*)\'/) {
$job{'schannel'} = $1 eq "ON" ? "true": "false";
}
- elsif($_ =~ /^ ENABLE_UNICODE: (.*)/) {
+ elsif($_ =~ /^ ENABLE_UNICODE: \'(.*)\'/) {
$job{'unicode'} = $1 eq "ON" ? "true": "false";
}
- elsif($_ =~ /^ HTTP_ONLY: (.*)/) {
+ elsif($_ =~ /^ HTTP_ONLY: \'(.*)\'/) {
$job{'http-only'} = $1 eq "ON" ? "true": "false";
}
- elsif($_ =~ /^ TESTING: (.*)/) {
+ elsif($_ =~ /^ TESTING: \'(.*)\'/) {
$job{'testing'} = $1 eq "ON" ? "true": "false";
}
- elsif($_ =~ /^ SHARED: (.*)/) {
+ elsif($_ =~ /^ SHARED: \'(.*)\'/) {
$job{'shared'} = $1 eq "ON" ? "true": "false";
}
- elsif($_ =~ /^ TARGET: \"-A (.*)\"/) {
+ elsif($_ =~ /^ TARGET: \'-A (.*)\'/) {
$job{'target'} = $1;
}
}
diff --git a/scripts/cmp-config.pl b/scripts/cmp-config.pl
index b1717cded..e36fcdd3c 100755
--- a/scripts/cmp-config.pl
+++ b/scripts/cmp-config.pl
@@ -43,6 +43,7 @@ my %remove = (
'#define HAVE_DECL_GETPWUID_R 1' => 1,
'#define HAVE_DLFCN_H 1' => 1,
'#define HAVE_GETHOSTBYNAME 1' => 1,
+ '#define HAVE_INTTYPES_H 1' => 1,
'#define HAVE_IOCTL 1' => 1,
'#define HAVE_LDAP_SSL 1' => 1,
'#define HAVE_LIBBROTLIDEC 1' => 1,
@@ -57,6 +58,7 @@ my %remove = (
'#define HAVE_OPENSSL_X509_H 1' => 1,
'#define HAVE_SA_FAMILY_T 1' => 1,
'#define HAVE_SETJMP_H 1' => 1,
+ '#define HAVE_STDINT_H 1' => 1,
'#define HAVE_STDIO_H 1' => 1,
'#define HAVE_STDLIB_H 1' => 1,
'#define HAVE_STRING_H 1' => 1,
diff --git a/scripts/nroff2cd b/scripts/nroff2cd
new file mode 100755
index 000000000..500367f81
--- /dev/null
+++ b/scripts/nroff2cd
@@ -0,0 +1,193 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+=begin comment
+
+This script converts an nroff file to curldown
+
+Example: cd2nroff [options] <file.md> > <file.3>
+
+Note: when converting .nf sections, this tool does not know if the
+section is code or just regular quotes. It then assumes and uses ~~~c
+for code.
+
+=end comment
+=cut
+
+my $nroff2cd = "0.1"; # to keep check
+
+sub single {
+ my ($f)=@_;
+ open(F, "<:crlf", "$f") ||
+ return 1;
+ my $line;
+ my $title;
+ my $section;
+ my $source;
+ my @seealso;
+ my @desc;
+ my $header; # non-zero when TH is passed
+ my $quote = 0; # quote state
+ while(<F>) {
+ $line++;
+ my $d = $_;
+ if($_ =~ /^.\\\"/) {
+ # a comment we can ignore
+ next;
+ }
+ if(!$header) {
+ if($d =~ /.so (.*)/) {
+ # this is basically an include, so do that
+ my $f = $1;
+ # remove leading directory
+ $f =~ s/(.*?\/)//;
+ close(F);
+ open(F, "<:crlf", "$f") || return 1;
+ }
+ if($d =~ /^\.TH ([^ ]*) (\d) \"(.*?)\" ([^ \n]*)/) {
+ # header, this needs to be the first thing after leading comments
+ $title = $1;
+ $section = $2;
+ # date is $3
+ $source = $4;
+ # if there are enclosing quotes around source, remove them
+ $source =~ s/[\"\'](.*)[\"\']\z/$1/;
+ $header = 1;
+
+ print <<HEAD
+---
+c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+SPDX-License-Identifier: curl
+Title: $title
+Section: $section
+Source: $source
+HEAD
+ ;
+ }
+ next;
+ }
+
+ if($quote) {
+ if($d =~ /^\.SH/) {
+ #end of quote without an .fi
+ $quote = 0;
+ push @desc, "~~~\n";
+ }
+ elsif($d =~ /^\.fi/) {
+ #end of quote
+ $quote = 0;
+ push @desc, "~~~\n";
+ next;
+ }
+ else {
+ # double-backslashes converted to single ones
+ $d =~ s/\\\\/\\/g;
+ push @desc, $d;
+ next;
+ }
+ }
+ if($d =~ /^\.SH (.*)/) {
+ my $word = $1;
+ # if there are enclosing quotes, remove them first
+ $word =~ s/[\"\'](.*)[\"\']\z/$1/;
+ if($word eq "SEE ALSO") {
+ # we just slurp up this section
+ next;
+ }
+ push @desc, "\n# $word\n\n";
+ }
+ elsif($d =~ /^\.(RS|RE)/) {
+ # ignore these
+ }
+ elsif($d =~ /^\.IP (.*)/) {
+ my $word = $1;
+ # if there are enclosing quotes, remove them first
+ $word =~ s/[\"\'](.*)[\"\']\z/$1/;
+ push @desc, "\n## $word\n\n";
+ }
+ elsif($d =~ /^\.IP/) {
+ # .IP with no text we just skip
+ }
+ elsif($d =~ /^\.BR (.*)/) {
+ # only used for SEE ALSO
+ my $word = $1;
+ # remove trailing comma
+ $word =~ s/,\z//;
+
+ for my $s (split(/,/, $word)) {
+ # remove all double quotes
+ $s =~ s/\"//g;
+ # tream leading whitespace
+ $s =~ s/^ +//g;
+ push @seealso, $s;
+ }
+ }
+ elsif($d =~ /^\.I (.*)/) {
+ push @desc, "*$1*\n";
+ }
+ elsif($d =~ /^\.B (.*)/) {
+ push @desc, "**$1**\n";
+ }
+ elsif($d =~ /^\.nf/) {
+ push @desc, "~~~c\n";
+ $quote = 1;
+ }
+ else {
+ # embolden
+ $d =~ s/\\fB(.*?)\\fP/**$1**/g;
+ # links to "curl.*()" are left bare since cd2nroff handles them
+ # specially
+ $d =~ s/\\fI(curl.*?\(3\))\\fP/$1/ig;
+ # emphasize
+ $d =~ s/\\fI(.*?)\\fP/*$1*/g;
+ # emphasize on a split line
+ $d =~ s/\\fI/*/g;
+ # bold on a split line
+ $d =~ s/\\fB/**/g;
+ # remove backslash amp
+ $d =~ s/\\&//g;
+ # remove backslashes
+ $d =~ s/\\//g;
+ # fix single quotes
+ $d =~ s/\(aq/'/g;
+ # fix double quotes
+ $d =~ s/\(dq/\"/g;
+ push @desc, $d;
+ }
+ }
+ close(F);
+
+ print "See-also:\n";
+ for my $s (sort @seealso) {
+ print " - $s\n" if($s);
+ }
+ print "---\n";
+ print @desc;
+
+ return !$header;
+}
+
+exit single($ARGV[0]);
+
diff --git a/scripts/schemetable.c b/scripts/schemetable.c
new file mode 100644
index 000000000..ae79eaa09
--- /dev/null
+++ b/scripts/schemetable.c
@@ -0,0 +1,207 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include <stdio.h>
+#include <curl/curl.h>
+
+/*
+ * Use this tool to generate an updated table for the Curl_getn_scheme_handler
+ * function in url.c.
+ */
+
+struct detail {
+ const char *n;
+ const char *ifdef;
+};
+
+static const struct detail scheme[] = {
+ {"dict", "#ifndef CURL_DISABLE_DICT" },
+ {"file", "#ifndef CURL_DISABLE_FILE" },
+ {"ftp", "#ifndef CURL_DISABLE_FTP" },
+ {"ftps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)" },
+ {"gopher", "#ifndef CURL_DISABLE_GOPHER" },
+ {"gophers", "#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)" },
+ {"http", "#ifndef CURL_DISABLE_HTTP" },
+ {"https", "#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" },
+ {"imap", "#ifndef CURL_DISABLE_IMAP" },
+ {"imaps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)" },
+ {"ldap", "#ifndef CURL_DISABLE_LDAP" },
+ {"ldaps", "#if !defined(CURL_DISABLE_LDAP) && \\\n"
+ " !defined(CURL_DISABLE_LDAPS) && \\\n"
+ " ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n"
+ " (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" },
+ {"mqtt", "#ifndef CURL_DISABLE_MQTT" },
+ {"pop3", "#ifndef CURL_DISABLE_POP3" },
+ {"pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" },
+ {"rtmp", "#ifdef USE_LIBRTMP" },
+ {"rtmpt", "#ifdef USE_LIBRTMP" },
+ {"rtmpe", "#ifdef USE_LIBRTMP" },
+ {"rtmpte", "#ifdef USE_LIBRTMP" },
+ {"rtmps", "#ifdef USE_LIBRTMP" },
+ {"rtmpts", "#ifdef USE_LIBRTMP" },
+ {"rtsp", "#ifndef CURL_DISABLE_RTSP" },
+ {"scp", "#if defined(USE_SSH) && !defined(USE_WOLFSSH)" },
+ {"sftp", "#if defined(USE_SSH)" },
+ {"smb", "#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \\\n"
+ " (SIZEOF_CURL_OFF_T > 4)" },
+ {"smbs", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \\\n"
+ " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" },
+ {"smtp", "#ifndef CURL_DISABLE_SMTP" },
+ {"smtps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)" },
+ {"telnet", "#ifndef CURL_DISABLE_TELNET" },
+ {"tftp", "#ifndef CURL_DISABLE_TFTP" },
+ {"ws", "#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" },
+ {"wss", "#if defined(USE_WEBSOCKETS) && \\\n"
+ " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" },
+ { NULL, NULL }
+};
+
+unsigned int calc(const char *s, int add, int shift)
+{
+ const char *so = s;
+ unsigned int c = add;
+ while(*s) {
+ c <<= shift;
+ c += *s;
+ s++;
+ }
+ return c;
+}
+
+unsigned int num[100];
+unsigned int ix[100];
+
+static void showtable(int try, int init, int shift)
+{
+ int nulls = 0;
+ int i;
+ for(i = 0; scheme[i].n; ++i)
+ num[i] = calc(scheme[i].n, init, shift);
+ for(i = 0; scheme[i].n; ++i)
+ ix[i] = num[i] % try;
+ printf("/*\n"
+ " unsigned int c = %d\n"
+ " while(l) {\n"
+ " c <<= %d;\n"
+ " c += Curl_raw_tolower(*s);\n"
+ " s++;\n"
+ " l--;\n"
+ " }\n"
+ "*/\n", init, shift);
+
+ printf(" static const struct Curl_handler * const protocols[%d] = {", try);
+
+ /* generate table */
+ for(i=0; i < try; i++) {
+ int match = 0;
+ int j;
+ for(j=0; scheme[j].n; j++) {
+ if(ix[j] == i) {
+ printf("\n");
+ printf("%s\n", scheme[j].ifdef);
+ printf(" &Curl_handler_%s,\n", scheme[j].n);
+ printf("#else\n NULL,\n");
+ printf("#endif");
+ match = 1;
+ nulls = 0;
+ break;
+ }
+ }
+ if(!match) {
+ if(!nulls || (nulls>10)) {
+ printf("\n ");
+ nulls = 0;
+ }
+ printf(" NULL,", nulls);
+ nulls++;
+ }
+ }
+ printf("\n };\n");
+}
+
+int main(void)
+{
+ int i;
+ int try;
+ int besttry = 9999;
+ int bestadd = 0;
+ int bestshift = 0;
+ int add;
+ int shift;
+ for(shift = 0; shift < 8; shift++) {
+ for(add = 0; add < 999; add++) {
+ for(i = 0; scheme[i].n; ++i) {
+ unsigned int v = calc(scheme[i].n, add, shift);
+ int j;
+ int badcombo = 0;
+ for(j=0; j < i; j++) {
+
+ if(num[j] == v) {
+ /*
+ printf("NOPE: %u is a dupe (%s and %s)\n",
+ v, scheme[i], scheme[j]);
+ */
+ badcombo = 1;
+ break;
+ }
+ }
+ if(badcombo)
+ break;
+ num[i] = v;
+ }
+#if 0
+ for(i = 0; scheme[i].n; ++i) {
+ printf("%u - %s\n", num[i], scheme[i].n);
+ }
+#endif
+ /* try different remainders to find smallest possible table */
+ for(try = 28; try < 199; try++) {
+ int good = 1;
+ for(i = 0; scheme[i].n; ++i) {
+ ix[i] = num[i] % try;
+ }
+ /* check for dupes */
+ for(i = 0; scheme[i].n && good; ++i) {
+ int j;
+ for(j=0; j < i; j++) {
+ if(ix[j] == ix[i]) {
+ /* printf("NOPE, try %u causes dupes (%d and %d)\n", try, j, i); */
+ good = 0;
+ break;
+ }
+ }
+ }
+ if(good) {
+ if(try < besttry) {
+ besttry = try;
+ bestadd = add;
+ bestshift = shift;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ showtable(besttry, bestadd, bestshift);
+}
diff --git a/scripts/singleuse.pl b/scripts/singleuse.pl
index b8a57f8d8..c4e1bed51 100755
--- a/scripts/singleuse.pl
+++ b/scripts/singleuse.pl
@@ -43,6 +43,7 @@ my $file = $ARGV[0];
my %wl = (
'curlx_uztoso' => 'cmdline tool use',
+ 'Curl_xfer_write_resp' => 'internal api',
);
my %api = (
diff --git a/scripts/updatemanpages.pl b/scripts/updatemanpages.pl
deleted file mode 100755
index 58a8755e8..000000000
--- a/scripts/updatemanpages.pl
+++ /dev/null
@@ -1,357 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-
-# Update man pages.
-
-use strict;
-use warnings;
-use Tie::File;
-
-# Data from the command line.
-
-my $curlver = $ARGV[0];
-my $curldate = $ARGV[1];
-
-# Directories and extensions.
-
-my @dirlist = ("docs/", "docs/libcurl/", "docs/libcurl/opts/", "tests/");
-my @extlist = (".1", ".3");
-my @excludelist = ("mk-ca-bundle.1", "template.3");
-
-# Subroutines
-
-sub printargs{
- # Print arguments and exit.
-
- print "usage: updatemanpages.pl <version> <date>\n";
- exit;
-}
-
-sub getthline{
- # Process file looking for .TH section.
-
- my $filename = shift;
- my $file_handle;
- my $file_line;
-
- # Open the file.
-
- open($file_handle, $filename);
-
- # Look for the .TH section, process it into an array,
- # modify it and write to file.
-
- tie(my @file_data, 'Tie::File', $filename);
- foreach my $file_data_line(@file_data) {
- if($file_data_line =~ /^.TH/) {
- $file_line = $file_data_line;
- last;
- }
- }
-
- # Close the file.
-
- close($file_handle);
- return $file_line;
-}
-
-sub extractth{
- # Extract .TH section as an array.
-
- my $input = shift;
-
- # Split the line into an array.
-
- my @tharray;
- my $inputsize = length($input);
- my $inputcurrent = "";
- my $quotemode = 0;
-
- for(my $inputseek = 0; $inputseek < $inputsize; $inputseek++) {
-
- if(substr($input, $inputseek, 1) eq " " && $quotemode eq 0) {
- push(@tharray, $inputcurrent);
- $inputcurrent = "";
- next;
- }
-
- $inputcurrent = $inputcurrent . substr($input, $inputseek, 1);
-
- if(substr($input, $inputseek, 1) eq "\"") {
- if($quotemode eq 0) {
- $quotemode = 1;
- }
- else {
- $quotemode = 0;
- }
- }
- }
-
- if($inputcurrent ne "") {
- push(@tharray, $inputcurrent);
- }
-
- return @tharray;
-}
-
-sub getdate{
- # Get the date from the .TH section.
-
- my $filename = shift;
- my $thline;
- my @tharray;
- my $date = "";
-
- $thline = getthline($filename);
-
- # Return nothing if there is no .TH section found.
-
- if(!$thline || $thline eq "") {
- return "";
- }
-
- @tharray = extractth($thline);
-
- # Remove the quotes at the start and end.
-
- $date = substr($tharray[3], 1, -1);
- return $date;
-}
-
-sub processth{
- # Process .TH section.
-
- my $input = shift;
- my $date = shift;
-
- # Split the line into an array.
-
- my @tharray = extractth($input);
-
- # Alter the date.
-
- my $itemdate = "\"";
- $itemdate .= $date;
- $itemdate .= "\"";
- $tharray[3] = $itemdate;
-
- # Alter the item version.
-
- my $itemver = $tharray[4];
- my $itemname = "";
-
- for(my $itemnameseek = 1;
- $itemnameseek < length($itemver);
- $itemnameseek++) {
- if(substr($itemver, $itemnameseek, 1) eq " " ||
- substr($itemver, $itemnameseek, 1) eq "\"") {
- last;
- }
- $itemname .= substr($itemver, $itemnameseek, 1);
- }
-
- $itemver = "\"";
- $itemver .= $itemname;
- $itemver .= " ";
- $itemver .= $curlver;
- $itemver .= "\"";
-
- $tharray[4] = $itemver;
-
- my $thoutput = "";
-
- foreach my $thvalue (@tharray) {
- $thoutput .= $thvalue;
- $thoutput .= " ";
- }
- $thoutput =~ s/\s+$//;
- $thoutput .= "\n";
-
- # Return updated string.
-
- return $thoutput;
-}
-
-sub processfile{
- # Process file looking for .TH section.
-
- my $filename = shift;
- my $date = shift;
- my $file_handle;
- my $file_dist_handle;
- my $filename_dist;
-
- # Open a handle for the original file and a second file handle
- # for the dist file.
-
- $filename_dist = $filename . ".dist";
-
- open($file_handle, $filename);
- open($file_dist_handle, ">" . $filename_dist);
-
- # Look for the .TH section, process it into an array,
- # modify it and write to file.
-
- tie(my @file_data, 'Tie::File', $filename);
- foreach my $file_data_line (@file_data) {
- if($file_data_line =~ /^.TH/) {
- my $file_dist_line = processth($file_data_line, $date);
- print $file_dist_handle $file_dist_line . "\n";
- }
- else {
- print $file_dist_handle $file_data_line . "\n";
- }
- }
-
- # Close the file.
-
- close($file_handle);
- close($file_dist_handle);
-}
-
-# Check that $curlver is set, otherwise print arguments and exit.
-
-if(!$curlver) {
- printargs();
-}
-
-# check to see that the git command works, it requires git 2.6 something
-my $gitcheck = `git log -1 --date="format:%B %d, %Y" $dirlist[0] 2>/dev/null`;
-if(length($gitcheck) < 1) {
- print "git version too old or $dirlist[0] is a bad argument\n";
- exit;
-}
-
-# Look in each directory.
-
-my $dir_handle;
-
-foreach my $dirname (@dirlist) {
- foreach my $extname (@extlist) {
- # Go through the directory looking for files ending with
- # the current extension.
-
- opendir($dir_handle, $dirname);
- my @filelist = grep(/.$extname$/i, readdir($dir_handle));
-
- foreach my $file (@filelist) {
- # Skip if file is in exclude list.
-
- if(grep(/^$file$/, @excludelist)) {
- next;
- }
-
- # Load the file and get the date.
-
- my $filedate;
-
- # Check if dist version exists and load date from that
- # file if it does.
-
- if(-e ($dirname . $file . ".dist")) {
- $filedate = getdate(($dirname . $file . ".dist"));
- }
- else {
- $filedate = getdate(($dirname . $file));
- }
-
- # Skip if value is empty.
-
- if(!$filedate || $filedate eq "") {
- next;
- }
-
- # Check the man page in the git repository.
-
- my $repodata = `LC_TIME=C git log -1 --date="format:%B %d, %Y" \\
- --since="$filedate" $dirname$file | grep ^Date:`;
-
- # If there is output then update the man page
- # with the new date/version.
-
- # Process the file if there is output.
-
- if($repodata) {
- my $thisdate;
- if(!$curldate) {
- if($repodata =~ /^Date: +(.*)/) {
- $thisdate = $1;
- }
- else {
- print STDERR "Warning: " . ($dirname . $file) . ": found no " .
- "date\n";
- }
- }
- else {
- $thisdate = $curldate;
- }
- processfile(($dirname . $file), $thisdate);
- print $dirname . $file . " page updated to $thisdate\n";
- }
- }
- closedir($dir_handle);
- }
-}
-
-__END__
-
-=pod
-
-=head1 updatemanpages.pl
-
-Updates the man pages with the version number and optional date. If the date
-isn't provided, the last modified date from git is used.
-
-=head2 USAGE
-
-updatemanpages.pl version [date]
-
-=head3 version
-
-Specifies version (required)
-
-=head3 date
-
-Specifies date (optional)
-
-=head2 SETTINGS
-
-=head3 @dirlist
-
-Specifies the list of directories to look for files in.
-
-=head3 @extlist
-
-Specifies the list of files with extensions to process.
-
-=head3 @excludelist
-
-Specifies the list of files to not process.
-
-=head2 NOTES
-
-This script is used during maketgz.
-
-=cut
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a3c4218ea..5695670f0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -24,7 +24,8 @@
set(EXE_NAME curl)
add_definitions(-DBUILDING_CURL)
-if(USE_MANUAL)
+if(ENABLE_CURL_MANUAL AND HAVE_MANUAL_TOOLS)
+ add_definitions("-DUSE_MANUAL")
# Use the C locale to ensure that only ASCII characters appear in the
# embedded text. NROFF and MANOPT are set in the parent CMakeLists.txt
add_custom_command(
diff --git a/src/Makefile.am b/src/Makefile.am
index ddeb70073..7a99c2548 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,6 +61,8 @@ curl_SOURCES += $(CURL_RCFILES)
$(CURL_RCFILES): tool_version.h
endif
+curl_LDFLAGS = $(AM_LDFLAGS) $(CURL_LDFLAGS_BIN)
+
# This might hold -Werror
CFLAGS += @CURL_CFLAG_EXTRAS@
@@ -89,7 +91,7 @@ CLEANFILES = tool_hugehelp.c
NROFF=env LC_ALL=C @NROFF@ @MANOPT@ 2>/dev/null # figured out by the configure script
EXTRA_DIST = mkhelp.pl \
- Makefile.mk curl.rc Makefile.inc CMakeLists.txt
+ Makefile.mk curl.rc Makefile.inc CMakeLists.txt .checksrc
# Use absolute directory to disable VPATH
MANPAGE=$(abs_top_builddir)/docs/curl.1
@@ -155,7 +157,7 @@ tidy:
$(TIDY) $(CURL_CFILES) $(TIDYFLAGS) -- $(curl_CPPFLAGS) $(CPPFLAGS) -DHAVE_CONFIG_H
listhelp:
- (cd $(top_srcdir)/docs/cmdline-opts && ./gen.pl listhelp *.d) > tool_listhelp.c
+ (cd $(top_srcdir)/docs/cmdline-opts && make listhelp)
if HAVE_WINDRES
.rc.o:
diff --git a/src/Makefile.inc b/src/Makefile.inc
index 253893536..c1d202a06 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -79,6 +79,7 @@ CURL_CFILES = \
tool_help.c \
tool_helpers.c \
tool_hugehelp.c \
+ tool_ipfs.c \
tool_libinfo.c \
tool_listhelp.c \
tool_main.c \
@@ -122,6 +123,7 @@ CURL_HFILES = \
tool_help.h \
tool_helpers.h \
tool_hugehelp.h \
+ tool_ipfs.h \
tool_libinfo.h \
tool_main.h \
tool_msgs.h \
diff --git a/src/Makefile.mk b/src/Makefile.mk
index 66882b353..83dd65d16 100644
--- a/src/Makefile.mk
+++ b/src/Makefile.mk
@@ -32,31 +32,13 @@ include $(PROOT)/lib/Makefile.mk
### Local
-RCFLAGS += -DCURL_EMBED_MANIFEST
CPPFLAGS += -I$(PROOT)/lib
LDFLAGS += -L$(PROOT)/lib
LIBS := -lcurl $(LIBS)
-ifdef WIN32
- ifneq ($(findstring -dyn,$(CFG)),)
- DYN := 1
- endif
-endif
-
-ifdef DYN
- curl_DEPENDENCIES := $(PROOT)/lib/libcurl$(CURL_DLL_SUFFIX).dll
- curl_DEPENDENCIES += $(PROOT)/lib/libcurl.dll.a
-else
- curl_DEPENDENCIES := $(PROOT)/lib/libcurl.a
- ifdef WIN32
- CPPFLAGS += -DCURL_STATICLIB
- LDFLAGS += -static
- endif
-endif
-
### Sources and targets
-# Provides CURL_CFILES, CURLX_CFILES, CURL_RCFILES
+# Provides CURL_CFILES, CURLX_CFILES
include Makefile.inc
TARGETS := curl$(BIN_EXT)
@@ -64,12 +46,9 @@ TARGETS := curl$(BIN_EXT)
CURL_CFILES += $(notdir $(CURLX_CFILES))
curl_OBJECTS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(strip $(CURL_CFILES)))
-ifdef WIN32
-curl_OBJECTS += $(patsubst %.rc,$(OBJ_DIR)/%.res,$(strip $(CURL_RCFILES)))
-endif
ifdef MAP
CURL_MAP := curl.map
-CURL_LDFLAGS_BIN += -Wl,-Map,$(CURL_MAP)
+LDFLAGS += -Wl,-Map,$(CURL_MAP)
TOVCLEAN := $(CURL_MAP)
endif
vpath %.c $(PROOT)/lib
@@ -105,7 +84,7 @@ tool_hugehelp.c:
endif
endif
-$(TARGETS): $(curl_OBJECTS) $(curl_DEPENDENCIES)
- $(CC) $(LDFLAGS) $(CURL_LDFLAGS_BIN) -o $@ $(curl_OBJECTS) $(LIBS)
+$(TARGETS): $(curl_OBJECTS) $(PROOT)/lib/libcurl.a
+ $(CC) $(LDFLAGS) -o $@ $(curl_OBJECTS) $(LIBS)
all: $(OBJ_DIR) $(TARGETS)
diff --git a/src/curl.rc b/src/curl.rc
index 11d528429..6fcaf353e 100644
--- a/src/curl.rc
+++ b/src/curl.rc
@@ -53,7 +53,7 @@ BEGIN
VALUE "OriginalFilename", "curl.exe\0"
VALUE "ProductName", "The curl executable\0"
VALUE "ProductVersion", CURL_VERSION "\0"
- VALUE "LegalCopyright", "\xa9 " CURL_COPYRIGHT "\0" /* a9: Copyright symbol */
+ VALUE "LegalCopyright", "Copyright (C) " CURL_COPYRIGHT "\0"
VALUE "License", "https://curl.se/docs/copyright.html\0"
END
END
diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c
index ce5e25e92..cbf57f057 100644
--- a/src/tool_cb_dbg.c
+++ b/src/tool_cb_dbg.c
@@ -217,7 +217,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(output, "%s%s== Info: %.*s", timebuf, idsbuf, (int)size, data);
- /* FALLTHROUGH */
+ FALLTHROUGH();
default: /* in case a new one is introduced to shock us */
return 0;
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index df44f7aa7..30ee3b09c 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -41,9 +41,9 @@
static char *parse_filename(const char *ptr, size_t len);
-#ifdef WIN32
-#define BOLD
-#define BOLDOFF
+#ifdef _WIN32
+#define BOLD "\x1b[1m"
+#define BOLDOFF "\x1b[22m"
#else
#define BOLD "\x1b[1m"
/* Switch off bold by setting "all attributes off" since the explicit
@@ -87,7 +87,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
}
#endif
-#ifdef WIN32
+#ifdef _WIN32
/* Discard incomplete UTF-8 sequence buffered from body */
if(outs->utf8seq[0])
memset(outs->utf8seq, 0, sizeof(outs->utf8seq));
@@ -150,16 +150,19 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
char *filename;
size_t len;
- while(*p && (p < end) && !ISALPHA(*p))
+ while((p < end) && *p && !ISALPHA(*p))
p++;
if(p > end - 9)
break;
if(memcmp(p, "filename=", 9)) {
/* no match, find next parameter */
- while((p < end) && (*p != ';'))
+ while((p < end) && *p && (*p != ';'))
p++;
- continue;
+ if((p < end) && *p)
+ continue;
+ else
+ break;
}
p += 9;
@@ -175,10 +178,18 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
return CURL_WRITEFUNC_ERROR;
}
+ if(per->config->output_dir) {
+ outs->filename = aprintf("%s/%s", per->config->output_dir, filename);
+ free(filename);
+ if(!outs->filename)
+ return CURL_WRITEFUNC_ERROR;
+ }
+ else
+ outs->filename = filename;
+
outs->is_cd_filename = TRUE;
outs->s_isreg = TRUE;
outs->fopened = FALSE;
- outs->filename = filename;
outs->alloc_filename = TRUE;
hdrcbdata->honor_cd_filename = FALSE; /* done now! */
if(!tool_create_output_file(outs, per->config))
@@ -209,7 +220,11 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
if(!outs->stream && !tool_create_output_file(outs, per->config))
return CURL_WRITEFUNC_ERROR;
- if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output)
+ if(hdrcbdata->global->isatty &&
+#ifdef _WIN32
+ tool_term_has_bold &&
+#endif
+ hdrcbdata->global->styled_output)
value = memchr(ptr, ':', cb);
if(value) {
size_t namelen = value - ptr;
@@ -297,7 +312,7 @@ static char *parse_filename(const char *ptr, size_t len)
if(copy != p)
memmove(copy, p, strlen(p) + 1);
-#if defined(MSDOS) || defined(WIN32)
+#if defined(_WIN32) || defined(MSDOS)
{
char *sanitized;
SANITIZEcode sc = sanitize_file_name(&sanitized, copy, 0);
@@ -306,7 +321,7 @@ static char *parse_filename(const char *ptr, size_t len)
return NULL;
copy = sanitized;
}
-#endif /* MSDOS || WIN32 */
+#endif /* _WIN32 || MSDOS */
/* in case we built debug enabled, we allow an environment variable
* named CURL_TESTDIR to prefix the given file name to put it into a
diff --git a/src/tool_cb_prg.c b/src/tool_cb_prg.c
index 47ec3ef39..86b6fa605 100644
--- a/src/tool_cb_prg.c
+++ b/src/tool_cb_prg.c
@@ -38,6 +38,8 @@
#include "memdebug.h" /* keep this as LAST include */
+#define MAX_BARLENGTH 256
+
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#elif defined(HAVE_TERMIO_H)
@@ -78,11 +80,16 @@ static const unsigned int sinus[] = {
static void fly(struct ProgressData *bar, bool moved)
{
- char buf[256];
+ char buf[MAX_BARLENGTH + 2];
int pos;
int check = bar->width - 2;
- msnprintf(buf, sizeof(buf), "%*s\r", bar->width-1, " ");
+ /* bar->width is range checked when assigned */
+ DEBUGASSERT(bar->width <= MAX_BARLENGTH);
+ memset(buf, ' ', bar->width);
+ buf[bar->width] = '\r';
+ buf[bar->width + 1] = '\0';
+
memcpy(&buf[bar->bar], "-=O=-", 5);
pos = sinus[bar->tick%200] / (1000000 / check);
@@ -114,8 +121,6 @@ static void fly(struct ProgressData *bar, bool moved)
** callback for CURLOPT_XFERINFOFUNCTION
*/
-#define MAX_BARLENGTH 256
-
#if (SIZEOF_CURL_OFF_T < 8)
#error "too small curl_off_t"
#else
@@ -203,7 +208,14 @@ int tool_progress_cb(void *clientp,
memset(line, '#', num);
line[num] = '\0';
msnprintf(format, sizeof(format), "\r%%-%ds %%5.1f%%%%", barwidth);
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
fprintf(bar->out, format, line, percent);
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
}
fflush(bar->out);
bar->prev = point;
@@ -249,7 +261,7 @@ void progressbarinit(struct ProgressData *bar,
struct winsize ts;
if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts))
cols = ts.ws_col;
-#elif defined(WIN32)
+#elif defined(_WIN32)
{
HANDLE stderr_hnd = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO console_info;
diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c
index d70a9b909..8cb5bbe8a 100644
--- a/src/tool_cb_rea.c
+++ b/src/tool_cb_rea.c
@@ -62,7 +62,7 @@ size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
if(msdelta > config->timeout_ms)
/* timeout */
return 0;
-#ifndef WIN32
+#ifndef _WIN32
/* this logic waits on read activity on a file descriptor that is not a
socket which makes it not work with select() on Windows */
else {
diff --git a/src/tool_cb_see.c b/src/tool_cb_see.c
index 8351473c8..bce57bb28 100644
--- a/src/tool_cb_see.c
+++ b/src/tool_cb_see.c
@@ -93,21 +93,6 @@ int tool_seek_cb(void *userdata, curl_off_t offset, int whence)
#ifdef USE_TOOL_FTRUNCATE
-#ifdef __BORLANDC__
-/* 64-bit lseek-like function unavailable */
-# define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
-#endif
-
-#ifdef __POCC__
-# if(__POCC__ < 450)
-/* 64-bit lseek-like function unavailable */
-# define _lseeki64(hnd,ofs,whence) _lseek(hnd,ofs,whence)
-# else
-# undef _lseeki64
-# define _lseeki64(hnd,ofs,whence) _lseek64(hnd,ofs,whence)
-# endif
-#endif
-
#ifdef _WIN32_WCE
/* 64-bit lseek-like function unavailable */
# undef _lseeki64
diff --git a/src/tool_cb_see.h b/src/tool_cb_see.h
index 14bbc4264..b5d7bf985 100644
--- a/src/tool_cb_see.h
+++ b/src/tool_cb_see.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "tool_setup.h"
-#if defined(WIN32) && !defined(HAVE_FTRUNCATE)
+#if defined(_WIN32) && !defined(HAVE_FTRUNCATE)
int tool_ftruncate64(int fd, curl_off_t where);
@@ -35,7 +35,7 @@ int tool_ftruncate64(int fd, curl_off_t where);
#define HAVE_FTRUNCATE 1
#define USE_TOOL_FTRUNCATE 1
-#endif /* WIN32 && ! HAVE_FTRUNCATE */
+#endif /* _WIN32 && ! HAVE_FTRUNCATE */
/*
** callback for CURLOPT_SEEKFUNCTION
diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c
index b7838664e..143cba255 100644
--- a/src/tool_cb_wrt.c
+++ b/src/tool_cb_wrt.c
@@ -44,7 +44,7 @@
#ifndef O_BINARY
#define O_BINARY 0
#endif
-#ifdef WIN32
+#ifdef _WIN32
#define OPENMODE S_IREAD | S_IWRITE
#else
#define OPENMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
@@ -57,7 +57,6 @@ bool tool_create_output_file(struct OutStruct *outs,
struct GlobalConfig *global;
FILE *file = NULL;
char *fname = outs->filename;
- char *aname = NULL;
DEBUGASSERT(outs);
DEBUGASSERT(config);
global = config->global;
@@ -66,15 +65,6 @@ bool tool_create_output_file(struct OutStruct *outs,
return FALSE;
}
- if(config->output_dir && outs->is_cd_filename) {
- aname = aprintf("%s/%s", config->output_dir, fname);
- if(!aname) {
- errorf(global, "out of memory");
- return FALSE;
- }
- fname = aname;
- }
-
if(config->file_clobber_mode == CLOBBER_ALWAYS ||
(config->file_clobber_mode == CLOBBER_DEFAULT &&
!outs->is_cd_filename)) {
@@ -94,14 +84,12 @@ bool tool_create_output_file(struct OutStruct *outs,
char *newname;
/* Guard against wraparound in new filename */
if(newlen < len) {
- free(aname);
errorf(global, "overflow in filename generation");
return FALSE;
}
newname = malloc(newlen);
if(!newname) {
errorf(global, "out of memory");
- free(aname);
return FALSE;
}
memcpy(newname, fname, len);
@@ -135,10 +123,8 @@ bool tool_create_output_file(struct OutStruct *outs,
if(!file) {
warnf(global, "Failed to open the file %s: %s", fname,
strerror(errno));
- free(aname);
return FALSE;
}
- free(aname);
outs->s_isreg = TRUE;
outs->fopened = TRUE;
outs->stream = file;
@@ -159,7 +145,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
struct OperationConfig *config = per->config;
size_t bytes = sz * nmemb;
bool is_tty = config->global->isatty;
-#ifdef WIN32
+#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO console_info;
intptr_t fhnd;
#endif
@@ -231,13 +217,13 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
}
}
-#ifdef WIN32
+#ifdef _WIN32
fhnd = _get_osfhandle(fileno(outs->stream));
/* if windows console then UTF-8 must be converted to UTF-16 */
if(isatty(fileno(outs->stream)) &&
GetConsoleScreenBufferInfo((HANDLE)fhnd, &console_info)) {
wchar_t *wc_buf;
- DWORD wc_len;
+ DWORD wc_len, chars_written;
unsigned char *rbuf = (unsigned char *)buffer;
DWORD rlen = (DWORD)bytes;
@@ -292,7 +278,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
(HANDLE) fhnd,
prefix,
prefix[1] ? 2 : 1,
- NULL,
+ &chars_written,
NULL)) {
return CURL_WRITEFUNC_ERROR;
}
@@ -351,7 +337,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
(HANDLE) fhnd,
wc_buf,
wc_len,
- NULL,
+ &chars_written,
NULL)) {
free(wc_buf);
return CURL_WRITEFUNC_ERROR;
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 906e23e14..3259bc7a5 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -25,6 +25,7 @@
#include "tool_cfgable.h"
#include "tool_formparse.h"
+#include "tool_paramhlp.h"
#include "tool_main.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -33,7 +34,6 @@ void config_init(struct OperationConfig *config)
{
memset(config, 0, sizeof(struct OperationConfig));
- config->postfieldsize = -1;
config->use_httpget = FALSE;
config->create_dirs = FALSE;
config->maxredirs = DEFAULT_MAXREDIRS;
@@ -45,6 +45,7 @@ void config_init(struct OperationConfig *config)
config->http09_allowed = FALSE;
config->ftp_skip_ip = TRUE;
config->file_clobber_mode = CLOBBER_DEFAULT;
+ curlx_dyn_init(&config->postdata, MAX_FILE2MEMORY);
}
static void free_config_fields(struct OperationConfig *config)
@@ -59,7 +60,7 @@ static void free_config_fields(struct OperationConfig *config)
Curl_safefree(config->cookiejar);
curl_slist_free_all(config->cookiefiles);
- Curl_safefree(config->postfields);
+ Curl_dyn_free(&config->postdata);
Curl_safefree(config->query);
Curl_safefree(config->referer);
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 57e8fce52..dfa74d81f 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -68,7 +68,7 @@ struct OperationConfig {
char *proto_default;
curl_off_t resume_from;
char *postfields;
- curl_off_t postfieldsize;
+ struct curlx_dynbuf postdata;
char *referer;
char *query;
long timeout_ms;
diff --git a/src/tool_dirhie.c b/src/tool_dirhie.c
index 16765c3a5..1cadbd0be 100644
--- a/src/tool_dirhie.c
+++ b/src/tool_dirhie.c
@@ -25,7 +25,7 @@
#include <sys/stat.h>
-#ifdef WIN32
+#ifdef _WIN32
# include <direct.h>
#endif
@@ -38,7 +38,7 @@
#include "memdebug.h" /* keep this as LAST include */
-#if defined(WIN32) || (defined(MSDOS) && !defined(__DJGPP__))
+#if defined(_WIN32) || (defined(MSDOS) && !defined(__DJGPP__))
# define mkdir(x,y) (mkdir)((x))
# ifndef F_OK
# define F_OK 0
@@ -88,7 +88,7 @@ static void show_dir_errno(struct GlobalConfig *global, const char *name)
* should create all the dir* automagically
*/
-#if defined(WIN32) || defined(__DJGPP__)
+#if defined(_WIN32) || defined(__DJGPP__)
/* systems that may use either or when specifying a path */
#define PATH_DELIMITERS "\\/"
#else
@@ -132,7 +132,7 @@ CURLcode create_dir_hierarchy(const char *outfile, struct GlobalConfig *global)
msnprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
else {
if(outdup == tempdir) {
-#if defined(MSDOS) || defined(WIN32)
+#if defined(_WIN32) || defined(MSDOS)
/* Skip creating a drive's current directory.
It may seem as though that would harmlessly fail but it could be
a corner case if X: did not exist, since we would be creating it
diff --git a/src/tool_doswin.c b/src/tool_doswin.c
index faa5755e6..db2b8b78a 100644
--- a/src/tool_doswin.c
+++ b/src/tool_doswin.c
@@ -23,13 +23,13 @@
***************************************************************************/
#include "tool_setup.h"
-#if defined(MSDOS) || defined(WIN32)
+#if defined(_WIN32) || defined(MSDOS)
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
# include <libgen.h>
#endif
-#ifdef WIN32
+#ifdef _WIN32
# include <stdlib.h>
# include <tlhelp32.h>
# include "tool_cfgable.h"
@@ -42,7 +42,7 @@
#include "curlx.h"
#include "memdebug.h" /* keep this as LAST include */
-#ifdef WIN32
+#ifdef _WIN32
# undef PATH_MAX
# define PATH_MAX MAX_PATH
#endif
@@ -55,7 +55,7 @@
# endif
#endif
-#ifdef WIN32
+#ifdef _WIN32
# define _use_lfn(f) (1) /* long file names always available */
#elif !defined(__DJGPP__) || (__DJGPP__ < 2) /* DJGPP 2.0 has _use_lfn() */
# define _use_lfn(f) (0) /* long file names never available */
@@ -597,7 +597,7 @@ char **__crt0_glob_function(char *arg)
#endif /* MSDOS && (__DJGPP__ || __GO32__) */
-#ifdef WIN32
+#ifdef _WIN32
/*
* Function to find CACert bundle on a Win32 platform using SearchPath.
@@ -714,6 +714,8 @@ static struct TerminalSettings {
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
+bool tool_term_has_bold;
+
static void restore_terminal(void)
{
if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE))
@@ -733,16 +735,23 @@ static BOOL WINAPI signal_handler(DWORD type)
static void init_terminal(void)
{
TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+
/*
* Enable VT (Virtual Terminal) output.
* Note: VT mode flag can be set on any version of Windows, but VT
- * processing only performed on Win10 >= Creators Update)
+ * processing only performed on Win10 >= version 1709 (OS build 16299)
+ * Creator's Update. Also, ANSI bold on/off supported since then.
*/
- if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE) &&
- GetConsoleMode(TerminalSettings.hStdOut,
- &TerminalSettings.dwOutputMode) &&
- !(TerminalSettings.dwOutputMode &
- ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
+ if(TerminalSettings.hStdOut == INVALID_HANDLE_VALUE ||
+ !GetConsoleMode(TerminalSettings.hStdOut,
+ &TerminalSettings.dwOutputMode) ||
+ !curlx_verify_windows_version(10, 0, 16299, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL))
+ return;
+
+ if((TerminalSettings.dwOutputMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
+ tool_term_has_bold = true;
+ else {
/* The signal handler is set before attempting to change the console mode
because otherwise a signal would not be caught after the change but
before the handler was installed. */
@@ -751,6 +760,7 @@ static void init_terminal(void)
if(SetConsoleMode(TerminalSettings.hStdOut,
(TerminalSettings.dwOutputMode |
ENABLE_VIRTUAL_TERMINAL_PROCESSING))) {
+ tool_term_has_bold = true;
atexit(restore_terminal);
}
else {
@@ -781,6 +791,6 @@ CURLcode win32_init(void)
return CURLE_OK;
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
-#endif /* MSDOS || WIN32 */
+#endif /* _WIN32 || MSDOS */
diff --git a/src/tool_doswin.h b/src/tool_doswin.h
index 669fdb6ed..e07d89d95 100644
--- a/src/tool_doswin.h
+++ b/src/tool_doswin.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "tool_setup.h"
-#if defined(MSDOS) || defined(WIN32)
+#if defined(_WIN32) || defined(MSDOS)
#define SANITIZE_ALLOW_COLONS (1<<0) /* Allow colons */
#define SANITIZE_ALLOW_PATH (1<<1) /* Allow path separators and colons */
@@ -57,7 +57,7 @@ char **__crt0_glob_function(char *arg);
#endif /* MSDOS && (__DJGPP__ || __GO32__) */
-#ifdef WIN32
+#ifdef _WIN32
CURLcode FindWin32CACert(struct OperationConfig *config,
curl_sslbackend backend,
@@ -65,8 +65,8 @@ CURLcode FindWin32CACert(struct OperationConfig *config,
struct curl_slist *GetLoadedModulePaths(void);
CURLcode win32_init(void);
-#endif /* WIN32 */
+#endif /* _WIN32 */
-#endif /* MSDOS || WIN32 */
+#endif /* _WIN32 || MSDOS */
#endif /* HEADER_CURL_TOOL_DOSWIN_H */
diff --git a/src/tool_easysrc.h b/src/tool_easysrc.h
index 8c8d13150..f698c8f5c 100644
--- a/src/tool_easysrc.h
+++ b/src/tool_easysrc.h
@@ -40,7 +40,7 @@ extern int easysrc_slist_count; /* Number of curl_slist variables */
extern CURLcode easysrc_init(void);
extern CURLcode easysrc_add(struct slist_wc **plist, const char *bupf);
extern CURLcode easysrc_addf(struct slist_wc **plist,
- const char *fmt, ...);
+ const char *fmt, ...) CURL_PRINTF(2, 3);
extern CURLcode easysrc_perform(void);
extern CURLcode easysrc_cleanup(void);
diff --git a/src/tool_filetime.c b/src/tool_filetime.c
index 9c2e80429..13113886e 100644
--- a/src/tool_filetime.c
+++ b/src/tool_filetime.c
@@ -41,7 +41,7 @@ int getfiletime(const char *filename, struct GlobalConfig *global,
/* Windows stat() may attempt to adjust the unix GMT file time by a daylight
saving time offset and since it's GMT that is bad behavior. When we have
access to a 64-bit type we can bypass stat and get the times directly. */
-#if defined(WIN32)
+#if defined(_WIN32)
HANDLE hfile;
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
@@ -87,7 +87,7 @@ int getfiletime(const char *filename, struct GlobalConfig *global,
return rc;
}
-#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || defined(WIN32)
+#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || defined(_WIN32)
void setfiletime(curl_off_t filetime, const char *filename,
struct GlobalConfig *global)
{
@@ -95,7 +95,7 @@ void setfiletime(curl_off_t filetime, const char *filename,
/* Windows utime() may attempt to adjust the unix GMT file time by a daylight
saving time offset and since it's GMT that is bad behavior. When we have
access to a 64-bit type we can bypass utime and set the times directly. */
-#if defined(WIN32)
+#if defined(_WIN32)
HANDLE hfile;
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
@@ -153,4 +153,4 @@ void setfiletime(curl_off_t filetime, const char *filename,
}
}
#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
- defined(WIN32) */
+ defined(_WIN32) */
diff --git a/src/tool_filetime.h b/src/tool_filetime.h
index 908b2d72b..205e5cee2 100644
--- a/src/tool_filetime.h
+++ b/src/tool_filetime.h
@@ -31,12 +31,12 @@ int getfiletime(const char *filename, struct GlobalConfig *global,
curl_off_t *stamp);
#if defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
- (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
+ (defined(_WIN32) && (SIZEOF_CURL_OFF_T >= 8))
void setfiletime(curl_off_t filetime, const char *filename,
struct GlobalConfig *global);
#else
#define setfiletime(a,b,c) Curl_nop_stmt
#endif /* defined(HAVE_UTIME) || defined(HAVE_UTIMES) || \
- (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
+ (defined(_WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
#endif /* HEADER_CURL_TOOL_FILETIME_H */
diff --git a/src/tool_findfile.c b/src/tool_findfile.c
index 201d8f0a8..a1544a563 100644
--- a/src/tool_findfile.c
+++ b/src/tool_findfile.c
@@ -53,7 +53,7 @@ static const struct finder conf_list[] = {
{ "CURL_HOME", NULL, FALSE },
{ "XDG_CONFIG_HOME", NULL, FALSE }, /* index == 1, used in the code */
{ "HOME", NULL, FALSE },
-#ifdef WIN32
+#ifdef _WIN32
{ "USERPROFILE", NULL, FALSE },
{ "APPDATA", NULL, FALSE },
{ "USERPROFILE", "\\Application Data", FALSE},
diff --git a/src/tool_findfile.h b/src/tool_findfile.h
index faafd71cb..63d25195f 100644
--- a/src/tool_findfile.h
+++ b/src/tool_findfile.h
@@ -25,7 +25,7 @@
***************************************************************************/
#include "tool_setup.h"
-#ifdef WIN32
+#ifdef _WIN32
#define CURLRC_DOTSCORE 2 /* look for underscore-prefixed name too */
#else
#define CURLRC_DOTSCORE 1 /* regular .curlrc check */
diff --git a/src/tool_formparse.c b/src/tool_formparse.c
index fa38698d5..875ce78d6 100644
--- a/src/tool_formparse.c
+++ b/src/tool_formparse.c
@@ -278,7 +278,7 @@ static CURLcode tool2curlparts(CURL *curl, struct tool_mime *m,
case TOOLMIME_STDIN:
if(!filename)
filename = "-";
- /* FALLTHROUGH */
+ FALLTHROUGH();
case TOOLMIME_STDINDATA:
ret = curl_mime_data_cb(part, m->size,
(curl_read_callback) tool_mime_stdin_read,
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index d9772a309..4c910fd73 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -51,315 +51,578 @@
# define USE_WATT32
#endif
-#define GetStr(str,val) do { \
- if(*(str)) { \
- free(*(str)); \
- *(str) = NULL; \
- } \
- if((val)) { \
- *(str) = strdup((val)); \
- if(!(*(str))) { \
- err = PARAM_NO_MEM; \
- goto error; \
- } \
- } \
- } while(0)
+#define ALLOW_BLANK TRUE
+#define DENY_BLANK FALSE
+
+static ParameterError getstr(char **str, const char *val, bool allowblank)
+{
+ if(*str) {
+ free(*str);
+ *str = NULL;
+ }
+ if(val) {
+ if(!allowblank && !val[0])
+ return PARAM_BLANK_STRING;
+
+ *str = strdup(val);
+ if(!*str)
+ return PARAM_NO_MEM;
+ }
+ return PARAM_OK;
+}
+
+/* one enum for every command line option. The name is the verbatim long
+ option name, but in uppercase with periods and minuses replaced with
+ underscores using a "C_" prefix. */
+typedef enum {
+ C_ABSTRACT_UNIX_SOCKET,
+ C_ALPN,
+ C_ALT_SVC,
+ C_ANYAUTH,
+ C_APPEND,
+ C_AWS_SIGV4,
+ C_BASIC,
+ C_BUFFER,
+ C_CA_NATIVE,
+ C_CACERT,
+ C_CAPATH,
+ C_CERT,
+ C_CERT_STATUS,
+ C_CERT_TYPE,
+ C_CIPHERS,
+ C_CLOBBER,
+ C_COMPRESSED,
+ C_COMPRESSED_SSH,
+ C_CONFIG,
+ C_CONNECT_TIMEOUT,
+ C_CONNECT_TO,
+ C_CONTINUE_AT,
+ C_COOKIE,
+ C_COOKIE_JAR,
+ C_CREATE_DIRS,
+ C_CREATE_FILE_MODE,
+ C_CRLF,
+ C_CRLFILE,
+ C_CURVES,
+ C_DATA,
+ C_DATA_ASCII,
+ C_DATA_BINARY,
+ C_DATA_RAW,
+ C_DATA_URLENCODE,
+ C_DELEGATION,
+ C_DIGEST,
+ C_DISABLE,
+ C_DISABLE_EPRT,
+ C_DISABLE_EPSV,
+ C_DISALLOW_USERNAME_IN_URL,
+ C_DNS_INTERFACE,
+ C_DNS_IPV4_ADDR,
+ C_DNS_IPV6_ADDR,
+ C_DNS_SERVERS,
+ C_DOH_CERT_STATUS,
+ C_DOH_INSECURE,
+ C_DOH_URL,
+ C_DUMP_HEADER,
+ C_EGD_FILE,
+ C_ENGINE,
+ C_EPRT,
+ C_EPSV,
+ C_ETAG_COMPARE,
+ C_ETAG_SAVE,
+ C_EXPECT100_TIMEOUT,
+ C_FAIL,
+ C_FAIL_EARLY,
+ C_FAIL_WITH_BODY,
+ C_FALSE_START,
+ C_FORM,
+ C_FORM_ESCAPE,
+ C_FORM_STRING,
+ C_FTP_ACCOUNT,
+ C_FTP_ALTERNATIVE_TO_USER,
+ C_FTP_CREATE_DIRS,
+ C_FTP_METHOD,
+ C_FTP_PASV,
+ C_FTP_PORT,
+ C_FTP_PRET,
+ C_FTP_SKIP_PASV_IP,
+ C_FTP_SSL,
+ C_FTP_SSL_CCC,
+ C_FTP_SSL_CCC_MODE,
+ C_FTP_SSL_CONTROL,
+ C_FTP_SSL_REQD,
+ C_GET,
+ C_GLOBOFF,
+ C_HAPPY_EYEBALLS_TIMEOUT_MS,
+ C_HAPROXY_CLIENTIP,
+ C_HAPROXY_PROTOCOL,
+ C_HEAD,
+ C_HEADER,
+ C_HELP,
+ C_HOSTPUBMD5,
+ C_HOSTPUBSHA256,
+ C_HSTS,
+ C_HTTP0_9,
+ C_HTTP1_0,
+ C_HTTP1_1,
+ C_HTTP2,
+ C_HTTP2_PRIOR_KNOWLEDGE,
+ C_HTTP3,
+ C_HTTP3_ONLY,
+ C_IGNORE_CONTENT_LENGTH,
+ C_INCLUDE,
+ C_INSECURE,
+ C_INTERFACE,
+ C_IPFS_GATEWAY,
+ C_IPV4,
+ C_IPV6,
+ C_JSON,
+ C_JUNK_SESSION_COOKIES,
+ C_KEEPALIVE,
+ C_KEEPALIVE_TIME,
+ C_KEY,
+ C_KEY_TYPE,
+ C_KRB,
+ C_KRB4,
+ C_LIBCURL,
+ C_LIMIT_RATE,
+ C_LIST_ONLY,
+ C_LOCAL_PORT,
+ C_LOCATION,
+ C_LOCATION_TRUSTED,
+ C_LOGIN_OPTIONS,
+ C_MAIL_AUTH,
+ C_MAIL_FROM,
+ C_MAIL_RCPT,
+ C_MAIL_RCPT_ALLOWFAILS,
+ C_MANUAL,
+ C_MAX_FILESIZE,
+ C_MAX_REDIRS,
+ C_MAX_TIME,
+ C_METALINK,
+ C_NEGOTIATE,
+ C_NETRC,
+ C_NETRC_FILE,
+ C_NETRC_OPTIONAL,
+ C_NEXT,
+ C_NOPROXY,
+ C_NPN,
+ C_NTLM,
+ C_NTLM_WB,
+ C_OAUTH2_BEARER,
+ C_OUTPUT,
+ C_OUTPUT_DIR,
+ C_PARALLEL,
+ C_PARALLEL_IMMEDIATE,
+ C_PARALLEL_MAX,
+ C_PASS,
+ C_PATH_AS_IS,
+ C_PINNEDPUBKEY,
+ C_POST301,
+ C_POST302,
+ C_POST303,
+ C_PREPROXY,
+ C_PROGRESS_BAR,
+ C_PROGRESS_METER,
+ C_PROTO,
+ C_PROTO_DEFAULT,
+ C_PROTO_REDIR,
+ C_PROXY,
+ C_PROXY_ANYAUTH,
+ C_PROXY_BASIC,
+ C_PROXY_CA_NATIVE,
+ C_PROXY_CACERT,
+ C_PROXY_CAPATH,
+ C_PROXY_CERT,
+ C_PROXY_CERT_TYPE,
+ C_PROXY_CIPHERS,
+ C_PROXY_CRLFILE,
+ C_PROXY_DIGEST,
+ C_PROXY_HEADER,
+ C_PROXY_HTTP2,
+ C_PROXY_INSECURE,
+ C_PROXY_KEY,
+ C_PROXY_KEY_TYPE,
+ C_PROXY_NEGOTIATE,
+ C_PROXY_NTLM,
+ C_PROXY_PASS,
+ C_PROXY_PINNEDPUBKEY,
+ C_PROXY_SERVICE_NAME,
+ C_PROXY_SSL_ALLOW_BEAST,
+ C_PROXY_SSL_AUTO_CLIENT_CERT,
+ C_PROXY_TLS13_CIPHERS,
+ C_PROXY_TLSAUTHTYPE,
+ C_PROXY_TLSPASSWORD,
+ C_PROXY_TLSUSER,
+ C_PROXY_TLSV1,
+ C_PROXY_USER,
+ C_PROXY1_0,
+ C_PROXYTUNNEL,
+ C_PUBKEY,
+ C_QUOTE,
+ C_RANDOM_FILE,
+ C_RANGE,
+ C_RATE,
+ C_RAW,
+ C_REFERER,
+ C_REMOTE_HEADER_NAME,
+ C_REMOTE_NAME,
+ C_REMOTE_NAME_ALL,
+ C_REMOTE_TIME,
+ C_REMOVE_ON_ERROR,
+ C_REQUEST,
+ C_REQUEST_TARGET,
+ C_RESOLVE,
+ C_RETRY,
+ C_RETRY_ALL_ERRORS,
+ C_RETRY_CONNREFUSED,
+ C_RETRY_DELAY,
+ C_RETRY_MAX_TIME,
+ C_SASL_AUTHZID,
+ C_SASL_IR,
+ C_SERVICE_NAME,
+ C_SESSIONID,
+ C_SHOW_ERROR,
+ C_SILENT,
+ C_SOCKS4,
+ C_SOCKS4A,
+ C_SOCKS5,
+ C_SOCKS5_BASIC,
+ C_SOCKS5_GSSAPI,
+ C_SOCKS5_GSSAPI_NEC,
+ C_SOCKS5_GSSAPI_SERVICE,
+ C_SOCKS5_HOSTNAME,
+ C_SPEED_LIMIT,
+ C_SPEED_TIME,
+ C_SSL,
+ C_SSL_ALLOW_BEAST,
+ C_SSL_AUTO_CLIENT_CERT,
+ C_SSL_NO_REVOKE,
+ C_SSL_REQD,
+ C_SSL_REVOKE_BEST_EFFORT,
+ C_SSLV2,
+ C_SSLV3,
+ C_STDERR,
+ C_STYLED_OUTPUT,
+ C_SUPPRESS_CONNECT_HEADERS,
+ C_TCP_FASTOPEN,
+ C_TCP_NODELAY,
+ C_TELNET_OPTION,
+ C_TEST_EVENT,
+ C_TFTP_BLKSIZE,
+ C_TFTP_NO_OPTIONS,
+ C_TIME_COND,
+ C_TLS_MAX,
+ C_TLS13_CIPHERS,
+ C_TLSAUTHTYPE,
+ C_TLSPASSWORD,
+ C_TLSUSER,
+ C_TLSV1,
+ C_TLSV1_0,
+ C_TLSV1_1,
+ C_TLSV1_2,
+ C_TLSV1_3,
+ C_TR_ENCODING,
+ C_TRACE,
+ C_TRACE_ASCII,
+ C_TRACE_CONFIG,
+ C_TRACE_IDS,
+ C_TRACE_TIME,
+ C_UNIX_SOCKET,
+ C_UPLOAD_FILE,
+ C_URL,
+ C_URL_QUERY,
+ C_USE_ASCII,
+ C_USER,
+ C_USER_AGENT,
+ C_VARIABLE,
+ C_VERBOSE,
+ C_VERSION,
+ C_WDEBUG,
+ C_WRITE_OUT,
+ C_XATTR
+} cmdline_t;
struct LongShort {
- const char *letter; /* short name option */
const char *lname; /* long name option */
enum {
- ARG_NONE, /* stand-alone but not a boolean */
- ARG_BOOL, /* accepts a --no-[name] prefix */
- ARG_STRING, /* requires an argument */
- ARG_FILENAME /* requires an argument, usually a file name */
+ ARG_NONE, /* stand-alone but not a boolean */
+ ARG_BOOL, /* accepts a --no-[name] prefix */
+ ARG_STRG, /* requires an argument */
+ ARG_FILE /* requires an argument, usually a file name */
} desc;
+ char letter; /* short name option or ' ' */
+ cmdline_t cmd;
};
+/* this array MUST be alphasorted based on the 'lname' */
static const struct LongShort aliases[]= {
- /* 'letter' strings with more than one character have *no* short option to
- mention. */
- {"*@", "url", ARG_STRING},
- {"*4", "dns-ipv4-addr", ARG_STRING},
- {"*6", "dns-ipv6-addr", ARG_STRING},
- {"*a", "random-file", ARG_FILENAME},
- {"*b", "egd-file", ARG_STRING},
- {"*B", "oauth2-bearer", ARG_STRING},
- {"*c", "connect-timeout", ARG_STRING},
- {"*C", "doh-url" , ARG_STRING},
- {"*d", "ciphers", ARG_STRING},
- {"*D", "dns-interface", ARG_STRING},
- {"*e", "disable-epsv", ARG_BOOL},
- {"*f", "disallow-username-in-url", ARG_BOOL},
- {"*E", "epsv", ARG_BOOL},
- /* 'epsv' made like this to make --no-epsv and --epsv to work
- although --disable-epsv is the documented option */
- {"*F", "dns-servers", ARG_STRING},
- {"*g", "trace", ARG_FILENAME},
- {"*G", "npn", ARG_BOOL},
- {"*h", "trace-ascii", ARG_FILENAME},
- {"*H", "alpn", ARG_BOOL},
- {"*i", "limit-rate", ARG_STRING},
- {"*I", "rate", ARG_STRING},
- {"*j", "compressed", ARG_BOOL},
- {"*J", "tr-encoding", ARG_BOOL},
- {"*k", "digest", ARG_BOOL},
- {"*l", "negotiate", ARG_BOOL},
- {"*m", "ntlm", ARG_BOOL},
- {"*M", "ntlm-wb", ARG_BOOL},
- {"*n", "basic", ARG_BOOL},
- {"*o", "anyauth", ARG_BOOL},
+ {"abstract-unix-socket", ARG_FILE, ' ', C_ABSTRACT_UNIX_SOCKET},
+ {"alpn", ARG_BOOL, ' ', C_ALPN},
+ {"alt-svc", ARG_STRG, ' ', C_ALT_SVC},
+ {"anyauth", ARG_BOOL, ' ', C_ANYAUTH},
+ {"append", ARG_BOOL, 'a', C_APPEND},
+ {"aws-sigv4", ARG_STRG, ' ', C_AWS_SIGV4},
+ {"basic", ARG_BOOL, ' ', C_BASIC},
+ {"buffer", ARG_BOOL, 'N', C_BUFFER},
+ {"ca-native", ARG_BOOL, ' ', C_CA_NATIVE},
+ {"cacert", ARG_FILE, ' ', C_CACERT},
+ {"capath", ARG_FILE, ' ', C_CAPATH},
+ {"cert", ARG_FILE, 'E', C_CERT},
+ {"cert-status", ARG_BOOL, ' ', C_CERT_STATUS},
+ {"cert-type", ARG_STRG, ' ', C_CERT_TYPE},
+ {"ciphers", ARG_STRG, ' ', C_CIPHERS},
+ {"clobber", ARG_BOOL, ' ', C_CLOBBER},
+ {"compressed", ARG_BOOL, ' ', C_COMPRESSED},
+ {"compressed-ssh", ARG_BOOL, ' ', C_COMPRESSED_SSH},
+ {"config", ARG_FILE, 'K', C_CONFIG},
+ {"connect-timeout", ARG_STRG, ' ', C_CONNECT_TIMEOUT},
+ {"connect-to", ARG_STRG, ' ', C_CONNECT_TO},
+ {"continue-at", ARG_STRG, 'C', C_CONTINUE_AT},
+ {"cookie", ARG_STRG, 'b', C_COOKIE},
+ {"cookie-jar", ARG_STRG, 'c', C_COOKIE_JAR},
+ {"create-dirs", ARG_BOOL, ' ', C_CREATE_DIRS},
+ {"create-file-mode", ARG_STRG, ' ', C_CREATE_FILE_MODE},
+ {"crlf", ARG_BOOL, ' ', C_CRLF},
+ {"crlfile", ARG_FILE, ' ', C_CRLFILE},
+ {"curves", ARG_STRG, ' ', C_CURVES},
+ {"data", ARG_STRG, 'd', C_DATA},
+ {"data-ascii", ARG_STRG, ' ', C_DATA_ASCII},
+ {"data-binary", ARG_STRG, ' ', C_DATA_BINARY},
+ {"data-raw", ARG_STRG, ' ', C_DATA_RAW},
+ {"data-urlencode", ARG_STRG, ' ', C_DATA_URLENCODE},
+ {"delegation", ARG_STRG, ' ', C_DELEGATION},
+ {"digest", ARG_BOOL, ' ', C_DIGEST},
+ {"disable", ARG_BOOL, 'q', C_DISABLE},
+ {"disable-eprt", ARG_BOOL, ' ', C_DISABLE_EPRT},
+ {"disable-epsv", ARG_BOOL, ' ', C_DISABLE_EPSV},
+ {"disallow-username-in-url", ARG_BOOL, ' ', C_DISALLOW_USERNAME_IN_URL},
+ {"dns-interface", ARG_STRG, ' ', C_DNS_INTERFACE},
+ {"dns-ipv4-addr", ARG_STRG, ' ', C_DNS_IPV4_ADDR},
+ {"dns-ipv6-addr", ARG_STRG, ' ', C_DNS_IPV6_ADDR},
+ {"dns-servers", ARG_STRG, ' ', C_DNS_SERVERS},
+ {"doh-cert-status", ARG_BOOL, ' ', C_DOH_CERT_STATUS},
+ {"doh-insecure", ARG_BOOL, ' ', C_DOH_INSECURE},
+ {"doh-url" , ARG_STRG, ' ', C_DOH_URL},
+ {"dump-header", ARG_FILE, 'D', C_DUMP_HEADER},
+ {"egd-file", ARG_STRG, ' ', C_EGD_FILE},
+ {"engine", ARG_STRG, ' ', C_ENGINE},
+ {"eprt", ARG_BOOL, ' ', C_EPRT},
+ {"epsv", ARG_BOOL, ' ', C_EPSV},
+ {"etag-compare", ARG_FILE, ' ', C_ETAG_COMPARE},
+ {"etag-save", ARG_FILE, ' ', C_ETAG_SAVE},
+ {"expect100-timeout", ARG_STRG, ' ', C_EXPECT100_TIMEOUT},
+ {"fail", ARG_BOOL, 'f', C_FAIL},
+ {"fail-early", ARG_BOOL, ' ', C_FAIL_EARLY},
+ {"fail-with-body", ARG_BOOL, ' ', C_FAIL_WITH_BODY},
+ {"false-start", ARG_BOOL, ' ', C_FALSE_START},
+ {"form", ARG_STRG, 'F', C_FORM},
+ {"form-escape", ARG_BOOL, ' ', C_FORM_ESCAPE},
+ {"form-string", ARG_STRG, ' ', C_FORM_STRING},
+ {"ftp-account", ARG_STRG, ' ', C_FTP_ACCOUNT},
+ {"ftp-alternative-to-user", ARG_STRG, ' ', C_FTP_ALTERNATIVE_TO_USER},
+ {"ftp-create-dirs", ARG_BOOL, ' ', C_FTP_CREATE_DIRS},
+ {"ftp-method", ARG_STRG, ' ', C_FTP_METHOD},
+ {"ftp-pasv", ARG_BOOL, ' ', C_FTP_PASV},
+ {"ftp-port", ARG_STRG, 'P', C_FTP_PORT},
+ {"ftp-pret", ARG_BOOL, ' ', C_FTP_PRET},
+ {"ftp-skip-pasv-ip", ARG_BOOL, ' ', C_FTP_SKIP_PASV_IP},
+ {"ftp-ssl", ARG_BOOL, ' ', C_FTP_SSL},
+ {"ftp-ssl-ccc", ARG_BOOL, ' ', C_FTP_SSL_CCC},
+ {"ftp-ssl-ccc-mode", ARG_STRG, ' ', C_FTP_SSL_CCC_MODE},
+ {"ftp-ssl-control", ARG_BOOL, ' ', C_FTP_SSL_CONTROL},
+ {"ftp-ssl-reqd", ARG_BOOL, ' ', C_FTP_SSL_REQD},
+ {"get", ARG_BOOL, 'G', C_GET},
+ {"globoff", ARG_BOOL, 'g', C_GLOBOFF},
+ {"happy-eyeballs-timeout-ms", ARG_STRG, ' ', C_HAPPY_EYEBALLS_TIMEOUT_MS},
+ {"haproxy-clientip", ARG_STRG, ' ', C_HAPROXY_CLIENTIP},
+ {"haproxy-protocol", ARG_BOOL, ' ', C_HAPROXY_PROTOCOL},
+ {"head", ARG_BOOL, 'I', C_HEAD},
+ {"header", ARG_STRG, 'H', C_HEADER},
+ {"help", ARG_BOOL, 'h', C_HELP},
+ {"hostpubmd5", ARG_STRG, ' ', C_HOSTPUBMD5},
+ {"hostpubsha256", ARG_STRG, ' ', C_HOSTPUBSHA256},
+ {"hsts", ARG_STRG, ' ', C_HSTS},
+ {"http0.9", ARG_BOOL, ' ', C_HTTP0_9},
+ {"http1.0", ARG_NONE, '0', C_HTTP1_0},
+ {"http1.1", ARG_NONE, ' ', C_HTTP1_1},
+ {"http2", ARG_NONE, ' ', C_HTTP2},
+ {"http2-prior-knowledge", ARG_NONE, ' ', C_HTTP2_PRIOR_KNOWLEDGE},
+ {"http3", ARG_NONE, ' ', C_HTTP3},
+ {"http3-only", ARG_NONE, ' ', C_HTTP3_ONLY},
+ {"ignore-content-length", ARG_BOOL, ' ', C_IGNORE_CONTENT_LENGTH},
+ {"include", ARG_BOOL, 'i', C_INCLUDE},
+ {"insecure", ARG_BOOL, 'k', C_INSECURE},
+ {"interface", ARG_STRG, ' ', C_INTERFACE},
+ {"ipfs-gateway", ARG_STRG, ' ', C_IPFS_GATEWAY},
+ {"ipv4", ARG_NONE, '4', C_IPV4},
+ {"ipv6", ARG_NONE, '6', C_IPV6},
+ {"json", ARG_STRG, ' ', C_JSON},
+ {"junk-session-cookies", ARG_BOOL, 'j', C_JUNK_SESSION_COOKIES},
+ {"keepalive", ARG_BOOL, ' ', C_KEEPALIVE},
+ {"keepalive-time", ARG_STRG, ' ', C_KEEPALIVE_TIME},
+ {"key", ARG_FILE, ' ', C_KEY},
+ {"key-type", ARG_STRG, ' ', C_KEY_TYPE},
+ {"krb", ARG_STRG, ' ', C_KRB},
+ {"krb4", ARG_STRG, ' ', C_KRB4},
+ {"libcurl", ARG_STRG, ' ', C_LIBCURL},
+ {"limit-rate", ARG_STRG, ' ', C_LIMIT_RATE},
+ {"list-only", ARG_BOOL, 'l', C_LIST_ONLY},
+ {"local-port", ARG_STRG, ' ', C_LOCAL_PORT},
+ {"location", ARG_BOOL, 'L', C_LOCATION},
+ {"location-trusted", ARG_BOOL, ' ', C_LOCATION_TRUSTED},
+ {"login-options", ARG_STRG, ' ', C_LOGIN_OPTIONS},
+ {"mail-auth", ARG_STRG, ' ', C_MAIL_AUTH},
+ {"mail-from", ARG_STRG, ' ', C_MAIL_FROM},
+ {"mail-rcpt", ARG_STRG, ' ', C_MAIL_RCPT},
+ {"mail-rcpt-allowfails", ARG_BOOL, ' ', C_MAIL_RCPT_ALLOWFAILS},
+ {"manual", ARG_BOOL, 'M', C_MANUAL},
+ {"max-filesize", ARG_STRG, ' ', C_MAX_FILESIZE},
+ {"max-redirs", ARG_STRG, ' ', C_MAX_REDIRS},
+ {"max-time", ARG_STRG, 'm', C_MAX_TIME},
+ {"metalink", ARG_BOOL, ' ', C_METALINK},
+ {"negotiate", ARG_BOOL, ' ', C_NEGOTIATE},
+ {"netrc", ARG_BOOL, 'n', C_NETRC},
+ {"netrc-file", ARG_FILE, ' ', C_NETRC_FILE},
+ {"netrc-optional", ARG_BOOL, ' ', C_NETRC_OPTIONAL},
+ {"next", ARG_NONE, ':', C_NEXT},
+ {"noproxy", ARG_STRG, ' ', C_NOPROXY},
+ {"npn", ARG_BOOL, ' ', C_NPN},
+ {"ntlm", ARG_BOOL, ' ', C_NTLM},
+ {"ntlm-wb", ARG_BOOL, ' ', C_NTLM_WB},
+ {"oauth2-bearer", ARG_STRG, ' ', C_OAUTH2_BEARER},
+ {"output", ARG_FILE, 'o', C_OUTPUT},
+ {"output-dir", ARG_STRG, ' ', C_OUTPUT_DIR},
+ {"parallel", ARG_BOOL, 'Z', C_PARALLEL},
+ {"parallel-immediate", ARG_BOOL, ' ', C_PARALLEL_IMMEDIATE},
+ {"parallel-max", ARG_STRG, ' ', C_PARALLEL_MAX},
+ {"pass", ARG_STRG, ' ', C_PASS},
+ {"path-as-is", ARG_BOOL, ' ', C_PATH_AS_IS},
+ {"pinnedpubkey", ARG_STRG, ' ', C_PINNEDPUBKEY},
+ {"post301", ARG_BOOL, ' ', C_POST301},
+ {"post302", ARG_BOOL, ' ', C_POST302},
+ {"post303", ARG_BOOL, ' ', C_POST303},
+ {"preproxy", ARG_STRG, ' ', C_PREPROXY},
+ {"progress-bar", ARG_BOOL, '#', C_PROGRESS_BAR},
+ {"progress-meter", ARG_BOOL, ' ', C_PROGRESS_METER},
+ {"proto", ARG_STRG, ' ', C_PROTO},
+ {"proto-default", ARG_STRG, ' ', C_PROTO_DEFAULT},
+ {"proto-redir", ARG_STRG, ' ', C_PROTO_REDIR},
+ {"proxy", ARG_STRG, 'x', C_PROXY},
+ {"proxy-anyauth", ARG_BOOL, ' ', C_PROXY_ANYAUTH},
+ {"proxy-basic", ARG_BOOL, ' ', C_PROXY_BASIC},
+ {"proxy-ca-native", ARG_BOOL, ' ', C_PROXY_CA_NATIVE},
+ {"proxy-cacert", ARG_FILE, ' ', C_PROXY_CACERT},
+ {"proxy-capath", ARG_FILE, ' ', C_PROXY_CAPATH},
+ {"proxy-cert", ARG_FILE, ' ', C_PROXY_CERT},
+ {"proxy-cert-type", ARG_STRG, ' ', C_PROXY_CERT_TYPE},
+ {"proxy-ciphers", ARG_STRG, ' ', C_PROXY_CIPHERS},
+ {"proxy-crlfile", ARG_FILE, ' ', C_PROXY_CRLFILE},
+ {"proxy-digest", ARG_BOOL, ' ', C_PROXY_DIGEST},
+ {"proxy-header", ARG_STRG, ' ', C_PROXY_HEADER},
+ {"proxy-http2", ARG_BOOL, ' ', C_PROXY_HTTP2},
+ {"proxy-insecure", ARG_BOOL, ' ', C_PROXY_INSECURE},
+ {"proxy-key", ARG_FILE, ' ', C_PROXY_KEY},
+ {"proxy-key-type", ARG_STRG, ' ', C_PROXY_KEY_TYPE},
+ {"proxy-negotiate", ARG_BOOL, ' ', C_PROXY_NEGOTIATE},
+ {"proxy-ntlm", ARG_BOOL, ' ', C_PROXY_NTLM},
+ {"proxy-pass", ARG_STRG, ' ', C_PROXY_PASS},
+ {"proxy-pinnedpubkey", ARG_STRG, ' ', C_PROXY_PINNEDPUBKEY},
+ {"proxy-service-name", ARG_STRG, ' ', C_PROXY_SERVICE_NAME},
+ {"proxy-ssl-allow-beast", ARG_BOOL, ' ', C_PROXY_SSL_ALLOW_BEAST},
+ {"proxy-ssl-auto-client-cert", ARG_BOOL, ' ', C_PROXY_SSL_AUTO_CLIENT_CERT},
+ {"proxy-tls13-ciphers", ARG_STRG, ' ', C_PROXY_TLS13_CIPHERS},
+ {"proxy-tlsauthtype", ARG_STRG, ' ', C_PROXY_TLSAUTHTYPE},
+ {"proxy-tlspassword", ARG_STRG, ' ', C_PROXY_TLSPASSWORD},
+ {"proxy-tlsuser", ARG_STRG, ' ', C_PROXY_TLSUSER},
+ {"proxy-tlsv1", ARG_NONE, ' ', C_PROXY_TLSV1},
+ {"proxy-user", ARG_STRG, 'U', C_PROXY_USER},
+ {"proxy1.0", ARG_STRG, ' ', C_PROXY1_0},
+ {"proxytunnel", ARG_BOOL, 'p', C_PROXYTUNNEL},
+ {"pubkey", ARG_STRG, ' ', C_PUBKEY},
+ {"quote", ARG_STRG, 'Q', C_QUOTE},
+ {"random-file", ARG_FILE, ' ', C_RANDOM_FILE},
+ {"range", ARG_STRG, 'r', C_RANGE},
+ {"rate", ARG_STRG, ' ', C_RATE},
+ {"raw", ARG_BOOL, ' ', C_RAW},
+ {"referer", ARG_STRG, 'e', C_REFERER},
+ {"remote-header-name", ARG_BOOL, 'J', C_REMOTE_HEADER_NAME},
+ {"remote-name", ARG_BOOL, 'O', C_REMOTE_NAME},
+ {"remote-name-all", ARG_BOOL, ' ', C_REMOTE_NAME_ALL},
+ {"remote-time", ARG_BOOL, 'R', C_REMOTE_TIME},
+ {"remove-on-error", ARG_BOOL, ' ', C_REMOVE_ON_ERROR},
+ {"request", ARG_STRG, 'X', C_REQUEST},
+ {"request-target", ARG_STRG, ' ', C_REQUEST_TARGET},
+ {"resolve", ARG_STRG, ' ', C_RESOLVE},
+ {"retry", ARG_STRG, ' ', C_RETRY},
+ {"retry-all-errors", ARG_BOOL, ' ', C_RETRY_ALL_ERRORS},
+ {"retry-connrefused", ARG_BOOL, ' ', C_RETRY_CONNREFUSED},
+ {"retry-delay", ARG_STRG, ' ', C_RETRY_DELAY},
+ {"retry-max-time", ARG_STRG, ' ', C_RETRY_MAX_TIME},
+ {"sasl-authzid", ARG_STRG, ' ', C_SASL_AUTHZID},
+ {"sasl-ir", ARG_BOOL, ' ', C_SASL_IR},
+ {"service-name", ARG_STRG, ' ', C_SERVICE_NAME},
+ {"sessionid", ARG_BOOL, ' ', C_SESSIONID},
+ {"show-error", ARG_BOOL, 'S', C_SHOW_ERROR},
+ {"silent", ARG_BOOL, 's', C_SILENT},
+ {"socks4", ARG_STRG, ' ', C_SOCKS4},
+ {"socks4a", ARG_STRG, ' ', C_SOCKS4A},
+ {"socks5", ARG_STRG, ' ', C_SOCKS5},
+ {"socks5-basic", ARG_BOOL, ' ', C_SOCKS5_BASIC},
+ {"socks5-gssapi", ARG_BOOL, ' ', C_SOCKS5_GSSAPI},
+ {"socks5-gssapi-nec", ARG_BOOL, ' ', C_SOCKS5_GSSAPI_NEC},
+ {"socks5-gssapi-service", ARG_STRG, ' ', C_SOCKS5_GSSAPI_SERVICE},
+ {"socks5-hostname", ARG_STRG, ' ', C_SOCKS5_HOSTNAME},
+ {"speed-limit", ARG_STRG, 'Y', C_SPEED_LIMIT},
+ {"speed-time", ARG_STRG, 'y', C_SPEED_TIME},
+ {"ssl", ARG_BOOL, ' ', C_SSL},
+ {"ssl-allow-beast", ARG_BOOL, ' ', C_SSL_ALLOW_BEAST},
+ {"ssl-auto-client-cert", ARG_BOOL, ' ', C_SSL_AUTO_CLIENT_CERT},
+ {"ssl-no-revoke", ARG_BOOL, ' ', C_SSL_NO_REVOKE},
+ {"ssl-reqd", ARG_BOOL, ' ', C_SSL_REQD},
+ {"ssl-revoke-best-effort", ARG_BOOL, ' ', C_SSL_REVOKE_BEST_EFFORT},
+ {"sslv2", ARG_NONE, '2', C_SSLV2},
+ {"sslv3", ARG_NONE, '3', C_SSLV3},
+ {"stderr", ARG_FILE, ' ', C_STDERR},
+ {"styled-output", ARG_BOOL, ' ', C_STYLED_OUTPUT},
+ {"suppress-connect-headers", ARG_BOOL, ' ', C_SUPPRESS_CONNECT_HEADERS},
+ {"tcp-fastopen", ARG_BOOL, ' ', C_TCP_FASTOPEN},
+ {"tcp-nodelay", ARG_BOOL, ' ', C_TCP_NODELAY},
+ {"telnet-option", ARG_STRG, 't', C_TELNET_OPTION},
+ {"test-event", ARG_BOOL, ' ', C_TEST_EVENT},
+ {"tftp-blksize", ARG_STRG, ' ', C_TFTP_BLKSIZE},
+ {"tftp-no-options", ARG_BOOL, ' ', C_TFTP_NO_OPTIONS},
+ {"time-cond", ARG_STRG, 'z', C_TIME_COND},
+ {"tls-max", ARG_STRG, ' ', C_TLS_MAX},
+ {"tls13-ciphers", ARG_STRG, ' ', C_TLS13_CIPHERS},
+ {"tlsauthtype", ARG_STRG, ' ', C_TLSAUTHTYPE},
+ {"tlspassword", ARG_STRG, ' ', C_TLSPASSWORD},
+ {"tlsuser", ARG_STRG, ' ', C_TLSUSER},
+ {"tlsv1", ARG_NONE, '1', C_TLSV1},
+ {"tlsv1.0", ARG_NONE, ' ', C_TLSV1_0},
+ {"tlsv1.1", ARG_NONE, ' ', C_TLSV1_1},
+ {"tlsv1.2", ARG_NONE, ' ', C_TLSV1_2},
+ {"tlsv1.3", ARG_NONE, ' ', C_TLSV1_3},
+ {"tr-encoding", ARG_BOOL, ' ', C_TR_ENCODING},
+ {"trace", ARG_FILE, ' ', C_TRACE},
+ {"trace-ascii", ARG_FILE, ' ', C_TRACE_ASCII},
+ {"trace-config", ARG_STRG, ' ', C_TRACE_CONFIG},
+ {"trace-ids", ARG_BOOL, ' ', C_TRACE_IDS},
+ {"trace-time", ARG_BOOL, ' ', C_TRACE_TIME},
+ {"unix-socket", ARG_FILE, ' ', C_UNIX_SOCKET},
+ {"upload-file", ARG_FILE, 'T', C_UPLOAD_FILE},
+ {"url", ARG_STRG, ' ', C_URL},
+ {"url-query", ARG_STRG, ' ', C_URL_QUERY},
+ {"use-ascii", ARG_BOOL, 'B', C_USE_ASCII},
+ {"user", ARG_STRG, 'u', C_USER},
+ {"user-agent", ARG_STRG, 'A', C_USER_AGENT},
+ {"variable", ARG_STRG, ' ', C_VARIABLE},
+ {"verbose", ARG_BOOL, 'v', C_VERBOSE},
+ {"version", ARG_BOOL, 'V', C_VERSION},
#ifdef USE_WATT32
- {"*p", "wdebug", ARG_BOOL},
+ {"wdebug", ARG_BOOL, ' ', C_WDEBUG},
#endif
- {"*q", "ftp-create-dirs", ARG_BOOL},
- {"*r", "create-dirs", ARG_BOOL},
- {"*R", "create-file-mode", ARG_STRING},
- {"*s", "max-redirs", ARG_STRING},
- {"*S", "ipfs-gateway", ARG_STRING},
- {"*t", "proxy-ntlm", ARG_BOOL},
- {"*u", "crlf", ARG_BOOL},
- {"*v", "stderr", ARG_FILENAME},
- {"*V", "aws-sigv4", ARG_STRING},
- {"*w", "interface", ARG_STRING},
- {"*x", "krb", ARG_STRING},
- {"*x", "krb4", ARG_STRING},
- /* 'krb4' is the previous name */
- {"*X", "haproxy-protocol", ARG_BOOL},
- {"*P", "haproxy-clientip", ARG_STRING},
- {"*y", "max-filesize", ARG_STRING},
- {"*z", "disable-eprt", ARG_BOOL},
- {"*Z", "eprt", ARG_BOOL},
- /* 'eprt' made like this to make --no-eprt and --eprt to work
- although --disable-eprt is the documented option */
- {"*~", "xattr", ARG_BOOL},
- {"$a", "ftp-ssl", ARG_BOOL},
- /* 'ftp-ssl' deprecated name since 7.20.0 */
- {"$a", "ssl", ARG_BOOL},
- /* 'ssl' new option name in 7.20.0, previously this was ftp-ssl */
- {"$b", "ftp-pasv", ARG_BOOL},
- {"$c", "socks5", ARG_STRING},
- {"$d", "tcp-nodelay", ARG_BOOL},
- {"$e", "proxy-digest", ARG_BOOL},
- {"$f", "proxy-basic", ARG_BOOL},
- {"$g", "retry", ARG_STRING},
- {"$V", "retry-connrefused", ARG_BOOL},
- {"$h", "retry-delay", ARG_STRING},
- {"$i", "retry-max-time", ARG_STRING},
- {"$k", "proxy-negotiate", ARG_BOOL},
- {"$l", "form-escape", ARG_BOOL},
- {"$m", "ftp-account", ARG_STRING},
- {"$n", "proxy-anyauth", ARG_BOOL},
- {"$o", "trace-time", ARG_BOOL},
- {"$p", "ignore-content-length", ARG_BOOL},
- {"$q", "ftp-skip-pasv-ip", ARG_BOOL},
- {"$r", "ftp-method", ARG_STRING},
- {"$s", "local-port", ARG_STRING},
- {"$t", "socks4", ARG_STRING},
- {"$T", "socks4a", ARG_STRING},
- {"$u", "ftp-alternative-to-user", ARG_STRING},
- {"$v", "ftp-ssl-reqd", ARG_BOOL},
- /* 'ftp-ssl-reqd' deprecated name since 7.20.0 */
- {"$v", "ssl-reqd", ARG_BOOL},
- /* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */
- {"$w", "sessionid", ARG_BOOL},
- /* 'sessionid' listed as --no-sessionid in the help */
- {"$x", "ftp-ssl-control", ARG_BOOL},
- {"$y", "ftp-ssl-ccc", ARG_BOOL},
- {"$j", "ftp-ssl-ccc-mode", ARG_STRING},
- {"$z", "libcurl", ARG_STRING},
- {"$#", "raw", ARG_BOOL},
- {"$0", "post301", ARG_BOOL},
- {"$1", "keepalive", ARG_BOOL},
- /* 'keepalive' listed as --no-keepalive in the help */
- {"$2", "socks5-hostname", ARG_STRING},
- {"$3", "keepalive-time", ARG_STRING},
- {"$4", "post302", ARG_BOOL},
- {"$5", "noproxy", ARG_STRING},
- {"$7", "socks5-gssapi-nec", ARG_BOOL},
- {"$8", "proxy1.0", ARG_STRING},
- {"$9", "tftp-blksize", ARG_STRING},
- {"$A", "mail-from", ARG_STRING},
- {"$B", "mail-rcpt", ARG_STRING},
- {"$C", "ftp-pret", ARG_BOOL},
- {"$D", "proto", ARG_STRING},
- {"$E", "proto-redir", ARG_STRING},
- {"$F", "resolve", ARG_STRING},
- {"$G", "delegation", ARG_STRING},
- {"$H", "mail-auth", ARG_STRING},
- {"$I", "post303", ARG_BOOL},
- {"$J", "metalink", ARG_BOOL},
- {"$6", "sasl-authzid", ARG_STRING},
- {"$K", "sasl-ir", ARG_BOOL },
- {"$L", "test-event", ARG_BOOL},
- {"$M", "unix-socket", ARG_FILENAME},
- {"$N", "path-as-is", ARG_BOOL},
- {"$O", "socks5-gssapi-service", ARG_STRING},
- /* 'socks5-gssapi-service' merged with'proxy-service-name' and
- deprecated since 7.49.0 */
- {"$O", "proxy-service-name", ARG_STRING},
- {"$P", "service-name", ARG_STRING},
- {"$Q", "proto-default", ARG_STRING},
- {"$R", "expect100-timeout", ARG_STRING},
- {"$S", "tftp-no-options", ARG_BOOL},
- {"$U", "connect-to", ARG_STRING},
- {"$W", "abstract-unix-socket", ARG_FILENAME},
- {"$X", "tls-max", ARG_STRING},
- {"$Y", "suppress-connect-headers", ARG_BOOL},
- {"$Z", "compressed-ssh", ARG_BOOL},
- {"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
- {"$!", "retry-all-errors", ARG_BOOL},
- {"$%", "trace-ids", ARG_BOOL},
- {"$&", "trace-config", ARG_STRING},
- {"0", "http1.0", ARG_NONE},
- {"01", "http1.1", ARG_NONE},
- {"02", "http2", ARG_NONE},
- {"03", "http2-prior-knowledge", ARG_NONE},
- {"04", "http3", ARG_NONE},
- {"05", "http3-only", ARG_NONE},
- {"09", "http0.9", ARG_BOOL},
- {"0a", "proxy-http2", ARG_BOOL},
- {"1", "tlsv1", ARG_NONE},
- {"10", "tlsv1.0", ARG_NONE},
- {"11", "tlsv1.1", ARG_NONE},
- {"12", "tlsv1.2", ARG_NONE},
- {"13", "tlsv1.3", ARG_NONE},
- {"1A", "tls13-ciphers", ARG_STRING},
- {"1B", "proxy-tls13-ciphers", ARG_STRING},
- {"2", "sslv2", ARG_NONE},
- {"3", "sslv3", ARG_NONE},
- {"4", "ipv4", ARG_NONE},
- {"6", "ipv6", ARG_NONE},
- {"a", "append", ARG_BOOL},
- {"A", "user-agent", ARG_STRING},
- {"b", "cookie", ARG_STRING},
- {"ba", "alt-svc", ARG_STRING},
- {"bb", "hsts", ARG_STRING},
- {"B", "use-ascii", ARG_BOOL},
- {"c", "cookie-jar", ARG_STRING},
- {"C", "continue-at", ARG_STRING},
- {"d", "data", ARG_STRING},
- {"dr", "data-raw", ARG_STRING},
- {"da", "data-ascii", ARG_STRING},
- {"db", "data-binary", ARG_STRING},
- {"de", "data-urlencode", ARG_STRING},
- {"df", "json", ARG_STRING},
- {"dg", "url-query", ARG_STRING},
- {"D", "dump-header", ARG_FILENAME},
- {"e", "referer", ARG_STRING},
- {"E", "cert", ARG_FILENAME},
- {"Ea", "cacert", ARG_FILENAME},
- {"Eb", "cert-type", ARG_STRING},
- {"Ec", "key", ARG_FILENAME},
- {"Ed", "key-type", ARG_STRING},
- {"Ee", "pass", ARG_STRING},
- {"Ef", "engine", ARG_STRING},
- {"EG", "ca-native", ARG_BOOL},
- {"EH", "proxy-ca-native", ARG_BOOL},
- {"Eg", "capath", ARG_FILENAME},
- {"Eh", "pubkey", ARG_STRING},
- {"Ei", "hostpubmd5", ARG_STRING},
- {"EF", "hostpubsha256", ARG_STRING},
- {"Ej", "crlfile", ARG_FILENAME},
- {"Ek", "tlsuser", ARG_STRING},
- {"El", "tlspassword", ARG_STRING},
- {"Em", "tlsauthtype", ARG_STRING},
- {"En", "ssl-allow-beast", ARG_BOOL},
- {"Eo", "ssl-auto-client-cert", ARG_BOOL},
- {"EO", "proxy-ssl-auto-client-cert", ARG_BOOL},
- {"Ep", "pinnedpubkey", ARG_STRING},
- {"EP", "proxy-pinnedpubkey", ARG_STRING},
- {"Eq", "cert-status", ARG_BOOL},
- {"EQ", "doh-cert-status", ARG_BOOL},
- {"Er", "false-start", ARG_BOOL},
- {"Es", "ssl-no-revoke", ARG_BOOL},
- {"ES", "ssl-revoke-best-effort", ARG_BOOL},
- {"Et", "tcp-fastopen", ARG_BOOL},
- {"Eu", "proxy-tlsuser", ARG_STRING},
- {"Ev", "proxy-tlspassword", ARG_STRING},
- {"Ew", "proxy-tlsauthtype", ARG_STRING},
- {"Ex", "proxy-cert", ARG_FILENAME},
- {"Ey", "proxy-cert-type", ARG_STRING},
- {"Ez", "proxy-key", ARG_FILENAME},
- {"E0", "proxy-key-type", ARG_STRING},
- {"E1", "proxy-pass", ARG_STRING},
- {"E2", "proxy-ciphers", ARG_STRING},
- {"E3", "proxy-crlfile", ARG_FILENAME},
- {"E4", "proxy-ssl-allow-beast", ARG_BOOL},
- {"E5", "login-options", ARG_STRING},
- {"E6", "proxy-cacert", ARG_FILENAME},
- {"E7", "proxy-capath", ARG_FILENAME},
- {"E8", "proxy-insecure", ARG_BOOL},
- {"E9", "proxy-tlsv1", ARG_NONE},
- {"EA", "socks5-basic", ARG_BOOL},
- {"EB", "socks5-gssapi", ARG_BOOL},
- {"EC", "etag-save", ARG_FILENAME},
- {"ED", "etag-compare", ARG_FILENAME},
- {"EE", "curves", ARG_STRING},
- {"f", "fail", ARG_BOOL},
- {"fa", "fail-early", ARG_BOOL},
- {"fb", "styled-output", ARG_BOOL},
- {"fc", "mail-rcpt-allowfails", ARG_BOOL},
- {"fd", "fail-with-body", ARG_BOOL},
- {"fe", "remove-on-error", ARG_BOOL},
- {"F", "form", ARG_STRING},
- {"Fs", "form-string", ARG_STRING},
- {"g", "globoff", ARG_BOOL},
- {"G", "get", ARG_BOOL},
- {"Ga", "request-target", ARG_STRING},
- {"h", "help", ARG_BOOL},
- {"H", "header", ARG_STRING},
- {"Hp", "proxy-header", ARG_STRING},
- {"i", "include", ARG_BOOL},
- {"I", "head", ARG_BOOL},
- {"j", "junk-session-cookies", ARG_BOOL},
- {"J", "remote-header-name", ARG_BOOL},
- {"k", "insecure", ARG_BOOL},
- {"kd", "doh-insecure", ARG_BOOL},
- {"K", "config", ARG_FILENAME},
- {"l", "list-only", ARG_BOOL},
- {"L", "location", ARG_BOOL},
- {"Lt", "location-trusted", ARG_BOOL},
- {"m", "max-time", ARG_STRING},
- {"M", "manual", ARG_BOOL},
- {"n", "netrc", ARG_BOOL},
- {"no", "netrc-optional", ARG_BOOL},
- {"ne", "netrc-file", ARG_FILENAME},
- {"N", "buffer", ARG_BOOL},
- /* 'buffer' listed as --no-buffer in the help */
- {"o", "output", ARG_FILENAME},
- {"O", "remote-name", ARG_BOOL},
- {"Oa", "remote-name-all", ARG_BOOL},
- {"Ob", "output-dir", ARG_STRING},
- {"Oc", "clobber", ARG_BOOL},
- {"p", "proxytunnel", ARG_BOOL},
- {"P", "ftp-port", ARG_STRING},
- {"q", "disable", ARG_BOOL},
- {"Q", "quote", ARG_STRING},
- {"r", "range", ARG_STRING},
- {"R", "remote-time", ARG_BOOL},
- {"s", "silent", ARG_BOOL},
- {"S", "show-error", ARG_BOOL},
- {"t", "telnet-option", ARG_STRING},
- {"T", "upload-file", ARG_FILENAME},
- {"u", "user", ARG_STRING},
- {"U", "proxy-user", ARG_STRING},
- {"v", "verbose", ARG_BOOL},
- {"V", "version", ARG_BOOL},
- {"w", "write-out", ARG_STRING},
- {"x", "proxy", ARG_STRING},
- {"xa", "preproxy", ARG_STRING},
- {"X", "request", ARG_STRING},
- {"Y", "speed-limit", ARG_STRING},
- {"y", "speed-time", ARG_STRING},
- {"z", "time-cond", ARG_STRING},
- {"Z", "parallel", ARG_BOOL},
- {"Zb", "parallel-max", ARG_STRING},
- {"Zc", "parallel-immediate", ARG_BOOL},
- {"#", "progress-bar", ARG_BOOL},
- {"#m", "progress-meter", ARG_BOOL},
- {":", "next", ARG_NONE},
- {":a", "variable", ARG_STRING},
+ {"write-out", ARG_STRG, 'w', C_WRITE_OUT},
+ {"xattr", ARG_BOOL, ' ', C_XATTR},
};
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
@@ -437,7 +700,7 @@ void parse_cert_parameter(const char *cert_parameter,
needs to work. In order not to break compatibility, we still use : as
separator, but we try to detect when it is used for a file name! On
windows. */
-#ifdef WIN32
+#ifdef _WIN32
if((param_place == &cert_parameter[1]) &&
(cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
(ISALPHA(cert_parameter[0])) ) {
@@ -495,12 +758,14 @@ static void
GetFileAndPassword(char *nextarg, char **file, char **password)
{
char *certname, *passphrase;
- parse_cert_parameter(nextarg, &certname, &passphrase);
- Curl_safefree(*file);
- *file = certname;
- if(passphrase) {
- Curl_safefree(*password);
- *password = passphrase;
+ if(nextarg) {
+ parse_cert_parameter(nextarg, &certname, &passphrase);
+ Curl_safefree(*file);
+ *file = certname;
+ if(passphrase) {
+ Curl_safefree(*password);
+ *password = passphrase;
+ }
}
}
@@ -559,7 +824,7 @@ static ParameterError GetSizeParameter(struct GlobalConfig *global,
#ifdef HAVE_WRITABLE_ARGV
static void cleanarg(argv_item_t str)
{
- /* now that GetStr has copied the contents of nextarg, wipe the next
+ /* now that getstr has copied the contents of nextarg, wipe the next
* argument out so that the username:password isn't displayed in the
* system process list */
if(str) {
@@ -624,7 +889,9 @@ static ParameterError data_urlencode(struct GlobalConfig *global,
return err;
}
else {
- GetStr(&postdata, p);
+ err = getstr(&postdata, p, ALLOW_BLANK);
+ if(err)
+ goto error;
if(postdata)
size = strlen(postdata);
}
@@ -641,25 +908,18 @@ static ParameterError data_urlencode(struct GlobalConfig *global,
char *enc = curl_easy_escape(NULL, postdata, (int)size);
Curl_safefree(postdata); /* no matter if it worked or not */
if(enc) {
- /* replace (in-place) '%20' by '+' according to RFC1866 */
- size_t enclen = replace_url_encoded_space_by_plus(enc);
- /* now make a string with the name from above and append the
- encoded string */
- size_t outlen = nlen + enclen + 2;
- char *n = malloc(outlen);
- if(!n) {
- curl_free(enc);
- return PARAM_NO_MEM;
- }
+ char *n;
+ replace_url_encoded_space_by_plus(enc);
if(nlen > 0) { /* only append '=' if we have a name */
- msnprintf(n, outlen, "%.*s=%s", (int)nlen, nextarg, enc);
- size = outlen-1;
- }
- else {
- strcpy(n, enc);
- size = outlen-2; /* since no '=' was inserted */
+ n = aprintf("%.*s=%s", (int)nlen, nextarg, enc);
+ curl_free(enc);
+ if(!n)
+ return PARAM_NO_MEM;
}
- curl_free(enc);
+ else
+ n = enc;
+
+ size = strlen(n);
postdata = n;
}
else
@@ -738,6 +998,212 @@ out:
return result;
}
+static int findarg(const void *a, const void *b)
+{
+ const struct LongShort *aa = a;
+ const struct LongShort *bb = b;
+ return strcmp(aa->lname, bb->lname);
+}
+
+static const struct LongShort *single(char letter)
+{
+ static const struct LongShort *singles[128 - ' ']; /* ASCII => pointer */
+ static bool singles_done = FALSE;
+ DEBUGASSERT((letter < 127) && (letter > ' '));
+
+ if(!singles_done) {
+ unsigned int j;
+ for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
+ if(aliases[j].letter != ' ') {
+ unsigned char l = aliases[j].letter;
+ singles[l - ' '] = &aliases[j];
+ }
+ }
+ singles_done = TRUE;
+ }
+ return singles[letter - ' '];
+}
+
+#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
+static ParameterError url_query(char *nextarg,
+ struct GlobalConfig *global,
+ struct OperationConfig *config)
+{
+ size_t size = 0;
+ ParameterError err = PARAM_OK;
+ char *query;
+ struct curlx_dynbuf dyn;
+ curlx_dyn_init(&dyn, MAX_QUERY_LEN);
+
+ if(*nextarg == '+') {
+ /* use without encoding */
+ query = strdup(&nextarg[1]);
+ if(!query)
+ err = PARAM_NO_MEM;
+ }
+ else
+ err = data_urlencode(global, nextarg, &query, &size);
+
+ if(!err) {
+ if(config->query) {
+ CURLcode result = curlx_dyn_addf(&dyn, "%s&%s", config->query, query);
+ free(query);
+ if(result)
+ err = PARAM_NO_MEM;
+ else {
+ free(config->query);
+ config->query = curlx_dyn_ptr(&dyn);
+ }
+ }
+ else
+ config->query = query;
+ }
+ return err;
+}
+
+static ParameterError set_data(cmdline_t cmd,
+ char *nextarg,
+ struct GlobalConfig *global,
+ struct OperationConfig *config)
+{
+ char *postdata = NULL;
+ FILE *file;
+ size_t size = 0;
+ ParameterError err = PARAM_OK;
+
+ if(cmd == C_DATA_URLENCODE) { /* --data-urlencode */
+ err = data_urlencode(global, nextarg, &postdata, &size);
+ if(err)
+ return err;
+ }
+ else if('@' == *nextarg && (cmd != C_DATA_RAW)) {
+ /* the data begins with a '@' letter, it means that a file name
+ or - (stdin) follows */
+ nextarg++; /* pass the @ */
+
+ if(!strcmp("-", nextarg)) {
+ file = stdin;
+ if(cmd == C_DATA_BINARY) /* forced data-binary */
+ set_binmode(stdin);
+ }
+ else {
+ file = fopen(nextarg, "rb");
+ if(!file) {
+ errorf(global, "Failed to open %s", nextarg);
+ return PARAM_READ_ERROR;
+ }
+ }
+
+ if((cmd == C_DATA_BINARY) || /* --data-binary */
+ (cmd == C_JSON) /* --json */)
+ /* forced binary */
+ err = file2memory(&postdata, &size, file);
+ else {
+ err = file2string(&postdata, file);
+ if(postdata)
+ size = strlen(postdata);
+ }
+
+ if(file && (file != stdin))
+ fclose(file);
+ if(err)
+ return err;
+
+ if(!postdata) {
+ /* no data from the file, point to a zero byte string to make this
+ get sent as a POST anyway */
+ postdata = strdup("");
+ if(!postdata)
+ return PARAM_NO_MEM;
+ }
+ }
+ else {
+ err = getstr(&postdata, nextarg, ALLOW_BLANK);
+ if(err)
+ return err;
+ if(postdata)
+ size = strlen(postdata);
+ }
+ if(cmd == C_JSON)
+ config->jsoned = TRUE;
+
+ if(curlx_dyn_len(&config->postdata)) {
+ /* skip separator append for --json */
+ if(!err && (cmd != C_JSON) &&
+ curlx_dyn_addn(&config->postdata, "&", 1))
+ err = PARAM_NO_MEM;
+ }
+
+ if(!err && curlx_dyn_addn(&config->postdata, postdata, size))
+ err = PARAM_NO_MEM;
+
+ Curl_safefree(postdata);
+
+ config->postfields = curlx_dyn_ptr(&config->postdata);
+ return err;
+}
+
+static ParameterError set_rate(struct GlobalConfig *global,
+ char *nextarg)
+{
+ /* --rate */
+ /* support a few different suffixes, extract the suffix first, then
+ get the number and convert to per hour.
+ /s == per second
+ /m == per minute
+ /h == per hour (default)
+ /d == per day (24 hours)
+ */
+ ParameterError err = PARAM_OK;
+ char *div = strchr(nextarg, '/');
+ char number[26];
+ long denominator;
+ long numerator = 60*60*1000; /* default per hour */
+ size_t numlen = div ? (size_t)(div - nextarg) : strlen(nextarg);
+ if(numlen > sizeof(number) -1)
+ return PARAM_NUMBER_TOO_LARGE;
+
+ strncpy(number, nextarg, numlen);
+ number[numlen] = 0;
+ err = str2unum(&denominator, number);
+ if(err)
+ return err;
+
+ if(denominator < 1)
+ return PARAM_BAD_USE;
+
+ if(div) {
+ char unit = div[1];
+ switch(unit) {
+ case 's': /* per second */
+ numerator = 1000;
+ break;
+ case 'm': /* per minute */
+ numerator = 60*1000;
+ break;
+ case 'h': /* per hour */
+ break;
+ case 'd': /* per day */
+ numerator = 24*60*60*1000;
+ break;
+ default:
+ errorf(global, "unsupported --rate unit");
+ err = PARAM_BAD_USE;
+ break;
+ }
+ }
+
+ if(err)
+ ;
+ else if(denominator > numerator)
+ err = PARAM_NUMBER_TOO_LARGE;
+ else
+ global->ms_per_transfer = numerator/denominator;
+
+ return err;
+}
+
+
ParameterError getparameter(const char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */
argv_item_t cleararg,
@@ -746,19 +1212,16 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
struct GlobalConfig *global,
struct OperationConfig *config)
{
- char letter;
- char subletter = '\0'; /* subletters can only occur on long options */
int rc;
const char *parse = NULL;
- unsigned int j;
time_t now;
- int hit = -1;
bool longopt = FALSE;
bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
ParameterError err = PARAM_OK;
bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
by using --OPTION or --no-OPTION */
bool nextalloc = FALSE; /* if nextarg is allocated */
+ struct getout *url;
static const char *redir_protos[] = {
"http",
"https",
@@ -766,6 +1229,8 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
"ftps",
NULL
};
+ const struct LongShort *a = NULL;
+ curl_off_t value;
#ifdef HAVE_WRITABLE_ARGV
argv_item_t clearthis = NULL;
#else
@@ -777,10 +1242,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(('-' != flag[0]) || ('-' == flag[1])) {
/* this should be a long name */
const char *word = ('-' == flag[0]) ? flag + 2 : flag;
- size_t fnam = strlen(word);
- int numhits = 0;
bool noflagged = FALSE;
bool expand = FALSE;
+ struct LongShort key;
if(!strncmp(word, "no-", 3)) {
/* disable this option but ignore the "no-" part when looking for it */
@@ -793,41 +1257,28 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
word += 7;
expand = TRUE;
}
+ key.lname = word;
- for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
- if(curl_strnequal(aliases[j].lname, word, fnam)) {
- longopt = TRUE;
- numhits++;
- if(curl_strequal(aliases[j].lname, word)) {
- parse = aliases[j].letter;
- hit = j;
- numhits = 1; /* a single unique hit */
- break;
- }
- parse = aliases[j].letter;
- hit = j;
- }
+ a = bsearch(&key, aliases, sizeof(aliases)/sizeof(aliases[0]),
+ sizeof(aliases[0]), findarg);
+ if(a) {
+ longopt = TRUE;
}
- if(numhits > 1) {
- /* this is at least the second match! */
- err = PARAM_OPTION_AMBIGUOUS;
- goto error;
- }
- else if(hit < 0) {
+ else {
err = PARAM_OPTION_UNKNOWN;
goto error;
}
- else if(noflagged && (aliases[hit].desc != ARG_BOOL)) {
+ if(noflagged && (a->desc != ARG_BOOL)) {
/* --no- prefixed an option that isn't boolean! */
err = PARAM_NO_NOT_BOOLEAN;
goto error;
}
- else if(expand) {
+ else if(expand && nextarg) {
struct curlx_dynbuf nbuf;
bool replaced;
- if((aliases[hit].desc != ARG_STRING) &&
- (aliases[hit].desc != ARG_FILENAME)) {
+ if((a->desc != ARG_STRG) &&
+ (a->desc != ARG_FILE)) {
/* --expand on an option that isn't a string or a filename */
err = PARAM_EXPAND_ERROR;
goto error;
@@ -845,36 +1296,24 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
}
else {
flag++; /* prefixed with one dash, pass it */
- hit = -1;
parse = flag;
}
do {
/* we can loop here if we have multiple single-letters */
+ char letter;
+ cmdline_t cmd;
- if(!longopt) {
- letter = (char)*parse;
- subletter = '\0';
- }
- else {
- letter = parse[0];
- subletter = parse[1];
- }
-
- if(hit < 0) {
- for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
- if(letter == aliases[j].letter[0]) {
- hit = j;
- break;
- }
- }
- if(hit < 0) {
+ if(!longopt && !a) {
+ a = single(*parse);
+ if(!a) {
err = PARAM_OPTION_UNKNOWN;
break;
}
}
-
- if(aliases[hit].desc >= ARG_STRING) {
+ letter = a->letter;
+ cmd = a->cmd;
+ if(a->desc >= ARG_STRG) {
/* this option requires an extra parameter */
if(!longopt && parse[1]) {
nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
@@ -891,813 +1330,684 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
*usedarg = TRUE; /* mark it as used */
}
- if((aliases[hit].desc == ARG_FILENAME) &&
+ if((a->desc == ARG_FILE) &&
(nextarg[0] == '-') && nextarg[1]) {
/* if the file name looks like a command line option */
warnf(global, "The file name argument '%s' looks like a flag.",
nextarg);
}
}
- else if((aliases[hit].desc == ARG_NONE) && !toggle) {
+ else if((a->desc == ARG_NONE) && !toggle) {
err = PARAM_NO_PREFIX;
break;
}
- switch(letter) {
- case '*': /* options without a short option */
- switch(subletter) {
- case '4': /* --dns-ipv4-addr */
- if(!curlinfo->ares_num) { /* c-ares is needed for this */
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ if(!nextarg)
+ /* this is a precaution mostly to please scan-build, as all arguments
+ that use nextarg should be marked as such and they will check that
+ nextarg is set before continuing, but code analyzers are not always
+ that aware of that state */
+ nextarg = (char *)"";
+
+ switch(cmd) {
+ case C_DNS_IPV4_ADDR: /* --dns-ipv4-addr */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
/* addr in dot notation */
- GetStr(&config->dns_ipv4_addr, nextarg);
- break;
- case '6': /* --dns-ipv6-addr */
- if(!curlinfo->ares_num) { /* c-ares is needed for this */
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ err = getstr(&config->dns_ipv4_addr, nextarg, DENY_BLANK);
+ break;
+ case C_DNS_IPV6_ADDR: /* --dns-ipv6-addr */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
/* addr in dot notation */
- GetStr(&config->dns_ipv6_addr, nextarg);
- break;
- case 'a': /* random-file */
- break;
- case 'b': /* egd-file */
- break;
- case 'B': /* OAuth 2.0 bearer token */
- GetStr(&config->oauth_bearer, nextarg);
+ err = getstr(&config->dns_ipv6_addr, nextarg, DENY_BLANK);
+ break;
+ case C_RANDOM_FILE: /* --random-file */
+ break;
+ case C_EGD_FILE: /* --egd-file */
+ break;
+ case C_OAUTH2_BEARER: /* --oauth2-bearer */
+ err = getstr(&config->oauth_bearer, nextarg, DENY_BLANK);
+ if(!err) {
cleanarg(clearthis);
config->authtype |= CURLAUTH_BEARER;
- break;
- case 'c': /* connect-timeout */
- err = secs2ms(&config->connecttimeout_ms, nextarg);
- break;
- case 'C': /* doh-url */
- GetStr(&config->doh_url, nextarg);
- if(config->doh_url && !config->doh_url[0])
- /* if given a blank string, we make it NULL again */
- Curl_safefree(config->doh_url);
- break;
- case 'd': /* ciphers */
- GetStr(&config->cipher_list, nextarg);
- break;
- case 'D': /* --dns-interface */
- if(!curlinfo->ares_num) /* c-ares is needed for this */
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- else
- /* interface name */
- GetStr(&config->dns_interface, nextarg);
- break;
- case 'e': /* --disable-epsv */
- config->disable_epsv = toggle;
- break;
- case 'f': /* --disallow-username-in-url */
- config->disallow_username_in_url = toggle;
- break;
- case 'E': /* --epsv */
- config->disable_epsv = (!toggle)?TRUE:FALSE;
- break;
- case 'F': /* --dns-servers */
- if(!curlinfo->ares_num) /* c-ares is needed for this */
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- else
- /* IP addrs of DNS servers */
- GetStr(&config->dns_servers, nextarg);
- break;
- case 'g': /* --trace */
- GetStr(&global->trace_dump, nextarg);
+ }
+ break;
+ case C_CONNECT_TIMEOUT: /* --connect-timeout */
+ err = secs2ms(&config->connecttimeout_ms, nextarg);
+ break;
+ case C_DOH_URL: /* --doh-url */
+ err = getstr(&config->doh_url, nextarg, ALLOW_BLANK);
+ if(!err && config->doh_url && !config->doh_url[0])
+ /* if given a blank string, make it NULL again */
+ Curl_safefree(config->doh_url);
+ break;
+ case C_CIPHERS: /* -- ciphers */
+ err = getstr(&config->cipher_list, nextarg, DENY_BLANK);
+ break;
+ case C_DNS_INTERFACE: /* --dns-interface */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ /* interface name */
+ err = getstr(&config->dns_interface, nextarg, DENY_BLANK);
+ break;
+ case C_DISABLE_EPSV: /* --disable-epsv */
+ config->disable_epsv = toggle;
+ break;
+ case C_DISALLOW_USERNAME_IN_URL: /* --disallow-username-in-url */
+ config->disallow_username_in_url = toggle;
+ break;
+ case C_EPSV: /* --epsv */
+ config->disable_epsv = (!toggle)?TRUE:FALSE;
+ break;
+ case C_DNS_SERVERS: /* --dns-servers */
+ if(!curlinfo->ares_num) /* c-ares is needed for this */
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ /* IP addrs of DNS servers */
+ err = getstr(&config->dns_servers, nextarg, DENY_BLANK);
+ break;
+ case C_TRACE: /* --trace */
+ err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
+ if(!err) {
if(global->tracetype && (global->tracetype != TRACE_BIN))
warnf(global, "--trace overrides an earlier trace/verbose option");
global->tracetype = TRACE_BIN;
- break;
- case 'G': /* --npn */
- warnf(global, "--npn is no longer supported");
- break;
- case 'h': /* --trace-ascii */
- GetStr(&global->trace_dump, nextarg);
+ }
+ break;
+ case C_NPN: /* --npn */
+ warnf(global, "--npn is no longer supported");
+ break;
+ case C_TRACE_ASCII: /* --trace-ascii */
+ err = getstr(&global->trace_dump, nextarg, DENY_BLANK);
+ if(!err) {
if(global->tracetype && (global->tracetype != TRACE_ASCII))
warnf(global,
"--trace-ascii overrides an earlier trace/verbose option");
global->tracetype = TRACE_ASCII;
- break;
- case 'H': /* --alpn */
- config->noalpn = (!toggle)?TRUE:FALSE;
- break;
- case 'i': /* --limit-rate */
- {
- curl_off_t value;
- err = GetSizeParameter(global, nextarg, "rate", &value);
- if(err)
- break;
+ }
+ break;
+ case C_ALPN: /* --alpn */
+ config->noalpn = (!toggle)?TRUE:FALSE;
+ break;
+ case C_LIMIT_RATE: /* --limit-rate */
+ err = GetSizeParameter(global, nextarg, "rate", &value);
+ if(!err) {
config->recvpersecond = value;
config->sendpersecond = value;
}
break;
- case 'I': /* --rate (request rate) */
- {
- /* support a few different suffixes, extract the suffix first, then
- get the number and convert to per hour.
- /s == per second
- /m == per minute
- /h == per hour (default)
- /d == per day (24 hours)
- */
- char *div = strchr(nextarg, '/');
- char number[26];
- long denominator;
- long numerator = 60*60*1000; /* default per hour */
- size_t numlen = div ? (size_t)(div - nextarg) : strlen(nextarg);
- if(numlen > sizeof(number)-1) {
- err = PARAM_NUMBER_TOO_LARGE;
- break;
- }
- strncpy(number, nextarg, numlen);
- number[numlen] = 0;
- err = str2unum(&denominator, number);
- if(err)
- break;
-
- if(denominator < 1) {
- err = PARAM_BAD_USE;
- break;
- }
- if(div) {
- char unit = div[1];
- switch(unit) {
- case 's': /* per second */
- numerator = 1000;
- break;
- case 'm': /* per minute */
- numerator = 60*1000;
- break;
- case 'h': /* per hour */
- break;
- case 'd': /* per day */
- numerator = 24*60*60*1000;
- break;
- default:
- errorf(global, "unsupported --rate unit");
- err = PARAM_BAD_USE;
- break;
- }
- }
- global->ms_per_transfer = numerator/denominator;
- }
+ case C_RATE:
+ err = set_rate(global, nextarg);
break;
-
- case 'j': /* --compressed */
- if(toggle && !(feature_libz || feature_brotli || feature_zstd)) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ case C_COMPRESSED: /* --compressed */
+ if(toggle && !(feature_libz || feature_brotli || feature_zstd))
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
config->encoding = toggle;
- break;
-
- case 'J': /* --tr-encoding */
- config->tr_encoding = toggle;
- break;
-
- case 'k': /* --digest */
- if(toggle)
- config->authtype |= CURLAUTH_DIGEST;
- else
- config->authtype &= ~CURLAUTH_DIGEST;
- break;
-
- case 'l': /* --negotiate */
- if(!toggle)
- config->authtype &= ~CURLAUTH_NEGOTIATE;
- else if(feature_spnego)
- config->authtype |= CURLAUTH_NEGOTIATE;
- else {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- break;
-
- case 'm': /* --ntlm */
- if(!toggle)
- config->authtype &= ~CURLAUTH_NTLM;
- else if(feature_ntlm)
- config->authtype |= CURLAUTH_NTLM;
- else {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- break;
-
- case 'M': /* --ntlm-wb */
- if(!toggle)
- config->authtype &= ~CURLAUTH_NTLM_WB;
- else if(feature_ntlm_wb)
- config->authtype |= CURLAUTH_NTLM_WB;
- else {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- break;
-
- case 'n': /* --basic for completeness */
- if(toggle)
- config->authtype |= CURLAUTH_BASIC;
- else
- config->authtype &= ~CURLAUTH_BASIC;
- break;
-
- case 'o': /* --anyauth, let libcurl pick it */
- if(toggle)
- config->authtype = CURLAUTH_ANY;
- /* --no-anyauth simply doesn't touch it */
- break;
-
+ break;
+ case C_TR_ENCODING: /* --tr-encoding */
+ config->tr_encoding = toggle;
+ break;
+ case C_DIGEST: /* --digest */
+ if(toggle)
+ config->authtype |= CURLAUTH_DIGEST;
+ else
+ config->authtype &= ~CURLAUTH_DIGEST;
+ break;
+ case C_NEGOTIATE: /* --negotiate */
+ if(!toggle)
+ config->authtype &= ~CURLAUTH_NEGOTIATE;
+ else if(feature_spnego)
+ config->authtype |= CURLAUTH_NEGOTIATE;
+ else
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case C_NTLM: /* --ntlm */
+ if(!toggle)
+ config->authtype &= ~CURLAUTH_NTLM;
+ else if(feature_ntlm)
+ config->authtype |= CURLAUTH_NTLM;
+ else
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case C_NTLM_WB: /* --ntlm-wb */
+ if(!toggle)
+ config->authtype &= ~CURLAUTH_NTLM_WB;
+ else if(feature_ntlm_wb)
+ config->authtype |= CURLAUTH_NTLM_WB;
+ else
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case C_BASIC: /* --basic */
+ if(toggle)
+ config->authtype |= CURLAUTH_BASIC;
+ else
+ config->authtype &= ~CURLAUTH_BASIC;
+ break;
+ case C_ANYAUTH: /* --anyauth */
+ if(toggle)
+ config->authtype = CURLAUTH_ANY;
+ /* --no-anyauth simply doesn't touch it */
+ break;
#ifdef USE_WATT32
- case 'p': /* --wdebug */
- dbug_init();
- break;
+ case C_WDEBUG: /* --wdebug */
+ dbug_init();
+ break;
#endif
- case 'q': /* --ftp-create-dirs */
- config->ftp_create_dirs = toggle;
- break;
-
- case 'r': /* --create-dirs */
- config->create_dirs = toggle;
- break;
-
- case 'R': /* --create-file-mode */
- err = oct2nummax(&config->create_file_mode, nextarg, 0777);
- break;
-
- case 's': /* --max-redirs */
- /* specified max no of redirects (http(s)), this accepts -1 as a
- special condition */
- err = str2num(&config->maxredirs, nextarg);
- if(err)
- break;
- if(config->maxredirs < -1)
- err = PARAM_BAD_NUMERIC;
- break;
-
- case 'S': /* ipfs gateway url */
- GetStr(&config->ipfs_gateway, nextarg);
- break;
-
- case 't': /* --proxy-ntlm */
- if(!feature_ntlm) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ case C_FTP_CREATE_DIRS: /* --ftp-create-dirs */
+ config->ftp_create_dirs = toggle;
+ break;
+ case C_CREATE_DIRS: /* --create-dirs */
+ config->create_dirs = toggle;
+ break;
+ case C_CREATE_FILE_MODE: /* --create-file-mode */
+ err = oct2nummax(&config->create_file_mode, nextarg, 0777);
+ break;
+ case C_MAX_REDIRS: /* --max-redirs */
+ /* specified max no of redirects (http(s)), this accepts -1 as a
+ special condition */
+ err = str2num(&config->maxredirs, nextarg);
+ if(!err && (config->maxredirs < -1))
+ err = PARAM_BAD_NUMERIC;
+ break;
+ case C_IPFS_GATEWAY: /* --ipfs-gateway */
+ err = getstr(&config->ipfs_gateway, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_NTLM: /* --proxy-ntlm */
+ if(!feature_ntlm)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
config->proxyntlm = toggle;
- break;
-
- case 'u': /* --crlf */
- /* LF -> CRLF conversion? */
- config->crlf = toggle;
- break;
-
- case 'V': /* --aws-sigv4 */
- config->authtype |= CURLAUTH_AWS_SIGV4;
- GetStr(&config->aws_sigv4, nextarg);
- break;
-
- case 'v': /* --stderr */
- tool_set_stderr_file(global, nextarg);
- break;
- case 'w': /* --interface */
- /* interface */
- GetStr(&config->iface, nextarg);
- break;
- case 'x': /* --krb */
- /* kerberos level string */
- if(!feature_spnego) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- GetStr(&config->krblevel, nextarg);
- break;
- case 'X': /* --haproxy-protocol */
- config->haproxy_protocol = toggle;
- break;
- case 'P': /* --haproxy-clientip */
- GetStr(&config->haproxy_clientip, nextarg);
- break;
- case 'y': /* --max-filesize */
- {
- curl_off_t value;
- err =
- GetSizeParameter(global, nextarg, "max-filesize", &value);
- if(err)
- break;
- config->max_filesize = value;
- }
- break;
- case 'z': /* --disable-eprt */
- config->disable_eprt = toggle;
- break;
- case 'Z': /* --eprt */
- config->disable_eprt = (!toggle)?TRUE:FALSE;
- break;
- case '~': /* --xattr */
- config->xattr = toggle;
- break;
- case '@': /* the URL! */
- {
- struct getout *url;
-
- if(!config->url_get)
- config->url_get = config->url_list;
-
- if(config->url_get) {
- /* there's a node here, if it already is filled-in continue to find
- an "empty" node */
- while(config->url_get && (config->url_get->flags & GETOUT_URL))
- config->url_get = config->url_get->next;
- }
+ break;
+ case C_CRLF: /* --crlf */
+ /* LF -> CRLF conversion? */
+ config->crlf = toggle;
+ break;
+ case C_AWS_SIGV4: /* --aws-sigv4 */
+ config->authtype |= CURLAUTH_AWS_SIGV4;
+ err = getstr(&config->aws_sigv4, nextarg, DENY_BLANK);
+ break;
+ case C_STDERR: /* --stderr */
+ tool_set_stderr_file(global, nextarg);
+ break;
+ case C_INTERFACE: /* --interface */
+ /* interface */
+ err = getstr(&config->iface, nextarg, DENY_BLANK);
+ break;
+ case C_KRB: /* --krb */
+ /* kerberos level string */
+ if(!feature_spnego)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ err = getstr(&config->krblevel, nextarg, DENY_BLANK);
+ break;
+ case C_HAPROXY_PROTOCOL: /* --haproxy-protocol */
+ config->haproxy_protocol = toggle;
+ break;
+ case C_HAPROXY_CLIENTIP: /* --haproxy-clientip */
+ err = getstr(&config->haproxy_clientip, nextarg, DENY_BLANK);
+ break;
+ case C_MAX_FILESIZE: /* --max-filesize */
+ err = GetSizeParameter(global, nextarg, "max-filesize", &value);
+ if(!err)
+ config->max_filesize = value;
+ break;
+ case C_DISABLE_EPRT: /* --disable-eprt */
+ config->disable_eprt = toggle;
+ break;
+ case C_EPRT: /* --eprt */
+ config->disable_eprt = (!toggle)?TRUE:FALSE;
+ break;
+ case C_XATTR: /* --xattr */
+ config->xattr = toggle;
+ break;
+ case C_URL: /* --url */
+ if(!config->url_get)
+ config->url_get = config->url_list;
- /* now there might or might not be an available node to fill in! */
+ if(config->url_get) {
+ /* there's a node here, if it already is filled-in continue to find
+ an "empty" node */
+ while(config->url_get && (config->url_get->flags & GETOUT_URL))
+ config->url_get = config->url_get->next;
+ }
- if(config->url_get)
- /* existing node */
- url = config->url_get;
- else
- /* there was no free node, create one! */
- config->url_get = url = new_getout(config);
+ /* now there might or might not be an available node to fill in! */
- if(!url) {
- err = PARAM_NO_MEM;
- break;
- }
+ if(config->url_get)
+ /* existing node */
+ url = config->url_get;
+ else
+ /* there was no free node, create one! */
+ config->url_get = url = new_getout(config);
+ if(!url)
+ err = PARAM_NO_MEM;
+ else {
/* fill in the URL */
- GetStr(&url->url, nextarg);
+ err = getstr(&url->url, nextarg, DENY_BLANK);
url->flags |= GETOUT_URL;
}
- }
break;
- case '$': /* more options without a short option */
- switch(subletter) {
- case 'a': /* --ssl */
- if(toggle && !feature_ssl) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ case C_SSL: /* --ssl */
+ if(toggle && !feature_ssl)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else {
config->ftp_ssl = toggle;
if(config->ftp_ssl)
warnf(global,
"--ssl is an insecure option, consider --ssl-reqd instead");
- break;
- case 'b': /* --ftp-pasv */
- Curl_safefree(config->ftpport);
- break;
- case 'c': /* --socks5 specifies a socks5 proxy to use, and resolves
- the name locally and passes on the resolved address */
- GetStr(&config->proxy, nextarg);
- config->proxyver = CURLPROXY_SOCKS5;
- break;
- case 't': /* --socks4 specifies a socks4 proxy to use */
- GetStr(&config->proxy, nextarg);
- config->proxyver = CURLPROXY_SOCKS4;
- break;
- case 'T': /* --socks4a specifies a socks4a proxy to use */
- GetStr(&config->proxy, nextarg);
- config->proxyver = CURLPROXY_SOCKS4A;
- break;
- case '2': /* --socks5-hostname specifies a socks5 proxy and enables name
- resolving with the proxy */
- GetStr(&config->proxy, nextarg);
- config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
- break;
- case 'd': /* --tcp-nodelay option */
- config->tcp_nodelay = toggle;
- break;
- case 'e': /* --proxy-digest */
- config->proxydigest = toggle;
- break;
- case 'f': /* --proxy-basic */
- config->proxybasic = toggle;
- break;
- case 'g': /* --retry */
- err = str2unum(&config->req_retry, nextarg);
- break;
- case 'V': /* --retry-connrefused */
- config->retry_connrefused = toggle;
- break;
- case 'h': /* --retry-delay */
- err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
- break;
- case 'i': /* --retry-max-time */
- err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
- break;
- case '!': /* --retry-all-errors */
- config->retry_all_errors = toggle;
- break;
-
- case 'k': /* --proxy-negotiate */
- if(!feature_spnego) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ }
+ break;
+ case C_FTP_PASV: /* --ftp-pasv */
+ Curl_safefree(config->ftpport);
+ break;
+ case C_SOCKS5: /* --socks5 */
+ /* socks5 proxy to use, and resolves the name locally and passes on the
+ resolved address */
+ err = getstr(&config->proxy, nextarg, DENY_BLANK);
+ config->proxyver = CURLPROXY_SOCKS5;
+ break;
+ case C_SOCKS4: /* --socks4 */
+ err = getstr(&config->proxy, nextarg, DENY_BLANK);
+ config->proxyver = CURLPROXY_SOCKS4;
+ break;
+ case C_SOCKS4A: /* --socks4a */
+ err = getstr(&config->proxy, nextarg, DENY_BLANK);
+ config->proxyver = CURLPROXY_SOCKS4A;
+ break;
+ case C_SOCKS5_HOSTNAME: /* --socks5-hostname */
+ err = getstr(&config->proxy, nextarg, DENY_BLANK);
+ config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
+ break;
+ case C_TCP_NODELAY: /* --tcp-nodelay */
+ config->tcp_nodelay = toggle;
+ break;
+ case C_PROXY_DIGEST: /* --proxy-digest */
+ config->proxydigest = toggle;
+ break;
+ case C_PROXY_BASIC: /* --proxy-basic */
+ config->proxybasic = toggle;
+ break;
+ case C_RETRY: /* --retry */
+ err = str2unum(&config->req_retry, nextarg);
+ break;
+ case C_RETRY_CONNREFUSED: /* --retry-connrefused */
+ config->retry_connrefused = toggle;
+ break;
+ case C_RETRY_DELAY: /* --retry-delay */
+ err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
+ break;
+ case C_RETRY_MAX_TIME: /* --retry-max-time */
+ err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
+ break;
+ case C_RETRY_ALL_ERRORS: /* --retry-all-errors */
+ config->retry_all_errors = toggle;
+ break;
+ case C_PROXY_NEGOTIATE: /* --proxy-negotiate */
+ if(!feature_spnego)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
config->proxynegotiate = toggle;
- break;
-
- case 'l': /* --form-escape */
- config->mime_options &= ~CURLMIMEOPT_FORMESCAPE;
- if(toggle)
- config->mime_options |= CURLMIMEOPT_FORMESCAPE;
- break;
+ break;
+ case C_FORM_ESCAPE: /* --form-escape */
+ config->mime_options &= ~CURLMIMEOPT_FORMESCAPE;
+ if(toggle)
+ config->mime_options |= CURLMIMEOPT_FORMESCAPE;
+ break;
+ case C_FTP_ACCOUNT: /* --ftp-account */
+ err = getstr(&config->ftp_account, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_ANYAUTH: /* --proxy-anyauth */
+ config->proxyanyauth = toggle;
+ break;
+ case C_TRACE_TIME: /* --trace-time */
+ global->tracetime = toggle;
+ break;
+ case C_IGNORE_CONTENT_LENGTH: /* --ignore-content-length */
+ config->ignorecl = toggle;
+ break;
+ case C_FTP_SKIP_PASV_IP: /* --ftp-skip-pasv-ip */
+ config->ftp_skip_ip = toggle;
+ break;
+ case C_FTP_METHOD: /* --ftp-method */
+ config->ftp_filemethod = ftpfilemethod(config, nextarg);
+ break;
+ case C_LOCAL_PORT: { /* --local-port */
+ /* 16bit base 10 is 5 digits, but we allow 6 so that this catches
+ overflows, not just truncates */
+ char lrange[7]="";
+ char *p = nextarg;
+ while(ISDIGIT(*p))
+ p++;
+ if(*p) {
+ /* if there's anything more than a plain decimal number */
+ rc = sscanf(p, " - %6s", lrange);
+ *p = 0; /* null-terminate to make str2unum() work below */
+ }
+ else
+ rc = 0;
- case 'm': /* --ftp-account */
- GetStr(&config->ftp_account, nextarg);
- break;
- case 'n': /* --proxy-anyauth */
- config->proxyanyauth = toggle;
- break;
- case 'o': /* --trace-time */
- global->tracetime = toggle;
- break;
- case 'p': /* --ignore-content-length */
- config->ignorecl = toggle;
- break;
- case 'q': /* --ftp-skip-pasv-ip */
- config->ftp_skip_ip = toggle;
- break;
- case 'r': /* --ftp-method (undocumented at this point) */
- config->ftp_filemethod = ftpfilemethod(config, nextarg);
+ err = str2unum(&config->localport, nextarg);
+ if(err || (config->localport > 65535)) {
+ err = PARAM_BAD_USE;
break;
- case 's': { /* --local-port */
- /* 16bit base 10 is 5 digits, but we allow 6 so that this catches
- overflows, not just truncates */
- char lrange[7]="";
- char *p = nextarg;
- while(ISDIGIT(*p))
- p++;
- if(*p) {
- /* if there's anything more than a plain decimal number */
- rc = sscanf(p, " - %6s", lrange);
- *p = 0; /* null-terminate to make str2unum() work below */
- }
- else
- rc = 0;
-
- err = str2unum(&config->localport, nextarg);
- if(err || (config->localport > 65535)) {
+ }
+ if(!rc)
+ config->localportrange = 1; /* default number of ports to try */
+ else {
+ err = str2unum(&config->localportrange, lrange);
+ if(err || (config->localportrange > 65535))
err = PARAM_BAD_USE;
- break;
- }
- if(!rc)
- config->localportrange = 1; /* default number of ports to try */
else {
- err = str2unum(&config->localportrange, lrange);
- if(err || (config->localportrange > 65535))
+ config->localportrange -= (config->localport-1);
+ if(config->localportrange < 1)
err = PARAM_BAD_USE;
- else {
- config->localportrange -= (config->localport-1);
- if(config->localportrange < 1)
- err = PARAM_BAD_USE;
- }
}
- break;
}
- case 'u': /* --ftp-alternative-to-user */
- GetStr(&config->ftp_alternative_to_user, nextarg);
- break;
- case 'v': /* --ssl-reqd */
- if(toggle && !feature_ssl) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- config->ftp_ssl_reqd = toggle;
- break;
- case 'w': /* --no-sessionid */
- config->disable_sessionid = (!toggle)?TRUE:FALSE;
+ break;
+ }
+ case C_FTP_ALTERNATIVE_TO_USER: /* --ftp-alternative-to-user */
+ err = getstr(&config->ftp_alternative_to_user, nextarg, DENY_BLANK);
+ break;
+ case C_FTP_SSL_REQD: /* --ftp-ssl-reqd */
+ case C_SSL_REQD: /* --ssl-reqd */
+ if(toggle && !feature_ssl) {
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
break;
- case 'x': /* --ftp-ssl-control */
- if(toggle && !feature_ssl) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ }
+ config->ftp_ssl_reqd = toggle;
+ break;
+ case C_SESSIONID: /* --sessionid */
+ config->disable_sessionid = (!toggle)?TRUE:FALSE;
+ break;
+ case C_FTP_SSL_CONTROL: /* --ftp-ssl-control */
+ if(toggle && !feature_ssl)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
config->ftp_ssl_control = toggle;
- break;
- case 'y': /* --ftp-ssl-ccc */
- config->ftp_ssl_ccc = toggle;
- if(!config->ftp_ssl_ccc_mode)
- config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
- break;
- case 'j': /* --ftp-ssl-ccc-mode */
- config->ftp_ssl_ccc = TRUE;
- config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
- break;
- case 'z': /* --libcurl */
+ break;
+ case C_FTP_SSL_CCC: /* --ftp-ssl-ccc */
+ config->ftp_ssl_ccc = toggle;
+ if(!config->ftp_ssl_ccc_mode)
+ config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
+ break;
+ case C_FTP_SSL_CCC_MODE: /* --ftp-ssl-ccc-mode */
+ config->ftp_ssl_ccc = TRUE;
+ config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
+ break;
+ case C_LIBCURL: /* --libcurl */
#ifdef CURL_DISABLE_LIBCURL_OPTION
- warnf(global,
- "--libcurl option was disabled at build-time");
- err = PARAM_OPTION_UNKNOWN;
- break;
+ warnf(global,
+ "--libcurl option was disabled at build-time");
+ err = PARAM_OPTION_UNKNOWN;
#else
- GetStr(&global->libcurl, nextarg);
- break;
+ err = getstr(&global->libcurl, nextarg, DENY_BLANK);
#endif
- case '#': /* --raw */
- config->raw = toggle;
- break;
- case '0': /* --post301 */
- config->post301 = toggle;
- break;
- case '1': /* --no-keepalive */
- config->nokeepalive = (!toggle)?TRUE:FALSE;
- break;
- case '3': /* --keepalive-time */
- err = str2unum(&config->alivetime, nextarg);
- break;
- case '4': /* --post302 */
- config->post302 = toggle;
- break;
- case 'I': /* --post303 */
- config->post303 = toggle;
- break;
- case '5': /* --noproxy */
- /* This specifies the noproxy list */
- GetStr(&config->noproxy, nextarg);
- break;
- case '7': /* --socks5-gssapi-nec */
- config->socks5_gssapi_nec = toggle;
- break;
- case '8': /* --proxy1.0 */
- /* http 1.0 proxy */
- GetStr(&config->proxy, nextarg);
- config->proxyver = CURLPROXY_HTTP_1_0;
- break;
- case '9': /* --tftp-blksize */
- err = str2unum(&config->tftp_blksize, nextarg);
- break;
- case 'A': /* --mail-from */
- GetStr(&config->mail_from, nextarg);
- break;
- case 'B': /* --mail-rcpt */
- /* append receiver to a list */
- err = add2list(&config->mail_rcpt, nextarg);
- break;
- case 'C': /* --ftp-pret */
- config->ftp_pret = toggle;
- break;
- case 'D': /* --proto */
- config->proto_present = TRUE;
- err = proto2num(config, built_in_protos, &config->proto_str, nextarg);
- break;
- case 'E': /* --proto-redir */
- config->proto_redir_present = TRUE;
- if(proto2num(config, redir_protos, &config->proto_redir_str,
- nextarg)) {
- err = PARAM_BAD_USE;
- break;
- }
- break;
- case 'F': /* --resolve */
- err = add2list(&config->resolve, nextarg);
- break;
- case 'G': /* --delegation LEVEL */
- config->gssapi_delegation = delegation(config, nextarg);
- break;
- case 'H': /* --mail-auth */
- GetStr(&config->mail_auth, nextarg);
- break;
- case 'J': /* --metalink */
- errorf(global, "--metalink is disabled");
+ break;
+ case C_RAW: /* --raw */
+ config->raw = toggle;
+ break;
+ case C_KEEPALIVE: /* --keepalive */
+ config->nokeepalive = (!toggle)?TRUE:FALSE;
+ break;
+ case C_KEEPALIVE_TIME: /* --keepalive-time */
+ err = str2unum(&config->alivetime, nextarg);
+ break;
+ case C_POST301: /* --post301 */
+ config->post301 = toggle;
+ break;
+ case C_POST302: /* --post302 */
+ config->post302 = toggle;
+ break;
+ case C_POST303: /* --post303 */
+ config->post303 = toggle;
+ break;
+ case C_NOPROXY: /* --noproxy */
+ /* This specifies the noproxy list */
+ err = getstr(&config->noproxy, nextarg, ALLOW_BLANK);
+ break;
+ case C_SOCKS5_GSSAPI_NEC: /* --socks5-gssapi-nec */
+ config->socks5_gssapi_nec = toggle;
+ break;
+ case C_PROXY1_0: /* --proxy1.0 */
+ /* http 1.0 proxy */
+ err = getstr(&config->proxy, nextarg, DENY_BLANK);
+ config->proxyver = CURLPROXY_HTTP_1_0;
+ break;
+ case C_TFTP_BLKSIZE: /* --tftp-blksize */
+ err = str2unum(&config->tftp_blksize, nextarg);
+ break;
+ case C_MAIL_FROM: /* --mail-from */
+ err = getstr(&config->mail_from, nextarg, DENY_BLANK);
+ break;
+ case C_MAIL_RCPT: /* --mail-rcpt */
+ /* append receiver to a list */
+ err = add2list(&config->mail_rcpt, nextarg);
+ break;
+ case C_FTP_PRET: /* --ftp-pret */
+ config->ftp_pret = toggle;
+ break;
+ case C_PROTO: /* --proto */
+ config->proto_present = TRUE;
+ err = proto2num(config, built_in_protos, &config->proto_str, nextarg);
+ break;
+ case C_PROTO_REDIR: /* --proto-redir */
+ config->proto_redir_present = TRUE;
+ if(proto2num(config, redir_protos, &config->proto_redir_str,
+ nextarg))
err = PARAM_BAD_USE;
- break;
- case '6': /* --sasl-authzid */
- GetStr(&config->sasl_authzid, nextarg);
- break;
- case 'K': /* --sasl-ir */
- config->sasl_ir = toggle;
- break;
- case 'L': /* --test-event */
+ break;
+ case C_RESOLVE: /* --resolve */
+ err = add2list(&config->resolve, nextarg);
+ break;
+ case C_DELEGATION: /* --delegation */
+ config->gssapi_delegation = delegation(config, nextarg);
+ break;
+ case C_MAIL_AUTH: /* --mail-auth */
+ err = getstr(&config->mail_auth, nextarg, DENY_BLANK);
+ break;
+ case C_METALINK: /* --metalink */
+ errorf(global, "--metalink is disabled");
+ err = PARAM_BAD_USE;
+ break;
+ case C_SASL_AUTHZID: /* --sasl-authzid */
+ err = getstr(&config->sasl_authzid, nextarg, DENY_BLANK);
+ break;
+ case C_SASL_IR: /* --sasl-ir */
+ config->sasl_ir = toggle;
+ break;
+ case C_TEST_EVENT: /* --test-event */
#ifdef CURLDEBUG
- global->test_event_based = toggle;
+ global->test_event_based = toggle;
#else
- warnf(global, "--test-event is ignored unless a debug build");
+ warnf(global, "--test-event is ignored unless a debug build");
#endif
- break;
- case 'M': /* --unix-socket */
- config->abstract_unix_socket = FALSE;
- GetStr(&config->unix_socket_path, nextarg);
- break;
- case 'N': /* --path-as-is */
- config->path_as_is = toggle;
- break;
- case 'O': /* --proxy-service-name */
- GetStr(&config->proxy_service_name, nextarg);
- break;
- case 'P': /* --service-name */
- GetStr(&config->service_name, nextarg);
- break;
- case 'Q': /* --proto-default */
- GetStr(&config->proto_default, nextarg);
+ break;
+ case C_UNIX_SOCKET: /* --unix-socket */
+ config->abstract_unix_socket = FALSE;
+ err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
+ break;
+ case C_PATH_AS_IS: /* --path-as-is */
+ config->path_as_is = toggle;
+ break;
+ case C_PROXY_SERVICE_NAME: /* --proxy-service-name */
+ err = getstr(&config->proxy_service_name, nextarg, DENY_BLANK);
+ break;
+ case C_SERVICE_NAME: /* --service-name */
+ err = getstr(&config->service_name, nextarg, DENY_BLANK);
+ break;
+ case C_PROTO_DEFAULT: /* --proto-default */
+ err = getstr(&config->proto_default, nextarg, DENY_BLANK);
+ if(!err)
err = check_protocol(config->proto_default);
- break;
- case 'R': /* --expect100-timeout */
- err = secs2ms(&config->expect100timeout_ms, nextarg);
- break;
- case 'S': /* --tftp-no-options */
- config->tftp_no_options = toggle;
- break;
- case 'U': /* --connect-to */
- err = add2list(&config->connect_to, nextarg);
- break;
- case 'W': /* --abstract-unix-socket */
- config->abstract_unix_socket = TRUE;
- GetStr(&config->unix_socket_path, nextarg);
- break;
- case 'X': /* --tls-max */
- err = str2tls_max(&config->ssl_version_max, nextarg);
- break;
- case 'Y': /* --suppress-connect-headers */
- config->suppress_connect_headers = toggle;
- break;
- case 'Z': /* --compressed-ssh */
- config->ssh_compression = toggle;
- break;
- case '~': /* --happy-eyeballs-timeout-ms */
- err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
- /* 0 is a valid value for this timeout */
- break;
- case '%': /* --trace-ids */
- global->traceids = toggle;
- break;
- case '&': /* --trace-config */
- if(set_trace_config(global, nextarg)) {
- err = PARAM_NO_MEM;
- }
- break;
- }
break;
- case '#':
- switch(subletter) {
- case 'm': /* --progress-meter */
- global->noprogress = !toggle;
- break;
- default: /* --progress-bar */
- global->progressmode =
- toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
- break;
- }
+ case C_EXPECT100_TIMEOUT: /* --expect100-timeout */
+ err = secs2ms(&config->expect100timeout_ms, nextarg);
break;
- case ':':
- switch(subletter) {
- case 'a': /* --variable */
- err = setvariable(global, nextarg);
- break;
- default: /* --next */
- err = PARAM_NEXT_OPERATION;
- break;
- }
+ case C_TFTP_NO_OPTIONS: /* --tftp-no-options */
+ config->tftp_no_options = toggle;
break;
- case '0': /* --http* options */
- switch(subletter) {
- case '\0':
- /* HTTP version 1.0 */
- sethttpver(global, config, CURL_HTTP_VERSION_1_0);
- break;
- case '1':
- /* HTTP version 1.1 */
- sethttpver(global, config, CURL_HTTP_VERSION_1_1);
- break;
- case '2':
- /* HTTP version 2.0 */
- if(!feature_http2)
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- sethttpver(global, config, CURL_HTTP_VERSION_2_0);
- break;
- case '3': /* --http2-prior-knowledge */
- /* HTTP version 2.0 over clean TCP */
- if(!feature_http2)
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
- break;
- case '4': /* --http3 */
- /* Try HTTP/3, allow fallback */
- if(!feature_http3) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ case C_CONNECT_TO: /* --connect-to */
+ err = add2list(&config->connect_to, nextarg);
+ break;
+ case C_ABSTRACT_UNIX_SOCKET: /* --abstract-unix-socket */
+ config->abstract_unix_socket = TRUE;
+ err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK);
+ break;
+ case C_TLS_MAX: /* --tls-max */
+ err = str2tls_max(&config->ssl_version_max, nextarg);
+ break;
+ case C_SUPPRESS_CONNECT_HEADERS: /* --suppress-connect-headers */
+ config->suppress_connect_headers = toggle;
+ break;
+ case C_COMPRESSED_SSH: /* --compressed-ssh */
+ config->ssh_compression = toggle;
+ break;
+ case C_HAPPY_EYEBALLS_TIMEOUT_MS: /* --happy-eyeballs-timeout-ms */
+ err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
+ /* 0 is a valid value for this timeout */
+ break;
+ case C_TRACE_IDS: /* --trace-ids */
+ global->traceids = toggle;
+ break;
+ case C_TRACE_CONFIG: /* --trace-config */
+ if(set_trace_config(global, nextarg))
+ err = PARAM_NO_MEM;
+ break;
+ case C_PROGRESS_METER: /* --progress-meter */
+ global->noprogress = !toggle;
+ break;
+ case C_PROGRESS_BAR: /* --progress-bar */
+ global->progressmode = toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
+ break;
+ case C_VARIABLE: /* --Variable */
+ err = setvariable(global, nextarg);
+ break;
+ case C_NEXT: /* --next */
+ err = PARAM_NEXT_OPERATION;
+ break;
+ case C_HTTP1_0: /* --http1.0 */
+ /* HTTP version 1.0 */
+ sethttpver(global, config, CURL_HTTP_VERSION_1_0);
+ break;
+ case C_HTTP1_1: /* --http1.1 */
+ /* HTTP version 1.1 */
+ sethttpver(global, config, CURL_HTTP_VERSION_1_1);
+ break;
+ case C_HTTP2: /* --http2 */
+ /* HTTP version 2.0 */
+ if(!feature_http2)
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ sethttpver(global, config, CURL_HTTP_VERSION_2_0);
+ break;
+ case C_HTTP2_PRIOR_KNOWLEDGE: /* --http2-prior-knowledge */
+ /* HTTP version 2.0 over clean TCP */
+ if(!feature_http2)
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
+ sethttpver(global, config, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
+ break;
+ case C_HTTP3: /* --http3: */
+ /* Try HTTP/3, allow fallback */
+ if(!feature_http3)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
sethttpver(global, config, CURL_HTTP_VERSION_3);
- break;
- case '5': /* --http3-only */
- /* Try HTTP/3 without fallback */
- if(!feature_http3) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
+ break;
+ case C_HTTP3_ONLY: /* --http3-only */
+ /* Try HTTP/3 without fallback */
+ if(!feature_http3)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
sethttpver(global, config, CURL_HTTP_VERSION_3ONLY);
- break;
- case '9':
- /* Allow HTTP/0.9 responses! */
- config->http09_allowed = toggle;
- break;
- case 'a':
- /* --proxy-http2 */
- if(!feature_httpsproxy || !feature_http2)
- return PARAM_LIBCURL_DOESNT_SUPPORT;
+ break;
+ case C_HTTP0_9: /* --http0.9 */
+ /* Allow HTTP/0.9 responses! */
+ config->http09_allowed = toggle;
+ break;
+ case C_PROXY_HTTP2: /* --proxy-http2 */
+ if(!feature_httpsproxy || !feature_http2)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
config->proxyver = CURLPROXY_HTTPS2;
- break;
- }
break;
- case '1': /* --tlsv1* options */
- switch(subletter) {
- case '\0':
- /* TLS version 1.x */
- config->ssl_version = CURL_SSLVERSION_TLSv1;
- break;
- case '0':
- /* TLS version 1.0 */
- config->ssl_version = CURL_SSLVERSION_TLSv1_0;
- break;
- case '1':
- /* TLS version 1.1 */
- config->ssl_version = CURL_SSLVERSION_TLSv1_1;
- break;
- case '2':
- /* TLS version 1.2 */
- config->ssl_version = CURL_SSLVERSION_TLSv1_2;
- break;
- case '3':
- /* TLS version 1.3 */
- config->ssl_version = CURL_SSLVERSION_TLSv1_3;
- break;
- case 'A': /* --tls13-ciphers */
- GetStr(&config->cipher13_list, nextarg);
- break;
- case 'B': /* --proxy-tls13-ciphers */
- GetStr(&config->proxy_cipher13_list, nextarg);
- break;
- }
+ case C_TLSV1: /* --tlsv1 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1;
break;
- case '2':
- /* SSL version 2 */
+ case C_TLSV1_0: /* --tlsv1.0 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_0;
+ break;
+ case C_TLSV1_1: /* --tlsv1.1 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_1;
+ break;
+ case C_TLSV1_2: /* --tlsv1.2 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_2;
+ break;
+ case C_TLSV1_3: /* --tlsv1.3 */
+ config->ssl_version = CURL_SSLVERSION_TLSv1_3;
+ break;
+ case C_TLS13_CIPHERS: /* --tls13-ciphers */
+ err = getstr(&config->cipher13_list, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_TLS13_CIPHERS: /* --proxy-tls13-ciphers */
+ err = getstr(&config->proxy_cipher13_list, nextarg, DENY_BLANK);
+ break;
+ case C_SSLV2: /* --sslv2 */
warnf(global, "Ignores instruction to use SSLv2");
break;
- case '3':
- /* SSL version 3 */
+ case C_SSLV3: /* --sslv3 */
warnf(global, "Ignores instruction to use SSLv3");
break;
- case '4':
- /* IPv4 */
+ case C_IPV4: /* --ipv4 */
config->ip_version = CURL_IPRESOLVE_V4;
break;
- case '6':
- /* IPv6 */
+ case C_IPV6: /* --ipv6 */
config->ip_version = CURL_IPRESOLVE_V6;
break;
- case 'a':
+ case C_APPEND: /* --append */
/* This makes the FTP sessions use APPE instead of STOR */
config->ftp_append = toggle;
break;
- case 'A':
- /* This specifies the User-Agent name */
- GetStr(&config->useragent, nextarg);
+ case C_USER_AGENT: /* --user-agent */
+ err = getstr(&config->useragent, nextarg, ALLOW_BLANK);
break;
- case 'b':
- switch(subletter) {
- case 'a': /* --alt-svc */
- if(!feature_altsvc)
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- else
- GetStr(&config->altsvc, nextarg);
- break;
- case 'b': /* --hsts */
- if(!feature_hsts)
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- else
- GetStr(&config->hsts, nextarg);
+ case C_ALT_SVC: /* --alt-svc */
+ if(!feature_altsvc)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ err = getstr(&config->altsvc, nextarg, ALLOW_BLANK);
+ break;
+ case C_HSTS: /* --hsts */
+ if(!feature_hsts)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ err = getstr(&config->hsts, nextarg, ALLOW_BLANK);
+ break;
+ case C_COOKIE: /* --cookie */
+ if(strchr(nextarg, '=')) {
+ /* A cookie string must have a =-letter */
+ err = add2list(&config->cookies, nextarg);
break;
- default: /* --cookie string coming up: */
- if(nextarg[0] == '@') {
- nextarg++;
- }
- else if(strchr(nextarg, '=')) {
- /* A cookie string must have a =-letter */
- err = add2list(&config->cookies, nextarg);
- break;
- }
+ }
+ else {
/* We have a cookie file to read from! */
err = add2list(&config->cookiefiles, nextarg);
}
break;
- case 'B':
- /* use ASCII/text when transferring */
+ case C_USE_ASCII: /* --use-ascii */
config->use_ascii = toggle;
break;
- case 'c':
- /* get the file name to dump all cookies in */
- GetStr(&config->cookiejar, nextarg);
+ case C_COOKIE_JAR: /* --cookie-jar */
+ err = getstr(&config->cookiejar, nextarg, DENY_BLANK);
break;
- case 'C':
+ case C_CONTINUE_AT: /* --continue-at */
/* This makes us continue an ftp transfer at given position */
if(strcmp(nextarg, "-")) {
err = str2offset(&config->resume_from, nextarg);
- if(err)
- break;
config->resume_from_current = FALSE;
}
else {
@@ -1706,158 +2016,21 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
}
config->use_resume = TRUE;
break;
- case 'd':
- /* postfield data */
- {
- char *postdata = NULL;
- FILE *file;
- size_t size = 0;
- bool raw_mode = (subletter == 'r');
-
- if(subletter == 'g') { /* --url-query */
-#define MAX_QUERY_LEN 100000 /* larger is not likely to ever work */
- char *query;
- struct curlx_dynbuf dyn;
- curlx_dyn_init(&dyn, MAX_QUERY_LEN);
-
- if(*nextarg == '+') {
- /* use without encoding */
- query = strdup(&nextarg[1]);
- if(!query) {
- err = PARAM_NO_MEM;
- break;
- }
- }
- else {
- err = data_urlencode(global, nextarg, &query, &size);
- if(err)
- break;
- }
-
- if(config->query) {
- CURLcode result =
- curlx_dyn_addf(&dyn, "%s&%s", config->query, query);
- free(query);
- if(result) {
- err = PARAM_NO_MEM;
- break;
- }
- free(config->query);
- config->query = curlx_dyn_ptr(&dyn);
- }
- else
- config->query = query;
-
- break; /* this is not a POST argument at all */
- }
- else if(subletter == 'e') { /* --data-urlencode */
- err = data_urlencode(global, nextarg, &postdata, &size);
- if(err)
- break;
- }
- else if('@' == *nextarg && !raw_mode) {
- /* the data begins with a '@' letter, it means that a file name
- or - (stdin) follows */
- nextarg++; /* pass the @ */
-
- if(!strcmp("-", nextarg)) {
- file = stdin;
- if(subletter == 'b') /* forced data-binary */
- set_binmode(stdin);
- }
- else {
- file = fopen(nextarg, "rb");
- if(!file) {
- errorf(global, "Failed to open %s", nextarg);
- err = PARAM_READ_ERROR;
- break;
- }
- }
-
- if((subletter == 'b') || /* --data-binary */
- (subletter == 'f') /* --json */)
- /* forced binary */
- err = file2memory(&postdata, &size, file);
- else {
- err = file2string(&postdata, file);
- if(postdata)
- size = strlen(postdata);
- }
-
- if(file && (file != stdin))
- fclose(file);
- if(err)
- break;
-
- if(!postdata) {
- /* no data from the file, point to a zero byte string to make this
- get sent as a POST anyway */
- postdata = strdup("");
- if(!postdata) {
- err = PARAM_NO_MEM;
- break;
- }
- }
- }
- else {
- GetStr(&postdata, nextarg);
- if(postdata)
- size = strlen(postdata);
- }
- if(subletter == 'f')
- config->jsoned = TRUE;
-
- if(config->postfields) {
- /* we already have a string, we append this one with a separating
- &-letter */
- char *oldpost = config->postfields;
- curl_off_t oldlen = config->postfieldsize;
- curl_off_t newlen = oldlen + curlx_uztoso(size) + 2;
- config->postfields = malloc((size_t)newlen);
- if(!config->postfields) {
- Curl_safefree(oldpost);
- Curl_safefree(postdata);
- err = PARAM_NO_MEM;
- break;
- }
- memcpy(config->postfields, oldpost, (size_t)oldlen);
- if(subletter != 'f') {
- /* skip this treatment for --json */
- /* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
- config->postfields[oldlen] = '\x26';
- memcpy(&config->postfields[oldlen + 1], postdata, size);
- config->postfields[oldlen + 1 + size] = '\0';
- config->postfieldsize += size + 1;
- }
- else {
- memcpy(&config->postfields[oldlen], postdata, size);
- config->postfields[oldlen + size] = '\0';
- config->postfieldsize += size;
- }
- Curl_safefree(oldpost);
- Curl_safefree(postdata);
- }
- else {
- config->postfields = postdata;
- config->postfieldsize = curlx_uztoso(size);
- }
- }
- /*
- We can't set the request type here, as this data might be used in
- a simple GET if -G is used. Already or soon.
-
- if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq)) {
- Curl_safefree(postdata);
- return PARAM_BAD_USE;
- }
- */
- break;
- case 'D':
- /* dump-header to given file name */
- GetStr(&config->headerfile, nextarg);
+ case C_DATA: /* --data */
+ case C_DATA_ASCII: /* --data-ascii */
+ case C_DATA_BINARY: /* --data-binary */
+ case C_DATA_URLENCODE: /* --data-urlencode */
+ case C_JSON: /* --json */
+ case C_DATA_RAW: /* --data-raw */
+ err = set_data(cmd, nextarg, global, config);
+ break;
+ case C_URL_QUERY: /* --url-query */
+ err = url_query(nextarg, global, config);
break;
- case 'e':
- {
+ case C_DUMP_HEADER: /* --dump-header */
+ err = getstr(&config->headerfile, nextarg, DENY_BLANK);
+ break;
+ case C_REFERER: { /* --referer */
char *ptr = strstr(nextarg, ";auto");
if(ptr) {
/* Automatic referer requested, this may be combined with a
@@ -1868,322 +2041,263 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
else
config->autoreferer = FALSE;
ptr = *nextarg ? nextarg : NULL;
- GetStr(&config->referer, ptr);
+ err = getstr(&config->referer, ptr, ALLOW_BLANK);
}
- break;
- case 'E':
- switch(subletter) {
- case '\0': /* certificate file */
- cleanarg(clearthis);
- GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
- break;
- case 'a': /* --cacert CA info PEM file */
- GetStr(&config->cacert, nextarg);
- break;
- case 'G': /* --ca-native */
- config->native_ca_store = toggle;
- break;
- case 'H': /* --proxy-ca-native */
- config->proxy_native_ca_store = toggle;
- break;
- case 'b': /* cert file type */
- GetStr(&config->cert_type, nextarg);
- break;
- case 'c': /* private key file */
- GetStr(&config->key, nextarg);
- break;
- case 'd': /* private key file type */
- GetStr(&config->key_type, nextarg);
- break;
- case 'e': /* private key passphrase */
- GetStr(&config->key_passwd, nextarg);
- cleanarg(clearthis);
- break;
- case 'f': /* crypto engine */
- GetStr(&config->engine, nextarg);
- if(config->engine && curl_strequal(config->engine, "list")) {
- err = PARAM_ENGINES_REQUESTED;
- break;
- }
- break;
- case 'g': /* CA cert directory */
- GetStr(&config->capath, nextarg);
- break;
- case 'h': /* --pubkey public key file */
- GetStr(&config->pubkey, nextarg);
- break;
- case 'i': /* --hostpubmd5 md5 of the host public key */
- GetStr(&config->hostpubmd5, nextarg);
- if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32) {
+ break;
+ case C_CERT: /* --cert */
+ cleanarg(clearthis);
+ GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
+ break;
+ case C_CACERT: /* --cacert */
+ err = getstr(&config->cacert, nextarg, DENY_BLANK);
+ break;
+ case C_CA_NATIVE: /* --ca-native */
+ config->native_ca_store = toggle;
+ break;
+ case C_PROXY_CA_NATIVE: /* --proxy-ca-native */
+ config->proxy_native_ca_store = toggle;
+ break;
+ case C_CERT_TYPE: /* --cert-type */
+ err = getstr(&config->cert_type, nextarg, DENY_BLANK);
+ break;
+ case C_KEY: /* --key */
+ err = getstr(&config->key, nextarg, DENY_BLANK);
+ break;
+ case C_KEY_TYPE: /* --key-type */
+ err = getstr(&config->key_type, nextarg, DENY_BLANK);
+ break;
+ case C_PASS: /* --pass */
+ err = getstr(&config->key_passwd, nextarg, DENY_BLANK);
+ cleanarg(clearthis);
+ break;
+ case C_ENGINE: /* --engine */
+ err = getstr(&config->engine, nextarg, DENY_BLANK);
+ if(!err &&
+ config->engine && !strcmp(config->engine, "list")) {
+ err = PARAM_ENGINES_REQUESTED;
+ }
+ break;
+ case C_CAPATH: /* --capath */
+ err = getstr(&config->capath, nextarg, DENY_BLANK);
+ break;
+ case C_PUBKEY: /* --pubkey */
+ err = getstr(&config->pubkey, nextarg, DENY_BLANK);
+ break;
+ case C_HOSTPUBMD5: /* --hostpubmd5 */
+ err = getstr(&config->hostpubmd5, nextarg, DENY_BLANK);
+ if(!err) {
+ if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
err = PARAM_BAD_USE;
- break;
- }
- break;
- case 'F': /* --hostpubsha256 sha256 of the host public key */
- GetStr(&config->hostpubsha256, nextarg);
- break;
- case 'j': /* CRL file */
- GetStr(&config->crlfile, nextarg);
- break;
- case 'k': /* TLS username */
- if(!feature_tls_srp) {
- cleanarg(clearthis);
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- GetStr(&config->tls_username, nextarg);
- cleanarg(clearthis);
- break;
- case 'l': /* TLS password */
- if(!feature_tls_srp) {
- cleanarg(clearthis);
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- GetStr(&config->tls_password, nextarg);
- cleanarg(clearthis);
- break;
- case 'm': /* TLS authentication type */
- if(!feature_tls_srp) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- GetStr(&config->tls_authtype, nextarg);
- if(!curl_strequal(config->tls_authtype, "SRP")) {
+ }
+ break;
+ case C_HOSTPUBSHA256: /* --hostpubsha256 */
+ err = getstr(&config->hostpubsha256, nextarg, DENY_BLANK);
+ break;
+ case C_CRLFILE: /* --crlfile */
+ err = getstr(&config->crlfile, nextarg, DENY_BLANK);
+ break;
+ case C_TLSUSER: /* --tlsuser */
+ if(!feature_tls_srp)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ err = getstr(&config->tls_username, nextarg, DENY_BLANK);
+ cleanarg(clearthis);
+ break;
+ case C_TLSPASSWORD: /* --tlspassword */
+ if(!feature_tls_srp)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ err = getstr(&config->tls_password, nextarg, ALLOW_BLANK);
+ cleanarg(clearthis);
+ break;
+ case C_TLSAUTHTYPE: /* --tlsauthtype */
+ if(!feature_tls_srp)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else {
+ err = getstr(&config->tls_authtype, nextarg, DENY_BLANK);
+ if(!err && strcmp(config->tls_authtype, "SRP"))
err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
- break;
- }
- break;
- case 'n': /* no empty SSL fragments, --ssl-allow-beast */
- if(feature_ssl)
- config->ssl_allow_beast = toggle;
- break;
-
- case 'o': /* --ssl-auto-client-cert */
- if(feature_ssl)
- config->ssl_auto_client_cert = toggle;
- break;
-
- case 'O': /* --proxy-ssl-auto-client-cert */
- if(feature_ssl)
- config->proxy_ssl_auto_client_cert = toggle;
- break;
-
- case 'p': /* Pinned public key DER file */
- GetStr(&config->pinnedpubkey, nextarg);
- break;
-
- case 'P': /* proxy pinned public key */
- GetStr(&config->proxy_pinnedpubkey, nextarg);
- break;
-
- case 'q': /* --cert-status */
- config->verifystatus = TRUE;
- break;
-
- case 'Q': /* --doh-cert-status */
- config->doh_verifystatus = TRUE;
- break;
-
- case 'r': /* --false-start */
- config->falsestart = TRUE;
- break;
-
- case 's': /* --ssl-no-revoke */
- if(feature_ssl)
- config->ssl_no_revoke = TRUE;
- break;
-
- case 'S': /* --ssl-revoke-best-effort */
- if(feature_ssl)
- config->ssl_revoke_best_effort = TRUE;
- break;
-
- case 't': /* --tcp-fastopen */
- config->tcp_fastopen = TRUE;
- break;
-
- case 'u': /* TLS username for proxy */
- cleanarg(clearthis);
- if(!feature_tls_srp) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- GetStr(&config->proxy_tls_username, nextarg);
- break;
-
- case 'v': /* TLS password for proxy */
- cleanarg(clearthis);
- if(!feature_tls_srp) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- GetStr(&config->proxy_tls_password, nextarg);
- break;
-
- case 'w': /* TLS authentication type for proxy */
- if(!feature_tls_srp) {
- err = PARAM_LIBCURL_DOESNT_SUPPORT;
- break;
- }
- GetStr(&config->proxy_tls_authtype, nextarg);
- if(!curl_strequal(config->proxy_tls_authtype, "SRP")) {
+ }
+ break;
+ case C_SSL_ALLOW_BEAST: /* --ssl-allow-beast */
+ if(feature_ssl)
+ config->ssl_allow_beast = toggle;
+ break;
+ case C_SSL_AUTO_CLIENT_CERT: /* --ssl-auto-client-cert */
+ if(feature_ssl)
+ config->ssl_auto_client_cert = toggle;
+ break;
+ case C_PROXY_SSL_AUTO_CLIENT_CERT: /* --proxy-ssl-auto-client-cert */
+ if(feature_ssl)
+ config->proxy_ssl_auto_client_cert = toggle;
+ break;
+ case C_PINNEDPUBKEY: /* --pinnedpubkey */
+ err = getstr(&config->pinnedpubkey, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_PINNEDPUBKEY: /* --proxy-pinnedpubkey */
+ err = getstr(&config->proxy_pinnedpubkey, nextarg, DENY_BLANK);
+ break;
+ case C_CERT_STATUS: /* --cert-status */
+ config->verifystatus = TRUE;
+ break;
+ case C_DOH_CERT_STATUS: /* --doh-cert-status */
+ config->doh_verifystatus = TRUE;
+ break;
+ case C_FALSE_START: /* --false-start */
+ config->falsestart = TRUE;
+ break;
+ case C_SSL_NO_REVOKE: /* --ssl-no-revoke */
+ if(feature_ssl)
+ config->ssl_no_revoke = TRUE;
+ break;
+ case C_SSL_REVOKE_BEST_EFFORT: /* --ssl-revoke-best-effort */
+ if(feature_ssl)
+ config->ssl_revoke_best_effort = TRUE;
+ break;
+ case C_TCP_FASTOPEN: /* --tcp-fastopen */
+ config->tcp_fastopen = TRUE;
+ break;
+ case C_PROXY_TLSUSER: /* --proxy-tlsuser */
+ cleanarg(clearthis);
+ if(!feature_tls_srp)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ err = getstr(&config->proxy_tls_username, nextarg, ALLOW_BLANK);
+ break;
+ case C_PROXY_TLSPASSWORD: /* --proxy-tlspassword */
+ cleanarg(clearthis);
+ if(!feature_tls_srp)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else
+ err = getstr(&config->proxy_tls_password, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_TLSAUTHTYPE: /* --proxy-tlsauthtype */
+ if(!feature_tls_srp)
+ err = PARAM_LIBCURL_DOESNT_SUPPORT;
+ else {
+ err = getstr(&config->proxy_tls_authtype, nextarg, DENY_BLANK);
+ if(!err && strcmp(config->proxy_tls_authtype, "SRP"))
err = PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
- break;
- }
- break;
-
- case 'x': /* certificate file for proxy */
- cleanarg(clearthis);
- GetFileAndPassword(nextarg, &config->proxy_cert,
- &config->proxy_key_passwd);
- break;
-
- case 'y': /* cert file type for proxy */
- GetStr(&config->proxy_cert_type, nextarg);
- break;
-
- case 'z': /* private key file for proxy */
- GetStr(&config->proxy_key, nextarg);
- break;
-
- case '0': /* private key file type for proxy */
- GetStr(&config->proxy_key_type, nextarg);
- break;
-
- case '1': /* private key passphrase for proxy */
- GetStr(&config->proxy_key_passwd, nextarg);
- cleanarg(clearthis);
- break;
-
- case '2': /* ciphers for proxy */
- GetStr(&config->proxy_cipher_list, nextarg);
- break;
-
- case '3': /* CRL file for proxy */
- GetStr(&config->proxy_crlfile, nextarg);
- break;
-
- case '4': /* no empty SSL fragments for proxy */
- if(feature_ssl)
- config->proxy_ssl_allow_beast = toggle;
- break;
-
- case '5': /* --login-options */
- GetStr(&config->login_options, nextarg);
- break;
-
- case '6': /* CA info PEM file for proxy */
- GetStr(&config->proxy_cacert, nextarg);
- break;
-
- case '7': /* CA cert directory for proxy */
- GetStr(&config->proxy_capath, nextarg);
- break;
-
- case '8': /* allow insecure SSL connects for proxy */
- config->proxy_insecure_ok = toggle;
- break;
-
- case '9': /* --proxy-tlsv1 */
- /* TLS version 1 for proxy */
- config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
- break;
-
- case 'A':
- /* --socks5-basic */
- if(toggle)
- config->socks5_auth |= CURLAUTH_BASIC;
- else
- config->socks5_auth &= ~CURLAUTH_BASIC;
- break;
-
- case 'B':
- /* --socks5-gssapi */
- if(toggle)
- config->socks5_auth |= CURLAUTH_GSSAPI;
- else
- config->socks5_auth &= ~CURLAUTH_GSSAPI;
- break;
-
- case 'C':
- GetStr(&config->etag_save_file, nextarg);
- break;
-
- case 'D':
- GetStr(&config->etag_compare_file, nextarg);
- break;
-
- case 'E':
- GetStr(&config->ssl_ec_curves, nextarg);
- break;
-
- default: /* unknown flag */
- err = PARAM_OPTION_UNKNOWN;
- break;
}
break;
- case 'f':
- switch(subletter) {
- case 'a': /* --fail-early */
- global->fail_early = toggle;
- break;
- case 'b': /* --styled-output */
- global->styled_output = toggle;
- break;
- case 'c': /* --mail-rcpt-allowfails */
- config->mail_rcpt_allowfails = toggle;
- break;
- case 'd': /* --fail-with-body */
- config->failwithbody = toggle;
- break;
- case 'e': /* --remove-on-error */
- config->rm_partial = toggle;
- break;
- default: /* --fail (hard on errors) */
- config->failonerror = toggle;
- break;
+ case C_PROXY_CERT: /* --proxy-cert */
+ cleanarg(clearthis);
+ GetFileAndPassword(nextarg, &config->proxy_cert,
+ &config->proxy_key_passwd);
+ break;
+ case C_PROXY_CERT_TYPE: /* --proxy-cert-type */
+ err = getstr(&config->proxy_cert_type, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_KEY: /* --proxy-key */
+ err = getstr(&config->proxy_key, nextarg, ALLOW_BLANK);
+ break;
+ case C_PROXY_KEY_TYPE: /* --proxy-key-type */
+ err = getstr(&config->proxy_key_type, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_PASS: /* --proxy-pass */
+ err = getstr(&config->proxy_key_passwd, nextarg, ALLOW_BLANK);
+ cleanarg(clearthis);
+ break;
+ case C_PROXY_CIPHERS: /* --proxy-ciphers */
+ err = getstr(&config->proxy_cipher_list, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_CRLFILE: /* --proxy-crlfile */
+ err = getstr(&config->proxy_crlfile, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_SSL_ALLOW_BEAST: /* --proxy-ssl-allow-beast */
+ if(feature_ssl)
+ config->proxy_ssl_allow_beast = toggle;
+ break;
+ case C_LOGIN_OPTIONS: /* --login-options */
+ err = getstr(&config->login_options, nextarg, ALLOW_BLANK);
+ break;
+ case C_PROXY_CACERT: /* --proxy-cacert */
+ err = getstr(&config->proxy_cacert, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_CAPATH: /* --proxy-capath */
+ err = getstr(&config->proxy_capath, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY_INSECURE: /* --proxy-insecure */
+ config->proxy_insecure_ok = toggle;
+ break;
+ case C_PROXY_TLSV1: /* --proxy-tlsv1 */
+ /* TLS version 1 for proxy */
+ config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
+ break;
+ case C_SOCKS5_BASIC: /* --socks5-basic */
+ if(toggle)
+ config->socks5_auth |= CURLAUTH_BASIC;
+ else
+ config->socks5_auth &= ~CURLAUTH_BASIC;
+ break;
+ case C_SOCKS5_GSSAPI: /* --socks5-gssapi */
+ if(toggle)
+ config->socks5_auth |= CURLAUTH_GSSAPI;
+ else
+ config->socks5_auth &= ~CURLAUTH_GSSAPI;
+ break;
+ case C_ETAG_SAVE: /* --etag-save */
+ err = getstr(&config->etag_save_file, nextarg, DENY_BLANK);
+ break;
+ case C_ETAG_COMPARE: /* --etag-compare */
+ err = getstr(&config->etag_compare_file, nextarg, DENY_BLANK);
+ break;
+ case C_CURVES: /* --curves */
+ err = getstr(&config->ssl_ec_curves, nextarg, DENY_BLANK);
+ break;
+ case C_FAIL_EARLY: /* --fail-early */
+ global->fail_early = toggle;
+ break;
+ case C_STYLED_OUTPUT: /* --styled-output */
+ global->styled_output = toggle;
+ break;
+ case C_MAIL_RCPT_ALLOWFAILS: /* --mail-rcpt-allowfails */
+ config->mail_rcpt_allowfails = toggle;
+ break;
+ case C_FAIL_WITH_BODY: /* --fail-with-body */
+ config->failwithbody = toggle;
+ if(config->failonerror && config->failwithbody) {
+ errorf(config->global, "You must select either --fail or "
+ "--fail-with-body, not both.");
+ err = PARAM_BAD_USE;
}
+ break;
+ case C_REMOVE_ON_ERROR: /* --remove-on-error */
+ config->rm_partial = toggle;
+ break;
+ case C_FAIL: /* --fail */
+ config->failonerror = toggle;
if(config->failonerror && config->failwithbody) {
errorf(config->global, "You must select either --fail or "
"--fail-with-body, not both.");
err = PARAM_BAD_USE;
- break;
}
break;
- case 'F':
+ case C_FORM: /* --form */
+ case C_FORM_STRING: /* --form-string */
/* "form data" simulation, this is a little advanced so lets do our best
to sort this out slowly and carefully */
if(formparse(config,
nextarg,
&config->mimeroot,
&config->mimecurrent,
- (subletter == 's')?TRUE:FALSE)) { /* 's' is literal
- string */
+ (cmd == C_FORM_STRING)?TRUE:FALSE)) /* literal string */
err = PARAM_BAD_USE;
- break;
- }
- if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq)) {
+ else if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq))
err = PARAM_BAD_USE;
- break;
- }
break;
-
- case 'g': /* g disables URLglobbing */
+ case C_GLOBOFF: /* --globoff */
config->globoff = toggle;
break;
-
- case 'G': /* HTTP GET */
- if(subletter == 'a') { /* --request-target */
- GetStr(&config->request_target, nextarg);
- }
- else
- config->use_httpget = toggle;
+ case C_GET: /* --get */
+ config->use_httpget = toggle;
break;
-
- case 'h': /* h for help */
+ case C_REQUEST_TARGET: /* --request-target */
+ err = getstr(&config->request_target, nextarg, DENY_BLANK);
+ break;
+ case C_HELP: /* --help */
if(toggle) {
- if(nextarg) {
+ if(*nextarg) {
global->help_category = strdup(nextarg);
if(!global->help_category) {
err = PARAM_NO_MEM;
@@ -2191,11 +2305,11 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
}
}
err = PARAM_HELP_REQUESTED;
- break;
}
/* we now actually support --no-help too! */
break;
- case 'H':
+ case C_HEADER: /* --header */
+ case C_PROXY_HEADER: /* --proxy-header */
/* A custom header to append to a list */
if(nextarg[0] == '@') {
/* read many headers from a file or stdin */
@@ -2206,7 +2320,6 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(!file) {
errorf(global, "Failed to open %s", &nextarg[1]);
err = PARAM_READ_ERROR;
- break;
}
else {
err = file2memory(&string, &len, file);
@@ -2215,7 +2328,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
/* !checksrc! disable BANNEDFUNC 2 */
char *h = strtok(string, "\r\n");
while(h) {
- if(subletter == 'p') /* --proxy-header */
+ if(cmd == C_PROXY_HEADER) /* --proxy-header */
err = add2list(&config->proxyheaders, h);
else
err = add2list(&config->headers, h);
@@ -2227,115 +2340,97 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
}
if(!use_stdin)
fclose(file);
- if(err)
- break;
}
}
else {
- if(subletter == 'p') /* --proxy-header */
+ if(cmd == C_PROXY_HEADER) /* --proxy-header */
err = add2list(&config->proxyheaders, nextarg);
else
err = add2list(&config->headers, nextarg);
}
break;
- case 'i':
+ case C_INCLUDE: /* --include */
config->show_headers = toggle; /* show the headers as well in the
general output stream */
break;
- case 'j':
+ case C_JUNK_SESSION_COOKIES: /* --junk-session-cookies */
config->cookiesession = toggle;
break;
- case 'I': /* --head */
+ case C_HEAD: /* --head */
config->no_body = toggle;
config->show_headers = toggle;
if(SetHTTPrequest(config,
(config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
- &config->httpreq)) {
+ &config->httpreq))
err = PARAM_BAD_USE;
- break;
- }
break;
- case 'J': /* --remote-header-name */
+ case C_REMOTE_HEADER_NAME: /* --remote-header-name */
config->content_disposition = toggle;
break;
- case 'k': /* allow insecure SSL connects */
- if(subletter == 'd') /* --doh-insecure */
- config->doh_insecure_ok = toggle;
- else
- config->insecure_ok = toggle;
+ case C_INSECURE: /* --insecure */
+ config->insecure_ok = toggle;
break;
- case 'K': /* parse config file */
+ case C_DOH_INSECURE: /* --doh-insecure */
+ config->doh_insecure_ok = toggle;
+ break;
+ case C_CONFIG: /* --config */
if(parseconfig(nextarg, global)) {
errorf(global, "cannot read config from '%s'", nextarg);
err = PARAM_READ_ERROR;
- break;
}
break;
- case 'l':
+ case C_LIST_ONLY: /* --list-only */
config->dirlistonly = toggle; /* only list the names of the FTP dir */
break;
- case 'L':
+ case C_LOCATION_TRUSTED: /* --location-trusted */
+ /* Continue to send authentication (user+password) when following
+ * locations, even when hostname changed */
+ config->unrestricted_auth = toggle;
+ FALLTHROUGH();
+ case C_LOCATION: /* --location */
config->followlocation = toggle; /* Follow Location: HTTP headers */
- switch(subletter) {
- case 't':
- /* Continue to send authentication (user+password) when following
- * locations, even when hostname changed */
- config->unrestricted_auth = toggle;
- break;
- }
break;
- case 'm':
+ case C_MAX_TIME: /* --max-time */
/* specified max time */
err = secs2ms(&config->timeout_ms, nextarg);
break;
- case 'M': /* M for manual, huge help */
+ case C_MANUAL: /* --manual */
if(toggle) { /* --no-manual shows no manual... */
#ifndef USE_MANUAL
warnf(global,
"built-in manual was disabled at build-time");
#endif
err = PARAM_MANUAL_REQUESTED;
- break;
}
break;
- case 'n':
- switch(subletter) {
- case 'o': /* use .netrc or URL */
- config->netrc_opt = toggle;
- break;
- case 'e': /* netrc-file */
- GetStr(&config->netrc_file, nextarg);
- break;
- default:
- /* pick info from .netrc, if this is used for http, curl will
- automatically enforce user+password with the request */
- config->netrc = toggle;
- break;
- }
+ case C_NETRC_OPTIONAL: /* --netrc-optional */
+ config->netrc_opt = toggle;
+ break;
+ case C_NETRC_FILE: /* --netrc-file */
+ err = getstr(&config->netrc_file, nextarg, DENY_BLANK);
break;
- case 'N':
+ case C_NETRC: /* --netrc */
+ /* pick info from .netrc, if this is used for http, curl will
+ automatically enforce user+password with the request */
+ config->netrc = toggle;
+ break;
+ case C_BUFFER: /* --buffer */
/* disable the output I/O buffering. note that the option is called
--buffer but is mostly used in the negative form: --no-buffer */
config->nobuffer = longopt ? !toggle : TRUE;
break;
- case 'O': /* --remote-name */
- if(subletter == 'a') { /* --remote-name-all */
- config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
- break;
- }
- else if(subletter == 'b') { /* --output-dir */
- GetStr(&config->output_dir, nextarg);
- break;
- }
- else if(subletter == 'c') { /* --clobber / --no-clobber */
- config->file_clobber_mode = toggle ? CLOBBER_ALWAYS : CLOBBER_NEVER;
- break;
- }
- /* FALLTHROUGH */
- case 'o': /* --output */
+ case C_REMOTE_NAME_ALL: /* --remote-name-all */
+ config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
+ break;
+ case C_OUTPUT_DIR: /* --output-dir */
+ err = getstr(&config->output_dir, nextarg, DENY_BLANK);
+ break;
+ case C_CLOBBER: /* --clobber */
+ config->file_clobber_mode = toggle ? CLOBBER_ALWAYS : CLOBBER_NEVER;
+ break;
+ case C_OUTPUT: /* --output */
+ case C_REMOTE_NAME: /* --remote-name */
/* output file */
- {
- struct getout *url;
if(!config->url_out)
config->url_out = config->url_list;
if(config->url_out) {
@@ -2364,12 +2459,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
/* fill in the outfile */
if('o' == letter) {
- if(!*nextarg) {
- warnf(global, "output file name has no length");
- err = PARAM_BAD_USE;
- break;
- }
- GetStr(&url->outfile, nextarg);
+ err = getstr(&url->outfile, nextarg, DENY_BLANK);
url->flags &= ~GETOUT_USEREMOTE; /* switch off */
}
else {
@@ -2380,25 +2470,25 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
url->flags &= ~GETOUT_USEREMOTE; /* switch off */
}
url->flags |= GETOUT_OUTFILE;
- }
- break;
- case 'P':
+ break;
+ case C_FTP_PORT: /* --ftp-port */
/* This makes the FTP sessions use PORT instead of PASV */
/* use <eth0> or <192.168.10.10> style addresses. Anything except
this will make us try to get the "default" address.
NOTE: this is a changed behavior since the released 4.1!
*/
- GetStr(&config->ftpport, nextarg);
+ err = getstr(&config->ftpport, nextarg, DENY_BLANK);
break;
- case 'p':
+ case C_PROXYTUNNEL: /* --proxytunnel */
/* proxy tunnel for non-http protocols */
config->proxytunnel = toggle;
break;
- case 'q': /* if used first, already taken care of, we do it like
- this so we don't cause an error! */
+ case C_DISABLE: /* --disable */
+ /* if used first, already taken care of, we do it like this so we don't
+ cause an error! */
break;
- case 'Q':
+ case C_QUOTE: /* --quote */
/* QUOTE command to send to FTP server */
switch(nextarg[0]) {
case '-':
@@ -2416,34 +2506,33 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
break;
}
break;
- case 'r':
+ case C_RANGE: /* --range */
/* Specifying a range WITHOUT A DASH will create an illegal HTTP range
(and won't actually be range by definition). The man page previously
claimed that to be a good way, why this code is added to work-around
it. */
if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
char buffer[32];
- curl_off_t off;
- if(curlx_strtoofft(nextarg, NULL, 10, &off)) {
+ if(curlx_strtoofft(nextarg, NULL, 10, &value)) {
warnf(global, "unsupported range point");
err = PARAM_BAD_USE;
- break;
}
- warnf(global,
- "A specified range MUST include at least one dash (-). "
- "Appending one for you");
- msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
- Curl_safefree(config->range);
- config->range = strdup(buffer);
- if(!config->range) {
- err = PARAM_NO_MEM;
- break;
+ else {
+ warnf(global,
+ "A specified range MUST include at least one dash (-). "
+ "Appending one for you");
+ msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-",
+ value);
+ Curl_safefree(config->range);
+ config->range = strdup(buffer);
+ if(!config->range)
+ err = PARAM_NO_MEM;
}
}
else {
/* byte range requested */
const char *tmp_range = nextarg;
- while(*tmp_range != '\0') {
+ while(*tmp_range) {
if(!ISDIGIT(*tmp_range) && *tmp_range != '-' && *tmp_range != ',') {
warnf(global, "Invalid character is found in given range. "
"A specified range MUST have only digits in "
@@ -2453,27 +2542,25 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
}
tmp_range++;
}
- GetStr(&config->range, nextarg);
+ err = getstr(&config->range, nextarg, DENY_BLANK);
}
break;
- case 'R':
+ case C_REMOTE_TIME: /* --remote-time */
/* use remote file's time */
config->remote_time = toggle;
break;
- case 's': /* --silent */
+ case C_SILENT: /* --silent */
global->silent = toggle;
break;
- case 'S': /* --show-error */
+ case C_SHOW_ERROR: /* --show-error */
global->showerror = toggle;
break;
- case 't':
+ case C_TELNET_OPTION: /* --telnet-option */
/* Telnet options */
err = add2list(&config->telnet_options, nextarg);
break;
- case 'T':
+ case C_UPLOAD_FILE: /* --upload-file */
/* we are uploading */
- {
- struct getout *url;
if(!config->url_ul)
config->url_ul = config->url_list;
if(config->url_ul) {
@@ -2502,46 +2589,42 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
url->flags |= GETOUT_NOUPLOAD;
else {
/* "-" equals stdin, but keep the string around for now */
- GetStr(&url->infile, nextarg);
+ err = getstr(&url->infile, nextarg, DENY_BLANK);
}
- }
- break;
- case 'u':
+ break;
+ case C_USER: /* --user */
/* user:password */
- GetStr(&config->userpwd, nextarg);
+ err = getstr(&config->userpwd, nextarg, ALLOW_BLANK);
cleanarg(clearthis);
break;
- case 'U':
+ case C_PROXY_USER: /* --proxy-user */
/* Proxy user:password */
- GetStr(&config->proxyuserpwd, nextarg);
+ err = getstr(&config->proxyuserpwd, nextarg, ALLOW_BLANK);
cleanarg(clearthis);
break;
- case 'v':
+ case C_VERBOSE: /* --verbose */
if(toggle) {
/* the '%' thing here will cause the trace get sent to stderr */
Curl_safefree(global->trace_dump);
global->trace_dump = strdup("%");
- if(!global->trace_dump) {
+ if(!global->trace_dump)
err = PARAM_NO_MEM;
- break;
+ else {
+ if(global->tracetype && (global->tracetype != TRACE_PLAIN))
+ warnf(global,
+ "-v, --verbose overrides an earlier trace/verbose option");
+ global->tracetype = TRACE_PLAIN;
}
- if(global->tracetype && (global->tracetype != TRACE_PLAIN))
- warnf(global,
- "-v, --verbose overrides an earlier trace/verbose option");
- global->tracetype = TRACE_PLAIN;
}
else
/* verbose is disabled here */
global->tracetype = TRACE_NONE;
break;
- case 'V':
- if(toggle) { /* --no-version yields no output! */
+ case C_VERSION: /* --version */
+ if(toggle) /* --no-version yields no output! */
err = PARAM_VERSION_INFO_REQUESTED;
- break;
- }
break;
-
- case 'w':
+ case C_WRITE_OUT: /* --write-out */
/* get the output string */
if('@' == *nextarg) {
/* the data begins with a '@' letter, it means that a file name
@@ -2572,69 +2655,57 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
warnf(global, "Failed to read %s", fname);
}
else
- GetStr(&config->writeout, nextarg);
+ err = getstr(&config->writeout, nextarg, DENY_BLANK);
break;
- case 'x':
- switch(subletter) {
- case 'a': /* --preproxy */
- GetStr(&config->preproxy, nextarg);
- break;
- default:
- /* --proxy */
- GetStr(&config->proxy, nextarg);
- if(config->proxyver != CURLPROXY_HTTPS2)
- config->proxyver = CURLPROXY_HTTP;
- break;
- }
+ case C_PREPROXY: /* --preproxy */
+ err = getstr(&config->preproxy, nextarg, DENY_BLANK);
+ break;
+ case C_PROXY: /* --proxy */
+ /* --proxy */
+ err = getstr(&config->proxy, nextarg, ALLOW_BLANK);
+ if(config->proxyver != CURLPROXY_HTTPS2)
+ config->proxyver = CURLPROXY_HTTP;
break;
- case 'X':
+ case C_REQUEST: /* --request */
/* set custom request */
- GetStr(&config->customrequest, nextarg);
+ err = getstr(&config->customrequest, nextarg, DENY_BLANK);
break;
- case 'y':
+ case C_SPEED_TIME: /* --speed-time */
/* low speed time */
err = str2unum(&config->low_speed_time, nextarg);
- if(err)
- break;
- if(!config->low_speed_limit)
+ if(!err && !config->low_speed_limit)
config->low_speed_limit = 1;
break;
- case 'Y':
+ case C_SPEED_LIMIT: /* --speed-limit */
/* low speed limit */
err = str2unum(&config->low_speed_limit, nextarg);
- if(err)
- break;
- if(!config->low_speed_time)
+ if(!err && !config->low_speed_time)
config->low_speed_time = 30;
break;
- case 'Z':
- switch(subletter) {
- case '\0': /* --parallel */
- global->parallel = toggle;
- break;
- case 'b': { /* --parallel-max */
- long val;
- err = str2unum(&val, nextarg);
- if(err)
- break;
- if(val > MAX_PARALLEL)
- global->parallel_max = MAX_PARALLEL;
- else if(val < 1)
- global->parallel_max = PARALLEL_DEFAULT;
- else
- global->parallel_max = (unsigned short)val;
- break;
- }
- case 'c': /* --parallel-immediate */
- global->parallel_connect = toggle;
+ case C_PARALLEL: /* --parallel */
+ global->parallel = toggle;
+ break;
+ case C_PARALLEL_MAX: { /* --parallel-max */
+ long val;
+ err = str2unum(&val, nextarg);
+ if(err)
break;
- }
+ if(val > MAX_PARALLEL)
+ global->parallel_max = MAX_PARALLEL;
+ else if(val < 1)
+ global->parallel_max = PARALLEL_DEFAULT;
+ else
+ global->parallel_max = (unsigned short)val;
+ break;
+ }
+ case C_PARALLEL_IMMEDIATE: /* --parallel-immediate */
+ global->parallel_connect = toggle;
break;
- case 'z': /* time condition coming up */
+ case C_TIME_COND: /* --time-cond */
switch(*nextarg) {
case '+':
nextarg++;
- /* FALLTHROUGH */
+ FALLTHROUGH();
default:
/* If-Modified-Since: (section 14.28 in RFC2068) */
config->timecond = CURL_TIMECOND_IFMODSINCE;
@@ -2654,11 +2725,10 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
config->condtime = (curl_off_t)curl_getdate(nextarg, &now);
if(-1 == config->condtime) {
/* now let's see if it is a file name to get the time from instead! */
- curl_off_t filetime;
- rc = getfiletime(nextarg, global, &filetime);
+ rc = getfiletime(nextarg, global, &value);
if(!rc)
/* pull the time out from the file */
- config->condtime = filetime;
+ config->condtime = value;
else {
/* failed, remove time condition */
config->timecond = CURL_TIMECOND_NONE;
@@ -2673,7 +2743,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
err = PARAM_OPTION_UNKNOWN;
break;
}
- hit = -1;
+ a = NULL;
} while(!longopt && !singleopt && *++parse && !*usedarg && !err);
diff --git a/src/tool_getparam.h b/src/tool_getparam.h
index a8a9d4597..12a971d02 100644
--- a/src/tool_getparam.h
+++ b/src/tool_getparam.h
@@ -49,6 +49,7 @@ typedef enum {
PARAM_CONTDISP_RESUME_FROM, /* --continue-at and --remote-header-name */
PARAM_READ_ERROR,
PARAM_EXPAND_ERROR, /* --expand problem */
+ PARAM_BLANK_STRING,
PARAM_LAST
} ParameterError;
diff --git a/src/tool_getpass.c b/src/tool_getpass.c
index f5aa98c6a..8ccccdfb8 100644
--- a/src/tool_getpass.c
+++ b/src/tool_getpass.c
@@ -46,7 +46,7 @@
# include iodef
#endif
-#ifdef WIN32
+#ifdef _WIN32
# include <conio.h>
#endif
@@ -94,7 +94,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen)
#define DONE
#endif /* __VMS */
-#if defined(WIN32)
+#if defined(_WIN32)
char *getpass_r(const char *prompt, char *buffer, size_t buflen)
{
@@ -122,7 +122,7 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen)
return buffer; /* we always return success */
}
#define DONE
-#endif /* WIN32 */
+#endif /* _WIN32 */
#ifndef DONE /* not previously provided */
diff --git a/src/tool_help.c b/src/tool_help.c
index 8983a4ca0..04ac24537 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -73,8 +73,6 @@ static const struct category_descriptors categories[] = {
{NULL, NULL, CURLHELP_HIDDEN}
};
-extern const struct helptxt helptext[];
-
static void print_category(curlhelp_t category)
{
@@ -175,12 +173,30 @@ void tool_version_info(void)
printf("Release-Date: %s\n", LIBCURL_TIMESTAMP);
#endif
if(built_in_protos[0]) {
+ const char *insert = NULL;
+ /* we have ipfs and ipns support if libcurl has http support */
+ for(builtin = built_in_protos; *builtin; ++builtin) {
+ if(insert) {
+ /* update insertion so ipfs will be printed in alphabetical order */
+ if(strcmp(*builtin, "ipfs") < 0)
+ insert = *builtin;
+ else
+ break;
+ }
+ else if(!strcmp(*builtin, "http")) {
+ insert = *builtin;
+ }
+ }
printf("Protocols:");
for(builtin = built_in_protos; *builtin; ++builtin) {
/* Special case: do not list rtmp?* protocols.
They may only appear together with "rtmp" */
if(!curl_strnequal(*builtin, "rtmp", 4) || !builtin[0][4])
printf(" %s", *builtin);
+ if(insert && insert == *builtin) {
+ printf(" ipfs ipns");
+ insert = NULL;
+ }
}
puts(""); /* newline */
}
diff --git a/src/tool_helpers.c b/src/tool_helpers.c
index 854bf777a..67924a26e 100644
--- a/src/tool_helpers.c
+++ b/src/tool_helpers.c
@@ -78,6 +78,8 @@ const char *param2text(int res)
return "error encountered when reading a file";
case PARAM_EXPAND_ERROR:
return "variable expansion failure";
+ case PARAM_BLANK_STRING:
+ return "blank argument where content is expected";
default:
return "unknown error";
}
diff --git a/src/tool_ipfs.c b/src/tool_ipfs.c
new file mode 100644
index 000000000..f3a20aa94
--- /dev/null
+++ b/src/tool_ipfs.c
@@ -0,0 +1,293 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define ENABLE_CURLX_PRINTF
+/* use our own printf() functions */
+#include "curlx.h"
+#include "dynbuf.h"
+
+#include "tool_cfgable.h"
+#include "tool_msgs.h"
+#include "tool_ipfs.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+/* ensure input ends in slash */
+static CURLcode ensure_trailing_slash(char **input)
+{
+ if(*input && **input) {
+ size_t len = strlen(*input);
+ if(((*input)[len - 1] != '/')) {
+ struct curlx_dynbuf dyn;
+ curlx_dyn_init(&dyn, len + 2);
+
+ if(curlx_dyn_addn(&dyn, *input, len)) {
+ Curl_safefree(*input);
+ return CURLE_OUT_OF_MEMORY;
+ }
+
+ Curl_safefree(*input);
+
+ if(curlx_dyn_addn(&dyn, "/", 1))
+ return CURLE_OUT_OF_MEMORY;
+
+ *input = curlx_dyn_ptr(&dyn);
+ }
+ }
+
+ return CURLE_OK;
+}
+
+static char *ipfs_gateway(void)
+{
+ char *ipfs_path = NULL;
+ char *gateway_composed_file_path = NULL;
+ FILE *gateway_file = NULL;
+ char *gateway = curlx_getenv("IPFS_GATEWAY");
+
+ /* Gateway is found from environment variable. */
+ if(gateway) {
+ if(ensure_trailing_slash(&gateway))
+ goto fail;
+ return gateway;
+ }
+
+ /* Try to find the gateway in the IPFS data folder. */
+ ipfs_path = curlx_getenv("IPFS_PATH");
+
+ if(!ipfs_path) {
+ char *home = curlx_getenv("HOME");
+ if(home && *home)
+ ipfs_path = aprintf("%s/.ipfs/", home);
+ /* fallback to "~/.ipfs", as that's the default location. */
+
+ Curl_safefree(home);
+ }
+
+ if(!ipfs_path || ensure_trailing_slash(&ipfs_path))
+ goto fail;
+
+ gateway_composed_file_path = aprintf("%sgateway", ipfs_path);
+
+ if(!gateway_composed_file_path)
+ goto fail;
+
+ gateway_file = fopen(gateway_composed_file_path, FOPEN_READTEXT);
+ Curl_safefree(gateway_composed_file_path);
+
+ if(gateway_file) {
+ int c;
+ struct curlx_dynbuf dyn;
+ curlx_dyn_init(&dyn, MAX_GATEWAY_URL_LEN);
+
+ /* get the first line of the gateway file, ignore the rest */
+ while((c = getc(gateway_file)) != EOF && c != '\n' && c != '\r') {
+ char c_char = (char)c;
+ if(curlx_dyn_addn(&dyn, &c_char, 1))
+ goto fail;
+ }
+
+ fclose(gateway_file);
+ gateway_file = NULL;
+
+ if(curlx_dyn_len(&dyn))
+ gateway = curlx_dyn_ptr(&dyn);
+
+ if(gateway)
+ ensure_trailing_slash(&gateway);
+
+ if(!gateway)
+ goto fail;
+
+ Curl_safefree(ipfs_path);
+
+ return gateway;
+ }
+fail:
+ if(gateway_file)
+ fclose(gateway_file);
+ Curl_safefree(gateway);
+ Curl_safefree(ipfs_path);
+ return NULL;
+}
+
+/*
+ * Rewrite ipfs://<cid> and ipns://<cid> to a HTTP(S)
+ * URL that can be handled by an IPFS gateway.
+ */
+CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url,
+ struct OperationConfig *config)
+{
+ CURLcode result = CURLE_URL_MALFORMAT;
+ CURLUcode getResult;
+ char *gateway = NULL;
+ char *gwhost = NULL;
+ char *gwpath = NULL;
+ char *gwquery = NULL;
+ char *gwscheme = NULL;
+ char *gwport = NULL;
+ char *inputpath = NULL;
+ char *cid = NULL;
+ char *pathbuffer = NULL;
+ char *cloneurl;
+ CURLU *gatewayurl = curl_url();
+
+ if(!gatewayurl) {
+ result = CURLE_FAILED_INIT;
+ goto clean;
+ }
+
+ getResult = curl_url_get(uh, CURLUPART_HOST, &cid, CURLU_URLDECODE);
+ if(getResult || !cid)
+ goto clean;
+
+ /* We might have a --ipfs-gateway argument. Check it first and use it. Error
+ * if we do have something but if it's an invalid url.
+ */
+ if(config->ipfs_gateway) {
+ /* ensure the gateway ends in a trailing / */
+ if(ensure_trailing_slash(&config->ipfs_gateway) != CURLE_OK) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ if(!curl_url_set(gatewayurl, CURLUPART_URL, config->ipfs_gateway,
+ CURLU_GUESS_SCHEME)) {
+ gateway = strdup(config->ipfs_gateway);
+ if(!gateway) {
+ result = CURLE_URL_MALFORMAT;
+ goto clean;
+ }
+
+ }
+ else {
+ result = CURLE_BAD_FUNCTION_ARGUMENT;
+ goto clean;
+ }
+ }
+ else {
+ /* this is ensured to end in a trailing / within ipfs_gateway() */
+ gateway = ipfs_gateway();
+ if(!gateway) {
+ result = CURLE_FILE_COULDNT_READ_FILE;
+ goto clean;
+ }
+
+ if(curl_url_set(gatewayurl, CURLUPART_URL, gateway, 0)) {
+ result = CURLE_URL_MALFORMAT;
+ goto clean;
+ }
+ }
+
+ /* check for unsupported gateway parts */
+ if(curl_url_get(gatewayurl, CURLUPART_QUERY, &gwquery, 0)
+ != CURLUE_NO_QUERY) {
+ result = CURLE_URL_MALFORMAT;
+ goto clean;
+ }
+
+ /* get gateway parts */
+ if(curl_url_get(gatewayurl, CURLUPART_HOST,
+ &gwhost, CURLU_URLDECODE)) {
+ goto clean;
+ }
+
+ if(curl_url_get(gatewayurl, CURLUPART_SCHEME,
+ &gwscheme, CURLU_URLDECODE)) {
+ goto clean;
+ }
+
+ curl_url_get(gatewayurl, CURLUPART_PORT, &gwport, CURLU_URLDECODE);
+ curl_url_get(gatewayurl, CURLUPART_PATH, &gwpath, CURLU_URLDECODE);
+
+ /* get the path from user input */
+ curl_url_get(uh, CURLUPART_PATH, &inputpath, CURLU_URLDECODE);
+ /* inputpath might be NULL or a valid pointer now */
+
+ /* set gateway parts in input url */
+ if(curl_url_set(uh, CURLUPART_SCHEME, gwscheme, CURLU_URLENCODE) ||
+ curl_url_set(uh, CURLUPART_HOST, gwhost, CURLU_URLENCODE) ||
+ curl_url_set(uh, CURLUPART_PORT, gwport, CURLU_URLENCODE))
+ goto clean;
+
+ /* if the input path is just a slash, clear it */
+ if(inputpath && (inputpath[0] == '/') && !inputpath[1])
+ *inputpath = '\0';
+
+ /* ensure the gateway path ends with a trailing slash */
+ ensure_trailing_slash(&gwpath);
+
+ pathbuffer = aprintf("%s%s/%s%s", gwpath, protocol, cid,
+ inputpath ? inputpath : "");
+ if(!pathbuffer) {
+ goto clean;
+ }
+
+ if(curl_url_set(uh, CURLUPART_PATH, pathbuffer, CURLU_URLENCODE)) {
+ goto clean;
+ }
+
+ /* Free whatever it has now, rewriting is next */
+ Curl_safefree(*url);
+
+ if(curl_url_get(uh, CURLUPART_URL, &cloneurl, CURLU_URLENCODE)) {
+ goto clean;
+ }
+ /* we need to strdup the URL so that we can call free() on it later */
+ *url = strdup(cloneurl);
+ curl_free(cloneurl);
+ if(!*url)
+ goto clean;
+
+ result = CURLE_OK;
+
+clean:
+ free(gateway);
+ curl_free(gwhost);
+ curl_free(gwpath);
+ curl_free(gwquery);
+ curl_free(inputpath);
+ curl_free(gwscheme);
+ curl_free(gwport);
+ curl_free(cid);
+ curl_free(pathbuffer);
+ curl_url_cleanup(gatewayurl);
+ {
+ switch(result) {
+ case CURLE_URL_MALFORMAT:
+ helpf(tool_stderr, "malformed target URL");
+ break;
+ case CURLE_FILE_COULDNT_READ_FILE:
+ helpf(tool_stderr, "IPFS automatic gateway detection failed");
+ break;
+ case CURLE_BAD_FUNCTION_ARGUMENT:
+ helpf(tool_stderr, "--ipfs-gateway was given a malformed URL");
+ break;
+ default:
+ break;
+ }
+ }
+ return result;
+}
diff --git a/src/tool_ipfs.h b/src/tool_ipfs.h
new file mode 100644
index 000000000..9c8a83e3b
--- /dev/null
+++ b/src/tool_ipfs.h
@@ -0,0 +1,33 @@
+#ifndef HEADER_CURL_TOOL_IPFS_H
+#define HEADER_CURL_TOOL_IPFS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#define MAX_GATEWAY_URL_LEN 10000
+
+CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url,
+ struct OperationConfig *config);
+
+#endif /* HEADER_CURL_TOOL_IPFS_H */
diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c
index 4e7a6dd63..32ed2533e 100644
--- a/src/tool_listhelp.c
+++ b/src/tool_listhelp.c
@@ -26,10 +26,10 @@
/*
* DO NOT edit tool_listhelp.c manually.
- * This source file is generated with the following command:
-
- cd $srcroot/docs/cmdline-opts
- ./gen.pl listhelp *.d > $srcroot/src/tool_listhelp.c
+ * This source file is generated with the following command in an autotools
+ * build:
+ *
+ * "make listhelp"
*/
const struct helptxt helptext[] = {
@@ -143,7 +143,7 @@ const struct helptxt helptext[] = {
CURLHELP_FTP},
{" --disallow-username-in-url",
"Disallow username in URL",
- CURLHELP_CURL | CURLHELP_HTTP},
+ CURLHELP_CURL},
{" --dns-interface <interface>",
"Interface to use for DNS requests",
CURLHELP_DNS},
@@ -246,7 +246,7 @@ const struct helptxt helptext[] = {
{" --happy-eyeballs-timeout-ms <milliseconds>",
"Time for IPv6 before trying IPv4",
CURLHELP_CONNECTION},
- {" --haproxy-clientip",
+ {" --haproxy-clientip <IP address>",
"Sets client IP in HAProxy PROXY protocol v1 header",
CURLHELP_HTTP | CURLHELP_PROXY},
{" --haproxy-protocol",
diff --git a/src/tool_main.c b/src/tool_main.c
index 2f132e2d2..446806ecb 100644
--- a/src/tool_main.c
+++ b/src/tool_main.c
@@ -25,7 +25,7 @@
#include <sys/stat.h>
-#ifdef WIN32
+#ifdef _WIN32
#include <tchar.h>
#endif
@@ -220,6 +220,7 @@ static void main_free(struct GlobalConfig *config)
#ifdef _UNICODE
#if defined(__GNUC__)
/* GCC doesn't know about wmain() */
+#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
#pragma GCC diagnostic ignored "-Wmissing-declarations"
#endif
@@ -234,7 +235,7 @@ int main(int argc, char *argv[])
tool_init_stderr();
-#ifdef WIN32
+#ifdef _WIN32
/* Undocumented diagnostic option to list the full paths of all loaded
modules. This is purposely pre-init. */
if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) {
@@ -275,7 +276,7 @@ int main(int argc, char *argv[])
main_free(&global);
}
-#ifdef WIN32
+#ifdef _WIN32
/* Flush buffers of all streams opened in write or update mode */
fflush(NULL);
#endif
@@ -287,4 +288,10 @@ int main(int argc, char *argv[])
#endif
}
+#ifdef _UNICODE
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+#endif
+
#endif /* ndef UNITTESTS */
diff --git a/src/tool_msgs.c b/src/tool_msgs.c
index c914836db..09c9310a5 100644
--- a/src/tool_msgs.c
+++ b/src/tool_msgs.c
@@ -39,6 +39,11 @@
static void voutf(struct GlobalConfig *config,
const char *prefix,
const char *fmt,
+ va_list ap) CURL_PRINTF(3, 0);
+
+static void voutf(struct GlobalConfig *config,
+ const char *prefix,
+ const char *fmt,
va_list ap)
{
size_t width = (79 - strlen(prefix));
@@ -100,7 +105,6 @@ void notef(struct GlobalConfig *config, const char *fmt, ...)
* Emit warning formatted message on configured 'errors' stream unless
* mute (--silent) was selected.
*/
-
void warnf(struct GlobalConfig *config, const char *fmt, ...)
{
va_list ap;
@@ -108,6 +112,7 @@ void warnf(struct GlobalConfig *config, const char *fmt, ...)
voutf(config, WARN_PREFIX, fmt, ap);
va_end(ap);
}
+
/*
* Emit help formatted message on given stream. This is for errors with or
* related to command line arguments.
diff --git a/src/tool_msgs.h b/src/tool_msgs.h
index 9458991c0..e963efaa0 100644
--- a/src/tool_msgs.h
+++ b/src/tool_msgs.h
@@ -26,9 +26,13 @@
#include "tool_setup.h"
#include "tool_cfgable.h"
-void warnf(struct GlobalConfig *config, const char *fmt, ...);
-void notef(struct GlobalConfig *config, const char *fmt, ...);
-void helpf(FILE *errors, const char *fmt, ...);
-void errorf(struct GlobalConfig *config, const char *fmt, ...);
+void warnf(struct GlobalConfig *config, const char *fmt, ...)
+ CURL_PRINTF(2, 3);
+void notef(struct GlobalConfig *config, const char *fmt, ...)
+ CURL_PRINTF(2, 3);
+void helpf(FILE *errors, const char *fmt, ...)
+ CURL_PRINTF(2, 3);
+void errorf(struct GlobalConfig *config, const char *fmt, ...)
+ CURL_PRINTF(2, 3);
#endif /* HEADER_CURL_TOOL_MSGS_H */
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 4991186eb..ba811d773 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -81,6 +81,7 @@
#include "tool_help.h"
#include "tool_hugehelp.h"
#include "tool_progress.h"
+#include "tool_ipfs.h"
#include "dynbuf.h"
#include "memdebug.h" /* keep this as LAST include */
@@ -210,7 +211,7 @@ static curl_off_t all_pers;
static CURLcode add_per_transfer(struct per_transfer **per)
{
struct per_transfer *p;
- p = calloc(sizeof(struct per_transfer), 1);
+ p = calloc(1, sizeof(struct per_transfer));
if(!p)
return CURLE_OUT_OF_MEMORY;
if(!transfers)
@@ -342,22 +343,6 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
return result;
}
-#ifdef __AMIGA__
-static void AmigaSetComment(struct per_transfer *per,
- CURLcode result)
-{
- struct OutStruct *outs = &per->outs;
- if(!result && outs->s_isreg && outs->filename) {
- /* Set the url (up to 80 chars) as comment for the file */
- if(strlen(per->this_url) > 78)
- per->this_url[79] = '\0';
- SetComment(outs->filename, per->this_url);
- }
-}
-#else
-#define AmigaSetComment(x,y) Curl_nop_stmt
-#endif
-
/* When doing serial transfers, we use a single fixed error area */
static char global_errorbuffer[CURL_ERROR_SIZE];
@@ -371,7 +356,6 @@ void single_transfer_cleanup(struct OperationConfig *config)
state->urls = NULL;
}
Curl_safefree(state->outfiles);
- Curl_safefree(state->httpgetfields);
Curl_safefree(state->uploadfile);
if(state->inglob) {
/* Free list of globbed upload files */
@@ -462,7 +446,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
}
}
-#ifdef WIN32
+#ifdef _WIN32
/* Discard incomplete UTF-8 sequence buffered from body */
if(outs->utf8seq[0])
memset(outs->utf8seq, 0, sizeof(outs->utf8seq));
@@ -653,13 +637,20 @@ noretry:
errorf(config->global, "curl: (%d) Failed writing body", result);
}
if(result && config->rm_partial) {
- notef(global, "Removing output file: %s", outs->filename);
- unlink(outs->filename);
+ struct_stat st;
+ if(!stat(outs->filename, &st) &&
+ S_ISREG(st.st_mode)) {
+ if(!unlink(outs->filename))
+ notef(global, "Removed output file: %s", outs->filename);
+ else
+ warnf(global, "Failed removing: %s", outs->filename);
+ }
+ else
+ warnf(global, "Skipping removal; not a regular file: %s",
+ outs->filename);
}
}
- AmigaSetComment(per, result);
-
/* File time can only be set _after_ the file has been closed */
if(!result && config->remote_time && outs->s_isreg && outs->filename) {
/* Ask libcurl if we got a remote file time */
@@ -697,197 +688,6 @@ noretry:
return result;
}
-static char *ipfs_gateway(void)
-{
- char *gateway = NULL;
- char *ipfs_path = NULL;
- char *gateway_composed_file_path = NULL;
- FILE *gateway_file = NULL;
-
- gateway = getenv("IPFS_GATEWAY");
-
- /* Gateway is found from environment variable. */
- if(gateway && *gateway) {
- char *composed_gateway = NULL;
- bool add_slash = (gateway[strlen(gateway) - 1] != '/');
- composed_gateway = aprintf("%s%s", gateway, (add_slash) ? "/" : "");
- if(composed_gateway) {
- gateway = aprintf("%s", composed_gateway);
- Curl_safefree(composed_gateway);
- }
- return gateway;
- }
- else
- /* a blank string does not count */
- gateway = NULL;
-
- /* Try to find the gateway in the IPFS data folder. */
- ipfs_path = getenv("IPFS_PATH");
-
- if(!ipfs_path) {
- char *home = getenv("HOME");
- if(home && *home)
- ipfs_path = aprintf("%s/.ipfs/", home);
- /* fallback to "~/.ipfs", as that's the default location. */
- }
-
- if(!ipfs_path) {
- Curl_safefree(gateway);
- Curl_safefree(ipfs_path);
- return NULL;
- }
-
- gateway_composed_file_path = aprintf("%sgateway", ipfs_path);
-
- if(!gateway_composed_file_path) {
- Curl_safefree(gateway);
- Curl_safefree(ipfs_path);
- return NULL;
- }
-
- gateway_file = fopen(gateway_composed_file_path, FOPEN_READTEXT);
- Curl_safefree(gateway_composed_file_path);
-
- if(gateway_file) {
- char *buf = NULL;
-
- if((PARAM_OK == file2string(&buf, gateway_file)) && buf && *buf) {
- bool add_slash = (buf[strlen(buf) - 1] != '/');
- gateway = aprintf("%s%s", buf, (add_slash) ? "/" : "");
- }
- Curl_safefree(buf);
-
- if(gateway_file)
- fclose(gateway_file);
-
- if(!gateway) {
- Curl_safefree(gateway);
- Curl_safefree(ipfs_path);
- return NULL;
- }
-
- Curl_safefree(ipfs_path);
- return gateway;
- }
-
- Curl_safefree(gateway);
- Curl_safefree(ipfs_path);
- return NULL;
-}
-
-/*
- * Rewrite ipfs://<cid> and ipns://<cid> to a HTTP(S)
- * URL that can be handled by an IPFS gateway.
- */
-static CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url,
- struct OperationConfig *config)
-{
- CURLcode result = CURLE_URL_MALFORMAT;
- CURLUcode urlGetResult;
- char *gateway = NULL;
- char *cid = NULL;
- char *pathbuffer = NULL;
- CURLU *ipfsurl = curl_url();
-
- if(!ipfsurl) {
- result = CURLE_FAILED_INIT;
- goto clean;
- }
-
- urlGetResult = curl_url_get(uh, CURLUPART_HOST, &cid, CURLU_URLDECODE);
-
- if(urlGetResult) {
- goto clean;
- }
-
- if(!cid) {
- goto clean;
- }
-
- /* We might have a --ipfs-gateway argument. Check it first and use it. Error
- * if we do have something but if it's an invalid url.
- */
- if(config->ipfs_gateway) {
- if(curl_url_set(ipfsurl, CURLUPART_URL, config->ipfs_gateway,
- CURLU_GUESS_SCHEME)
- == CURLUE_OK) {
- gateway = strdup(config->ipfs_gateway);
- if(!gateway) {
- result = CURLE_URL_MALFORMAT;
- goto clean;
- }
-
- }
- else {
- result = CURLE_BAD_FUNCTION_ARGUMENT;
- goto clean;
- }
- }
- else {
- gateway = ipfs_gateway();
- if(!gateway) {
- result = CURLE_FILE_COULDNT_READ_FILE;
- goto clean;
- }
-
- if(curl_url_set(ipfsurl, CURLUPART_URL, gateway, CURLU_GUESS_SCHEME
- | CURLU_NON_SUPPORT_SCHEME) != CURLUE_OK) {
- goto clean;
- }
- }
-
- pathbuffer = aprintf("%s/%s", protocol, cid);
- if(!pathbuffer) {
- goto clean;
- }
-
- if(curl_url_set(ipfsurl, CURLUPART_PATH, pathbuffer, CURLU_URLENCODE)
- != CURLUE_OK) {
- goto clean;
- }
-
- /* Free whatever it has now, rewriting is next */
- Curl_safefree(*url);
-
- if(curl_url_get(ipfsurl, CURLUPART_URL, url, CURLU_URLENCODE)
- != CURLUE_OK) {
- goto clean;
- }
-
- result = CURLE_OK;
-
-clean:
- free(gateway);
- curl_free(cid);
- curl_free(pathbuffer);
- curl_url_cleanup(ipfsurl);
-
- switch(result) {
- case CURLE_URL_MALFORMAT:
- helpf(tool_stderr, "malformed URL. Visit https://curl.se/"
- "docs/ipfs.html#Gateway-file-and-"
- "environment-variable for more "
- "information");
- break;
- case CURLE_FILE_COULDNT_READ_FILE:
- helpf(tool_stderr, "IPFS automatic gateway detection "
- "failure. Visit https://curl.se/docs/"
- "ipfs.html#Malformed-gateway-URL for "
- "more information");
- break;
- case CURLE_BAD_FUNCTION_ARGUMENT:
- helpf(tool_stderr, "--ipfs-gateway argument results in "
- "malformed URL. Visit https://curl.se/"
- "docs/ipfs.html#Malformed-gateway-URL "
- "for more information");
- break;
- default:
- break;
- }
-
- return result;
-}
-
/*
* Return the protocol token for the scheme used in the given URL
*/
@@ -911,13 +711,13 @@ static CURLcode url_proto(char **url,
if(curl_strequal(schemep, proto_ipfs) ||
curl_strequal(schemep, proto_ipns)) {
result = ipfs_url_rewrite(uh, schemep, url, config);
-
/* short-circuit proto_token, we know it's ipfs or ipns */
if(curl_strequal(schemep, proto_ipfs))
proto = proto_ipfs;
else if(curl_strequal(schemep, proto_ipns))
proto = proto_ipns;
-
+ if(result)
+ config->synthetic_error = TRUE;
}
else
proto = proto_token(schemep);
@@ -952,15 +752,11 @@ static CURLcode single_transfer(struct GlobalConfig *global,
if(config->use_httpget) {
if(!httpgetfields) {
/* Use the postfields data for an HTTP get */
- httpgetfields = state->httpgetfields = strdup(config->postfields);
- Curl_safefree(config->postfields);
- if(!httpgetfields) {
- errorf(global, "out of memory");
- result = CURLE_OUT_OF_MEMORY;
- }
- else if(SetHTTPrequest(config,
- (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
- &config->httpreq)) {
+ httpgetfields = state->httpgetfields = config->postfields;
+ config->postfields = NULL;
+ if(SetHTTPrequest(config,
+ (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
+ &config->httpreq)) {
result = CURLE_FAILED_INIT;
}
}
@@ -1623,9 +1419,9 @@ static CURLcode single_transfer(struct GlobalConfig *global,
}
else {
my_setopt_str(curl, CURLOPT_POSTFIELDS,
- config->postfields);
+ curlx_dyn_ptr(&config->postdata));
my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
- config->postfieldsize);
+ (curl_off_t)curlx_dyn_len(&config->postdata));
}
break;
case HTTPREQ_MIMEPOST:
@@ -1776,7 +1572,8 @@ static CURLcode single_transfer(struct GlobalConfig *global,
(config->proxy_capath ?
config->proxy_capath :
config->capath));
- if(result == CURLE_NOT_BUILT_IN) {
+ if((result == CURLE_NOT_BUILT_IN) ||
+ (result == CURLE_UNKNOWN_OPTION)) {
if(config->proxy_capath) {
warnf(global,
"ignoring --proxy-capath, not supported by libcurl");
@@ -2825,7 +2622,7 @@ static CURLcode transfer_per_config(struct GlobalConfig *global,
if(env)
curl_free(env);
-#ifdef WIN32
+#ifdef _WIN32
else {
result = FindWin32CACert(config, tls_backend_info->backend,
TEXT("curl-ca-bundle.crt"));
diff --git a/src/tool_operate.h b/src/tool_operate.h
index 21a7f929d..4993b1c96 100644
--- a/src/tool_operate.h
+++ b/src/tool_operate.h
@@ -74,7 +74,7 @@ struct per_transfer {
/* NULL or malloced */
char *uploadfile;
- char *errorbuffer; /* alloced and assigned while this is used for a
+ char *errorbuffer; /* allocated and assigned while this is used for a
transfer */
};
diff --git a/src/tool_operhlp.c b/src/tool_operhlp.c
index a964d796d..d1e8352d8 100644
--- a/src/tool_operhlp.c
+++ b/src/tool_operhlp.c
@@ -215,7 +215,7 @@ CURLcode get_url_file_name(char **filename, const char *url)
if(!*filename)
return CURLE_OUT_OF_MEMORY;
-#if defined(MSDOS) || defined(WIN32)
+#if defined(_WIN32) || defined(MSDOS)
{
char *sanitized;
SANITIZEcode sc = sanitize_file_name(&sanitized, *filename, 0);
@@ -227,7 +227,7 @@ CURLcode get_url_file_name(char **filename, const char *url)
}
*filename = sanitized;
}
-#endif /* MSDOS || WIN32 */
+#endif /* _WIN32 || MSDOS */
/* in case we built debug enabled, we allow an environment variable
* named CURL_TESTDIR to prefix the given file name to put it into a
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
index d70e80db4..272581500 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -88,8 +88,6 @@ ParameterError file2string(char **bufp, FILE *file)
return PARAM_OK;
}
-#define MAX_FILE2MEMORY (1024*1024*1024) /* big enough ? */
-
ParameterError file2memory(char **bufp, size_t *size, FILE *file)
{
if(file) {
@@ -134,6 +132,8 @@ static ParameterError getnum(long *val, const char *str, int base)
if(str) {
char *endptr = NULL;
long num;
+ if(!str[0])
+ return PARAM_BLANK_STRING;
errno = 0;
num = strtol(str, &endptr, base);
if(errno == ERANGE)
@@ -408,7 +408,7 @@ ParameterError proto2num(struct OperationConfig *config,
break;
case set:
protoset[0] = NULL;
- /* FALLTHROUGH */
+ FALLTHROUGH();
case allow:
protoset_set(protoset, p);
break;
diff --git a/src/tool_paramhlp.h b/src/tool_paramhlp.h
index edb878195..96c49ac59 100644
--- a/src/tool_paramhlp.h
+++ b/src/tool_paramhlp.h
@@ -30,6 +30,8 @@ struct getout *new_getout(struct OperationConfig *config);
ParameterError file2string(char **bufp, FILE *file);
+#define MAX_FILE2MEMORY (1024*1024*1024) /* big enough ? */
+
ParameterError file2memory(char **bufp, size_t *size, FILE *file);
ParameterError str2num(long *val, const char *str);
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c
index c15f21043..da4870066 100644
--- a/src/tool_parsecfg.c
+++ b/src/tool_parsecfg.c
@@ -46,7 +46,7 @@ static const char *unslashquote(const char *line, char *param);
#define MAX_CONFIG_LINE_LENGTH (10*1024*1024)
static bool my_get_line(FILE *fp, struct curlx_dynbuf *, bool *error);
-#ifdef WIN32
+#ifdef _WIN32
static FILE *execpath(const char *filename, char **pathp)
{
static char filebuffer[512];
@@ -98,7 +98,7 @@ int parseconfig(const char *filename, struct GlobalConfig *global)
}
filename = pathalloc = curlrc;
}
-#ifdef WIN32 /* Windows */
+#ifdef _WIN32 /* Windows */
else {
char *fullp;
/* check for .curlrc then _curlrc in the dir of the executable */
@@ -210,8 +210,9 @@ int parseconfig(const char *filename, struct GlobalConfig *global)
break;
default:
warnf(operation->global, "%s:%d: warning: '%s' uses unquoted "
- "whitespace in the line that may cause side-effects",
- filename, lineno, option);
+ "whitespace", filename, lineno, option);
+ warnf(operation->global, "This may cause side-effects. "
+ "Consider using double quotes?");
}
}
if(!*param)
diff --git a/src/tool_sdecls.h b/src/tool_sdecls.h
index 7b2eb2338..b93c32462 100644
--- a/src/tool_sdecls.h
+++ b/src/tool_sdecls.h
@@ -71,7 +71,7 @@ struct OutStruct {
FILE *stream;
curl_off_t bytes;
curl_off_t init;
-#ifdef WIN32
+#ifdef _WIN32
unsigned char utf8seq[5];
#endif
};
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index de3b78fab..b41b6d1d2 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -240,14 +240,10 @@ static char *c_escape(const char *str, curl_off_t len)
if(p && *p)
result = curlx_dyn_addn(&escaped, to + 2 * (p - from), 2);
else {
- const char *format = "\\x%02x";
-
- if(len > 1 && ISXDIGIT(s[1])) {
- /* Octal escape to avoid >2 digit hex. */
- format = "\\%03o";
- }
-
- result = curlx_dyn_addf(&escaped, format,
+ result = curlx_dyn_addf(&escaped,
+ /* Octal escape to avoid >2 digit hex. */
+ (len > 1 && ISXDIGIT(s[1])) ?
+ "\\%03o" : "\\x%02x",
(unsigned int) *(unsigned char *) s);
}
}
@@ -431,7 +427,7 @@ static CURLcode libcurl_generate_mime_part(CURL *curl,
case TOOLMIME_STDIN:
if(!filename)
filename = "-";
- /* FALLTHROUGH */
+ FALLTHROUGH();
case TOOLMIME_STDINDATA:
/* Can only be reading stdin in the current context. */
CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
@@ -653,7 +649,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *global,
if(escape) {
curl_off_t len = ZERO_TERMINATED;
if(tag == CURLOPT_POSTFIELDS)
- len = config->postfieldsize;
+ len = curlx_dyn_len(&config->postdata);
escaped = c_escape(value, len);
NULL_CHECK(escaped);
CODE2("curl_easy_setopt(hnd, %s, \"%s\");", name, escaped);
diff --git a/src/tool_setup.h b/src/tool_setup.h
index 48b355640..c69859ea6 100644
--- a/src/tool_setup.h
+++ b/src/tool_setup.h
@@ -66,10 +66,12 @@ extern FILE *tool_stderr;
# include "tool_strdup.h"
#endif
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32)
/* set in win32_init() */
extern LARGE_INTEGER tool_freq;
extern bool tool_isVistaOrGreater;
+/* set in init_terminal() */
+extern bool tool_term_has_bold;
#endif
#endif /* HEADER_CURL_TOOL_SETUP_H */
diff --git a/src/tool_sleep.c b/src/tool_sleep.c
index 08d6f9028..c24f73729 100644
--- a/src/tool_sleep.c
+++ b/src/tool_sleep.c
@@ -47,7 +47,7 @@ void tool_go_sleep(long ms)
{
#if defined(MSDOS)
delay(ms);
-#elif defined(WIN32)
+#elif defined(_WIN32)
Sleep(ms);
#elif defined(HAVE_POLL_FINE)
(void)poll((void *)0, 0, (int)ms);
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 69016179d..8ae28a3a6 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -66,13 +66,23 @@ static CURLcode glob_fixed(struct URLGlob *glob, char *fixed, size_t len)
*/
static int multiply(curl_off_t *amount, curl_off_t with)
{
- curl_off_t sum = *amount * with;
- if(!with) {
- *amount = 0;
- return 0;
+ curl_off_t sum;
+ DEBUGASSERT(*amount >= 0);
+ DEBUGASSERT(with >= 0);
+ if((with <= 0) || (*amount <= 0)) {
+ sum = 0;
+ }
+ else {
+#if defined(__GNUC__) && \
+ ((__GNUC__ > 5) || ((__GNUC__ == 5) && (__GNUC_MINOR__ >= 1)))
+ if(__builtin_mul_overflow(*amount, with, &sum))
+ return 1;
+#else
+ sum = *amount * with;
+ if(sum/with != *amount)
+ return 1; /* didn't fit, bail out */
+#endif
}
- if(sum/with != *amount)
- return 1; /* didn't fit, bail out */
*amount = sum;
return 0;
}
@@ -117,7 +127,7 @@ static CURLcode glob_set(struct URLGlob *glob, char **patternp,
if(multiply(amount, pat->content.Set.size + 1))
return GLOBERROR("range overflow", 0, CURLE_URL_MALFORMAT);
- /* FALLTHROUGH */
+ FALLTHROUGH();
case ',':
*buf = '\0';
@@ -161,7 +171,7 @@ static CURLcode glob_set(struct URLGlob *glob, char **patternp,
++pattern;
++(*posp);
}
- /* FALLTHROUGH */
+ FALLTHROUGH();
default:
*buf++ = *pattern++; /* copy character to set element */
++(*posp);
@@ -692,7 +702,7 @@ CURLcode glob_match_url(char **result, char *filename, struct URLGlob *glob)
if(curlx_dyn_addn(&dyn, "", 0))
return CURLE_OUT_OF_MEMORY;
-#if defined(MSDOS) || defined(WIN32)
+#if defined(_WIN32) || defined(MSDOS)
{
char *sanitized;
SANITIZEcode sc = sanitize_file_name(&sanitized, curlx_dyn_ptr(&dyn),
@@ -707,5 +717,5 @@ CURLcode glob_match_url(char **result, char *filename, struct URLGlob *glob)
#else
*result = curlx_dyn_ptr(&dyn);
return CURLE_OK;
-#endif /* MSDOS || WIN32 */
+#endif /* _WIN32 || MSDOS */
}
diff --git a/src/tool_util.c b/src/tool_util.c
index 7a1c03b20..812a689d0 100644
--- a/src/tool_util.c
+++ b/src/tool_util.c
@@ -31,7 +31,7 @@
#include "memdebug.h" /* keep this as LAST include */
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32)
/* In case of bug fix this function has a counterpart in timeval.c */
struct timeval tvnow(void)
diff --git a/src/tool_writeout_json.c b/src/tool_writeout_json.c
index 7bc74a269..4ed6b93fb 100644
--- a/src/tool_writeout_json.c
+++ b/src/tool_writeout_json.c
@@ -41,8 +41,8 @@
int jsonquoted(const char *in, size_t len,
struct curlx_dynbuf *out, bool lowercase)
{
- const char *i = in;
- const char *in_end = &in[len];
+ const unsigned char *i = (unsigned char *)in;
+ const unsigned char *in_end = &i[len];
CURLcode result = CURLE_OK;
for(; (i < in_end) && !result; i++) {
diff --git a/src/tool_xattr.c b/src/tool_xattr.c
index 968cf2f72..9472194fa 100644
--- a/src/tool_xattr.c
+++ b/src/tool_xattr.c
@@ -87,11 +87,12 @@ static int xattr(int fd,
int err = 0;
if(value) {
#ifdef DEBUGBUILD
+ (void)fd;
if(getenv("CURL_FAKE_XATTR")) {
printf("%s => %s\n", attr, value);
}
return 0;
-#endif
+#else
#ifdef HAVE_FSETXATTR_6
err = fsetxattr(fd, attr, value, strlen(value), 0, 0);
#elif defined(HAVE_FSETXATTR_5)
@@ -105,6 +106,7 @@ static int xattr(int fd,
err = (rc < 0 ? -1 : 0);
}
#endif
+#endif
}
return err;
}
diff --git a/src/var.c b/src/var.c
index f8f42f666..388d45592 100644
--- a/src/var.c
+++ b/src/var.c
@@ -358,7 +358,7 @@ static ParameterError addvariable(struct GlobalConfig *global,
if(check)
notef(global, "Overwriting variable '%s'", check->name);
- p = calloc(sizeof(struct var), 1);
+ p = calloc(1, sizeof(struct var));
if(!p)
return PARAM_NO_MEM;
diff --git a/tests/.gitignore b/tests/.gitignore
index eae0490de..f08407f52 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -26,3 +26,4 @@ testcurl.html
testcurl.pdf
*.port
config
+second-hsts.txt
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
index 665d93eb8..5a8e78323 100644
--- a/tests/FILEFORMAT.md
+++ b/tests/FILEFORMAT.md
@@ -74,6 +74,17 @@ For example, to insert the word hello 100 times:
%repeat[100 x hello]%
+## Include file
+
+This instruction allows a test case to include another file. It is helpful to
+remember that the ordinary variables are expanded before the include happens
+so `%LOGDIR` and the others can be used in the include line.
+
+The file name cannot contain `%` as that letter is used to end the name for
+the include instruction:
+
+ %include filename%
+
## Conditional lines
Lines in the test file can be made to appear conditionally on a specific
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 17e9ad049..a6d0708f7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -22,19 +22,35 @@
#
###########################################################################
-HTMLPAGES = testcurl.html runtests.html
-PDFPAGES = testcurl.pdf runtests.pdf
MANDISTPAGES = runtests.1.dist testcurl.1.dist
-EXTRA_DIST = appveyor.pm azure.pm badsymbols.pl check-deprecated.pl CMakeLists.txt \
- devtest.pl dictserver.py directories.pm disable-scan.pl error-codes.pl extern-scan.pl FILEFORMAT.md \
- processhelp.pm ftpserver.pl getpart.pm globalconfig.pm http-server.pl http2-server.pl \
- http3-server.pl manpage-scan.pl manpage-syntax.pl markdown-uppercase.pl mem-include-scan.pl \
- memanalyze.pl negtelnetserver.py nroff-scan.pl option-check.pl options-scan.pl \
- pathhelp.pm README.md rtspserver.pl runner.pm runtests.1 runtests.pl secureserver.pl \
- serverhelp.pm servers.pm smbserver.py sshhelp.pm sshserver.pl stunnel.pem symbol-scan.pl \
- testcurl.1 testcurl.pl testutil.pm tftpserver.pl util.py valgrind.pm \
- valgrind.supp version-scan.pl check-translatable-options.pl
+# scripts used in test cases
+TESTSCRIPTS = \
+ test1119.pl \
+ test1132.pl \
+ test1135.pl \
+ test1139.pl \
+ test1140.pl \
+ test1165.pl \
+ test1167.pl \
+ test1173.pl \
+ test1175.pl \
+ test1177.pl \
+ test1222.pl \
+ test1275.pl \
+ test1276.pl \
+ test1477.pl \
+ test1544.pl \
+ test971.pl
+
+EXTRA_DIST = appveyor.pm azure.pm CMakeLists.txt devtest.pl \
+ dictserver.py directories.pm FILEFORMAT.md processhelp.pm ftpserver.pl \
+ getpart.pm globalconfig.pm http-server.pl http2-server.pl \
+ http3-server.pl memanalyze.pl negtelnetserver.py pathhelp.pm README.md \
+ rtspserver.pl runner.pm runtests.1 runtests.pl secureserver.pl \
+ serverhelp.pm servers.pm smbserver.py sshhelp.pm sshserver.pl \
+ stunnel.pem testcurl.1 testcurl.pl testutil.pm tftpserver.pl util.py \
+ valgrind.pm valgrind.supp $(TESTSCRIPTS)
DISTCLEANFILES = configurehelp.pm
@@ -56,8 +72,6 @@ PERLFLAGS = -I$(srcdir)
CLEANFILES = .http.pid .https.pid .ftp.pid .ftps.pid $(MANDISTPAGES)
-MAN2HTML= roffit $< >$@
-
curl:
@cd $(top_builddir) && $(MAKE)
@@ -107,16 +121,6 @@ torture-test: perlcheck all
event-test: perlcheck all
$(TEST) $(TEST_E) $(TFLAGS)
-.1.html:
- $(MAN2HTML)
-
-.1.pdf:
- @(foo=`echo $@ | sed -e 's/\.[0-9]$$//g'`; \
- groff -Tps -man $< >$$foo.ps; \
- ps2pdf $$foo.ps $@; \
- rm $$foo.ps; \
- echo "converted $< to $@")
-
checksrc:
(cd libtest && $(MAKE) checksrc)
(cd unit && $(MAKE) checksrc)
diff --git a/tests/README.md b/tests/README.md
index 65af2a0bd..1464eacdc 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -8,6 +8,41 @@ SPDX-License-Identifier: curl
# Running
+ See the "Requires to run" section for prerequisites.
+
+ In the root of the curl repository:
+
+ ./configure && make && make test
+
+ To run a specific set of tests (e.g. 303 and 410):
+
+ make test TFLAGS="303 410"
+
+ To run the tests faster, pass the -j (parallelism) flag:
+
+ make test TFLAGS="-j10"
+
+ "make test" builds the test suite support code and invokes the 'runtests.pl'
+ perl script to run all the tests. The value of `TFLAGS` is passed
+ directly to 'runtests.pl'.
+
+ When you run tests via make, the flags `-a` and `-s` are passed, meaning
+ to continue running tests even after one fails, and to emit short output.
+
+ If you'd like to not use those flags, you can run 'runtests.pl' directly.
+ You must `chdir` into the tests directory, then you can run it like so:
+
+ ./runtests.pl 303 410
+
+ You must have run `make test` at least once first to build the support code.
+
+ To see what flags are available for runtests.pl, and what output it emits, run:
+
+ man ./tests/runtests.1
+
+ After a test fails, examine the tests/log directory for stdout, stderr, and
+ output from the servers used in the test.
+
## Requires to run
- perl (and a unix-style shell)
@@ -15,7 +50,7 @@ SPDX-License-Identifier: curl
- python-impacket (for SMB tests)
- diff (when a test fails, a diff is shown)
- stunnel (for HTTPS and FTPS tests)
- - OpenSSH or SunSSH (for SCP, SFTP and SOCKS4/5 tests)
+ - OpenSSH or SunSSH (for SCP and SFTP tests)
- nghttpx (for HTTP/2 and HTTP/3 tests)
- nroff (for --manual tests)
- An available `en_US.UTF-8` locale
@@ -59,9 +94,7 @@ SPDX-License-Identifier: curl
The test suite runs stand-alone servers on random ports to which it makes
requests. For SSL tests, it runs stunnel to handle encryption to the regular
- servers. For SSH, it runs a standard OpenSSH server. For SOCKS4/5 tests SSH
- is used to perform the SOCKS functionality and requires a SSH client and
- server.
+ servers. For SSH, it runs a standard OpenSSH server.
The listen port numbers for the test servers are picked randomly to allow
users to run multiple test cases concurrently and to not collide with other
@@ -75,47 +108,9 @@ SPDX-License-Identifier: curl
used, set the environment variable `NGHTTPX`. The default can also be
changed by specifying `--with-test-nghttpx=<path>` as argument to `configure`.
-### Run
-
- `./configure && make && make test`. This builds the test suite support code
- and invokes the 'runtests.pl' perl script to run all the tests. Edit the top
- variables of that script in case you have some specific needs, or run the
- script manually (after the support code has been built).
-
- The script breaks on the first test that doesn't do OK. Use `-a` to prevent
- the script from aborting on the first error. Run the script with `-v` for
- more verbose output. Use `-d` to run the test servers with debug output
- enabled as well. Specifying `-k` keeps all the log files generated by the
- test intact.
-
- Use `-s` for shorter output, or pass test numbers to run specific tests only
- (like `./runtests.pl 3 4` to test 3 and 4 only). It also supports test case
- ranges with 'to', as in `./runtests.pl 3 to 9` which runs the seven tests
- from 3 to 9. Any test numbers starting with ! are disabled, as are any test
- numbers found in the files `data/DISABLED` or `data/DISABLED.local` (one per
- line). The latter is meant for local temporary disables and will be ignored
- by git.
-
- Test cases mentioned in `DISABLED` can still be run if `-f` is provided.
-
- When `-s` is not present, each successful test will display on one line the
- test number and description and on the next line a set of flags, the test
- result, current test sequence, total number of tests to be run and an
- estimated amount of time to complete the test run. The flags consist of
- these letters describing what is checked in this test:
-
- s stdout
- d data
- u upload
- p protocol
- o output
- e exit code
- m memory
- v valgrind
-
### Shell startup scripts
- Tests which use the ssh test server, SCP/SFTP/SOCKS tests, might be badly
+ Tests which use the ssh test server, SCP/SFTP tests, might be badly
influenced by the output of system wide or user specific shell startup
scripts, .bashrc, .profile, /etc/csh.cshrc, .login, /etc/bashrc, etc. which
output text messages or escape sequences on user login. When these shell
diff --git a/tests/convsrctest.pl b/tests/convsrctest.pl
deleted file mode 100755
index cdb252aeb..000000000
--- a/tests/convsrctest.pl
+++ /dev/null
@@ -1,263 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-#***************************************************************************
-
-#=======================================================================
-# Read a test definition which exercises curl's --libcurl option.
-# Generate either compilable source code for a new test tool,
-# or a new test definition which runs the tool and expects the
-# same output.
-# This should verify that the --libcurl code really does perform
-# the same actions as the original curl invocation.
-#-----------------------------------------------------------------------
-# The output of curl's --libcurl option differs in several ways from
-# the code needed to integrate with the test tool environment:
-# - #include "test.h"
-# - no call of curl_global_init & curl_global_cleanup
-# - main() function vs. test() function
-# - no checking of curl_easy_setopt calls vs. test_setopt wrapper
-# - handling of stdout
-# - variable names ret & hnd vs. res & curl
-# - URL as literal string vs. passed as argument
-#=======================================================================
-use strict;
-use warnings;
-
-use getpart qw(
- getpart
- loadtest
- fulltest
- );
-
-# Boilerplate code for test tool
-my $head =
-'#include "test.h"
-#include "memdebug.h"
-
-int test(char *URL)
-{
- CURLcode res;
- CURL *curl;
-';
-# Other declarations from --libcurl come here
-# e.g. curl_slist
-my $init =
-'
- if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
- fprintf(stderr, "curl_global_init() failed\n");
- return TEST_ERR_MAJOR_BAD;
- }
-
- if ((curl = curl_easy_init()) == NULL) {
- fprintf(stderr, "curl_easy_init() failed\n");
- curl_global_cleanup();
- return TEST_ERR_MAJOR_BAD;
- }
-';
-# Option setting, perform and cleanup come here
-my $exit =
-' curl_global_cleanup();
-
- return (int)res;
-}
-';
-
-my $myname = leaf($0);
-sub usage {die "Usage: $myname -c|-test=num testfile\n";}
-
-sub main {
- @ARGV == 2
- or usage;
- my($opt,$testfile) = @ARGV;
-
- if(loadtest($testfile)) {
- die "$myname: $testfile doesn't look like a test case\n";
- }
-
- my $comment = sprintf("DO NOT EDIT - generated from %s by %s",
- leaf($testfile), $myname);
- if($opt eq '-c') {
- generate_c($comment);
- }
- elsif(my($num) = $opt =~ /^-test=(\d+)$/) {
- generate_test($comment, $num);
- }
- else {
- usage;
- }
-}
-
-sub generate_c {
- my($comment) = @_;
- # Fetch the generated code, which is the output file checked by
- # the old test.
- my @libcurl = getpart("verify", "file")
- or die "$myname: no <verify><file> section found\n";
-
- # Mangle the code into a suitable form for a test tool.
- # We want to extract the important parts (declarations,
- # URL, setopt calls, cleanup code) from the --libcurl
- # boilerplate and insert them into a new boilerplate.
- my(@decl,@code);
- # First URL passed in as argument, others as global
- my @urlvars = ('URL', 'libtest_arg2', 'libtest_arg3');
- my($seen_main,$seen_setopt,$seen_return);
- foreach (@libcurl) {
- # Check state changes first (even though it
- # duplicates some matches) so that the other tests
- # are in a logical order).
- if(/^int main/) {
- $seen_main = 1;
- }
- if($seen_main and /curl_easy_setopt/) {
- # Don't match 'curl_easy_setopt' in comment!
- $seen_setopt = 1;
- }
- if(/^\s*return/) {
- $seen_return = 1;
- }
-
- # Now filter the code according to purpose
- if(! $seen_main) {
- next;
- }
- elsif(! $seen_setopt) {
- if(/^\s*(int main|\{|CURLcode |CURL |hnd = curl_easy_init)/) {
- # Initialization handled by boilerplate
- next;
- }
- else {
- push @decl, $_;
- }
- }
- elsif(! $seen_return) {
- if(/CURLOPT_URL/) {
- # URL is passed in as argument or by global
- my $var = shift @urlvars;
- s/\"[^\"]*\"/$var/;
- }
- s/\bhnd\b/curl/;
- # Convert to macro wrapper
- s/curl_easy_setopt/test_setopt/;
- if(/curl_easy_perform/) {
- s/\bret\b/res/;
- push @code, $_;
- push @code, "test_cleanup:\n";
- }
- else {
- push @code, $_;
- }
- }
- }
-
- print("/* $comment */\n",
- $head,
- @decl,
- $init,
- @code,
- $exit);
-}
-
-# Read the original test data file and transform it
-# - add a "DO NOT EDIT comment"
-# - replace CURLOPT_URL string with URL variable
-# - remove <verify><file> section (was the --libcurl output)
-# - insert a <client><tool> section with our new C program name
-# - replace <client><command> section with the URL
-sub generate_test {
- my($comment,$newnumber) = @_;
- my @libcurl = getpart("verify", "file")
- or die "$myname: no <verify><file> section found\n";
- # Scan the --libcurl code to find the URL used.
- my $url;
- foreach (@libcurl) {
- if(my($u) = /CURLOPT_URL, \"([^\"]*)\"/) {
- $url = $u;
- }
- }
- die "$myname: CURLOPT_URL not found\n"
- unless defined $url;
-
- # Traverse the pseudo-XML transforming as required
- my @new;
- my(@path,$path,$skip);
- foreach (fulltest()) {
- if(my($end) = /\s*<(\/?)testcase>/) {
- push @new, $_;
- push @new, "# $comment\n"
- unless $end;
- }
- elsif(my($tag) = /^\s*<(\w+)/) {
- push @path, $tag;
- $path = join '/', @path;
- if($path eq 'verify/file') {
- $skip = 1;
- }
- push @new, $_
- unless $skip;
- if($path eq 'client') {
- push @new, ("<tool>\n",
- "lib$newnumber\n",
- "</tool>\n");
- }
- elsif($path eq 'client/command') {
- push @new, sh_quote($url)."\n";
- }
- }
- elsif(my($etag) = /^\s*<\/(\w+)/) {
- my $tag = pop @path;
- die "$myname: mismatched </$etag>\n"
- unless $tag eq $etag;
- push @new, $_
- unless $skip;
- $skip --
- if $path eq 'verify/file';
- $path = join '/', @path;
- }
- else {
- if($path eq 'client/command') {
- # Replaced above
- }
- else {
- push @new, $_
- unless $skip;
- }
- }
- }
- print @new;
-}
-
-sub leaf {
- # Works for POSIX filenames
- (my $path = shift) =~ s!.*/!!;
- return $path;
-}
-
-sub sh_quote {
- my $word = shift;
- $word =~ s/[\$\"\'\\]/\\$&/g;
- return '"' . $word . '"';
-}
-
-main;
diff --git a/tests/data/DISABLED b/tests/data/DISABLED
index 308d27e5a..a98dc8566 100644
--- a/tests/data/DISABLED
+++ b/tests/data/DISABLED
@@ -70,9 +70,6 @@
266
579
587
-722
-724
-727
# 1021 re-added here due to flakiness
1021
1117
@@ -84,6 +81,8 @@
2301
2302
2305
+# response body seem not to be handled by hyper
+2307
%endif
2043
# The CRL test (313) doesn't work with rustls because rustls doesn't support
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 1472b1954..c3d496f64 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -51,7 +51,7 @@ test226 test227 test228 test229 test230 test231 test232 test233 test234 \
test235 test236 test237 test238 test239 test240 test241 test242 test243 \
test244 test245 test246 test247 test248 test249 test250 test251 test252 \
test253 test254 test255 test256 test257 test258 test259 test260 test261 \
-test262 test263 test264 test265 test266 test267 test269 test270 \
+test262 test263 test264 test265 test266 test267 test268 test269 test270 \
test271 test272 test273 test274 test275 test276 test277 test278 test279 \
test280 test281 test282 test283 test284 test285 test286 test287 test288 \
test289 test290 test291 test292 test293 test294 test295 test296 test297 \
@@ -72,7 +72,7 @@ test417 test418 test419 test420 test421 test422 test423 test424 test425 \
test426 test427 test428 test429 test430 test431 test432 test433 test434 \
test435 test436 test437 test438 test439 test440 test441 test442 test443 \
test444 test445 test446 test447 test448 test449 test450 test451 test452 \
-test453 test454 test455 test456 test457 test458 \
+test453 test454 test455 test456 test457 test458 test459 test460 test461 \
\
test490 test491 test492 test493 test494 test495 test496 test497 test498 \
\
@@ -96,12 +96,13 @@ test644 test645 test646 test647 test648 test649 test650 test651 test652 \
test653 test654 test655 test656 test658 test659 test660 test661 test662 \
test663 test664 test665 test666 test667 test668 test669 test670 test671 \
test672 test673 test674 test675 test676 test677 test678 test679 test680 \
-test681 test682 test683 test684 test685 test686 test687 test688 \
+test681 test682 test683 test684 test685 test686 test687 test688 test689 \
\
test700 test701 test702 test703 test704 test705 test706 test707 test708 \
test709 test710 test711 test712 test713 test714 test715 test716 test717 \
test718 test719 test720 test721 test722 test723 test724 test725 test726 \
-test727 test728 \
+test727 test728 test729 test730 test731 test732 test733 test734 test735 \
+test736 test737 test738 test739 test740 test741 test742 \
\
test799 test800 test801 test802 test803 test804 test805 test806 test807 \
test808 test809 test810 test811 test812 test813 test814 test815 test816 \
@@ -124,7 +125,7 @@ test952 test953 test954 test955 test956 test957 test958 test959 test960 \
test961 test962 test963 test964 test965 test966 test967 test968 test969 \
test970 test971 test972 test973 test974 test975 test976 test977 test978 \
test979 test980 test981 test982 test983 test984 test985 test986 test987 \
-test988 test989 test990 test991 \
+test988 test989 test990 test991 test992 \
\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
@@ -185,14 +186,14 @@ test1439 test1440 test1441 test1442 test1443 test1444 test1445 test1446 \
test1447 test1448 test1449 test1450 test1451 test1452 test1453 test1454 \
test1455 test1456 test1457 test1458 test1459 test1460 test1461 test1462 \
test1463 test1464 test1465 test1466 test1467 test1468 test1469 test1470 \
-test1471 test1472 test1473 test1474 \
+test1471 test1472 test1473 test1475 test1476 test1477 test1478 \
\
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 test1542 test1543 test1544 \
+test1540 test1542 test1543 test1544 test1545 \
\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
@@ -214,11 +215,11 @@ test1670 test1671 \
\
test1680 test1681 test1682 test1683 \
\
-test1700 test1701 test1702 test1703 \
+test1700 test1701 test1702 test1703 test1704 \
\
test1800 test1801 \
\
- test1903 test1904 test1905 test1906 test1907 \
+test1900 test1903 test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
test1916 test1917 test1918 test1919 \
\
@@ -243,7 +244,7 @@ test2100 \
\
test2200 test2201 test2202 test2203 test2204 test2205 \
\
-test2300 test2301 test2302 test2303 test2304 test2305 test2306 \
+test2300 test2301 test2302 test2303 test2304 test2305 test2306 test2307 \
\
test2400 test2401 test2402 test2403 test2404 \
\
diff --git a/tests/data/test1026 b/tests/data/test1026
index d565f24d5..e310e6962 100644
--- a/tests/data/test1026
+++ b/tests/data/test1026
@@ -28,7 +28,7 @@ curl --manual
# Search for these two sentinel lines in the manual output; if they are found,
# then chances are good the entire manual is there.
<postcheck>
-perl -e 'open(IN,$ARGV[0]); my $lines=grep(/(curl\s*-\s*transfer\sa\s*URL)|(CONTRIBUTORS)/, <IN>); exit ($lines != 2); # Let this file pass an XML syntax check: </IN>' %LOGDIR/stdout%TESTNUMBER
+perl -e 'open(IN,$ARGV[0]); my $lines=grep(/(curl\s*-\s*transfer\sa\s*URL)|(AUTHORS)/, <IN>); exit ($lines != 2); # Let this file pass an XML syntax check: </IN>' %LOGDIR/stdout%TESTNUMBER
</postcheck>
</client>
diff --git a/tests/data/test1119 b/tests/data/test1119
index 41f6dba2c..1a73439e6 100644
--- a/tests/data/test1119
+++ b/tests/data/test1119
@@ -18,7 +18,7 @@ Verify that symbols-in-versions and headers are in sync
</name>
<command type="perl">
-%SRCDIR/symbol-scan.pl %SRCDIR/.. ../include/curl
+%SRCDIR/test1119.pl %SRCDIR/.. ../include/curl
</command>
</client>
diff --git a/tests/data/test1132 b/tests/data/test1132
index 613031bac..e7a802a71 100644
--- a/tests/data/test1132
+++ b/tests/data/test1132
@@ -18,7 +18,7 @@ Verify memory #include files in libcurl's C source files
</name>
<command type="perl">
-%SRCDIR/mem-include-scan.pl %SRCDIR/../lib
+%SRCDIR/test1132.pl %SRCDIR/../lib
</command>
</client>
diff --git a/tests/data/test1135 b/tests/data/test1135
index d188989ed..de028a0c9 100644
--- a/tests/data/test1135
+++ b/tests/data/test1135
@@ -22,7 +22,7 @@ Verify CURL_EXTERN order
</name>
<command type="perl">
-%SRCDIR/extern-scan.pl %SRCDIR/..
+%SRCDIR/test1135.pl %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1139 b/tests/data/test1139
index b5267b012..2704e0a21 100644
--- a/tests/data/test1139
+++ b/tests/data/test1139
@@ -20,7 +20,7 @@ Verify that all libcurl options have man pages
</name>
<command type="perl">
-%SRCDIR/manpage-scan.pl %SRCDIR/.. %PWD/..
+%SRCDIR/test1139.pl %SRCDIR/.. %PWD/..
</command>
</client>
diff --git a/tests/data/test1140 b/tests/data/test1140
index 5aa997e78..5f26c73f4 100644
--- a/tests/data/test1140
+++ b/tests/data/test1140
@@ -19,7 +19,7 @@ Verify the nroff of man pages
</name>
<command type="perl">
-%SRCDIR/nroff-scan.pl %SRCDIR/../docs/ %SRCDIR/../docs/libcurl/*.3 %SRCDIR/../docs/libcurl/opts/*.3 %SRCDIR/../docs/*.1
+%SRCDIR/test1140.pl %PWD/../docs/ %PWD/../docs/libcurl/*.3 %PWD/../docs/libcurl/opts/*.3 %PWD/../docs/*.1
</command>
</client>
diff --git a/tests/data/test1154 b/tests/data/test1154
index b7349e17d..bd08ce26c 100644
--- a/tests/data/test1154
+++ b/tests/data/test1154
@@ -47,9 +47,9 @@ User-Agent: curl/%VERSION
Accept: */*
</protocol>
-# 27 == CURLE_OUT_OF_MEMORY
+# 100 == CURLE_TOO_LARGE
<errorcode>
-27
+100
</errorcode>
</verify>
</testcase>
diff --git a/tests/data/test1165 b/tests/data/test1165
index de4283af2..89f02d719 100644
--- a/tests/data/test1165
+++ b/tests/data/test1165
@@ -18,7 +18,7 @@ Verify configure.ac and source code CURL_DISABLE_-sync
</name>
<command type="perl">
-%SRCDIR/disable-scan.pl %SRCDIR/..
+%SRCDIR/test1165.pl %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1167 b/tests/data/test1167
index 3c2fb1a5f..76777f81b 100644
--- a/tests/data/test1167
+++ b/tests/data/test1167
@@ -17,7 +17,7 @@ Verify curl prefix of public symbols in header files
</name>
<command type="perl">
-%SRCDIR/badsymbols.pl %SRCDIR/..
+%SRCDIR/test1167.pl %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1173 b/tests/data/test1173
index b5dafbb3b..97d338df3 100644
--- a/tests/data/test1173
+++ b/tests/data/test1173
@@ -19,7 +19,7 @@ Man page syntax checks
</name>
<command type="perl">
-%SRCDIR/manpage-syntax.pl %SRCDIR/../docs/libcurl/symbols-in-versions %SRCDIR/../docs/*.1 %SRCDIR/../docs/libcurl/*.3 %SRCDIR/../docs/libcurl/opts/*.3
+%SRCDIR/test1173.pl %SRCDIR/../docs/libcurl/symbols-in-versions %PWD/../docs/*.1 %PWD/../docs/libcurl/*.3 %PWD/../docs/libcurl/opts/*.3
</command>
</client>
diff --git a/tests/data/test1175 b/tests/data/test1175
index 5190dbe2a..6e99a616e 100644
--- a/tests/data/test1175
+++ b/tests/data/test1175
@@ -18,7 +18,7 @@ Verify that symbols-in-versions and libcurl-errors.3 are in sync
</name>
<command type="perl">
-%SRCDIR/error-codes.pl %SRCDIR
+%SRCDIR/test1175.pl %SRCDIR
</command>
</client>
diff --git a/tests/data/test1177 b/tests/data/test1177
index 66fe49767..6cc94a5b1 100644
--- a/tests/data/test1177
+++ b/tests/data/test1177
@@ -18,7 +18,7 @@ Verify that feature names and CURL_VERSION_* in lib and docs are in sync
</name>
<command type="perl">
-%SRCDIR/version-scan.pl %SRCDIR/../docs/libcurl/curl_version_info.3 %SRCDIR/../include/curl/curl.h %SRCDIR/../lib/version.c
+%SRCDIR/test1177.pl %PWD/../docs/libcurl/curl_version_info.3 %SRCDIR/../include/curl/curl.h %SRCDIR/../lib/version.c
</command>
</client>
diff --git a/tests/data/test1222 b/tests/data/test1222
index b56cf6879..b46fd1156 100644
--- a/tests/data/test1222
+++ b/tests/data/test1222
@@ -17,7 +17,7 @@ Verify deprecation statuses and versions
</name>
<command type="perl">
-%SRCDIR/check-deprecated.pl %SRCDIR/..
+%SRCDIR/test1222.pl %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1254 b/tests/data/test1254
index a39cbd26e..07e77ed2a 100644
--- a/tests/data/test1254
+++ b/tests/data/test1254
@@ -27,7 +27,7 @@ foo
http
</server>
<name>
-Under condition using --proxy, override NO_PROXY by --nproxy and access target URL through proxy
+override NO_PROXY by --noproxy and access target URL through proxy
</name>
<setenv>
NO_PROXY=example.com
diff --git a/tests/data/test1268 b/tests/data/test1268
index 806592fb8..05fe9d8e7 100644
--- a/tests/data/test1268
+++ b/tests/data/test1268
@@ -30,7 +30,7 @@ file name argument looks like a flag
<verify>
<file name="%LOGDIR/moo%TESTNUMBER" mode="text">
Warning: The file name argument '-k' looks like a flag.
-curl: (1) Protocol "hej" not supported or disabled in libcurl
+curl: (1) Protocol "hej" not supported
</file>
# we expect an error since we provide a weird URL
diff --git a/tests/data/test1275 b/tests/data/test1275
index d1cb223b8..31893f7ba 100644
--- a/tests/data/test1275
+++ b/tests/data/test1275
@@ -18,7 +18,7 @@ Verify capital letters after period in markdown files
</name>
<command type="perl">
-%SRCDIR/markdown-uppercase.pl %SRCDIR/..
+%SRCDIR/test1275.pl %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1276 b/tests/data/test1276
index 3961bf4cb..b365f800a 100644
--- a/tests/data/test1276
+++ b/tests/data/test1276
@@ -18,7 +18,7 @@ Verify lib/optiontable.pl
</name>
<command type="perl">
-%SRCDIR/option-check.pl %SRCDIR/..
+%SRCDIR/test1276.pl %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1279 b/tests/data/test1279
index fd3b34bd3..041f5449b 100644
--- a/tests/data/test1279
+++ b/tests/data/test1279
@@ -19,7 +19,7 @@ Verify libcurl.def against CURL_EXTERN declarations
</name>
<command type="perl">
-%SRCDIR/extern-scan.pl --heading=EXPORTS --sort %SRCDIR/..
+%SRCDIR/test1135.pl --heading=EXPORTS --sort %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1474 b/tests/data/test1474
deleted file mode 100644
index a87044d1a..000000000
--- a/tests/data/test1474
+++ /dev/null
@@ -1,121 +0,0 @@
-<testcase>
-# This test is quite timing dependent and tricky to set up. The time line of
-# test operations looks like this:
-#
-# 1. curl sends a PUT request with Expect: 100-continue and waits only 1 msec
-# for a 100 response.
-# 2. The HTTP server accepts the connection but waits 500 msec before acting
-# on the request.
-# 3. curl doesn't receive the expected 100 response before its timeout expires,
-# so it starts sending the body. It is throttled by a --limit-rate, so it
-# sends the first 64 KiB then stops for 1000 msec due to this
-# throttling.
-# 4. The server sends its 417 response while curl is throttled.
-# 5. curl responds to this 417 response by closing the connection (because it
-# has a half-completed response outstanding) and starting a new one. This
-# new request does not have an Expect: header so it is sent without delay.
-# It's still throttled, however, so it takes about 16 seconds to finish
-# sending.
-# 6. The server receives the response and this time acks it with 200.
-#
-# Because of the timing sensitivity (scheduling delays of 500 msec can cause
-# the test to fail), this test is marked flaky to avoid it being run in the CI
-# builds which are often run on overloaded servers.
-# Increasing the --limit-rate would decrease the test time, but at the cost of
-# becoming even more sensitive to delays (going from 500 msec to 250 msec or
-# less of accepted delay before failure). Adding a --speed-time would increase
-# the 1 second delay between writes to longer, but it would also increase the
-# total time needed by the test, which is already quite high.
-#
-# The assumption in step 3 is also broken on NetBSD 9.3, OpenBSD 7.3 and
-# Solaris 10 as they only usually send about half the requested amount of data
-# (see https://curl.se/mail/lib-2023-09/0021.html).
-<info>
-<keywords>
-HTTP
-HTTP PUT
-Expect
-flaky
-timing-dependent
-</keywords>
-</info>
-# Server-side
-<reply>
-# 417 means the server didn't like the Expect header
-<data>
-HTTP/1.1 417 BAD swsbounce
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Content-Length: 0
-
-</data>
-<data1>
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Content-Length: 10
-
-blablabla
-</data1>
-<datacheck>
-HTTP/1.1 417 BAD swsbounce
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Content-Length: 0
-
-HTTP/1.1 200 OK
-Date: Tue, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Content-Length: 10
-
-blablabla
-</datacheck>
-<servercmd>
-no-expect
-delay: 500
-connection-monitor
-</servercmd>
-</reply>
-
-# Client-side
-<client>
-<server>
-http
-</server>
-<name>
-HTTP PUT with Expect: 100-continue and 417 response during upload
-</name>
-<command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt --limit-rate 64K --expect100-timeout 0.001
-</command>
-<precheck>
-perl -e "print 'Test does not work on this BSD system' if ( $^O eq 'netbsd' || $^O eq 'openbsd' || ($^O eq 'solaris' && qx/uname -r/ * 100 <= 510));"
-</precheck>
-# Must be large enough to trigger curl's automatic 100-continue behaviour
-<file name="%LOGDIR/test%TESTNUMBER.txt">
-%repeat[132 x S]%%repeat[16462 x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%0a]%
-</file>
-</client>
-
-# Verify data after the test has been "shot"
-<verify>
-<protocol>
-PUT /we/want/%TESTNUMBER HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-User-Agent: curl/%VERSION
-Accept: */*
-Content-Length: 1053701
-Expect: 100-continue
-
-%repeat[132 x S]%%repeat[1021 x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%0a]%%repeat[60 x x]%[DISCONNECT]
-PUT /we/want/%TESTNUMBER HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-User-Agent: curl/%VERSION
-Accept: */*
-Content-Length: 1053701
-
-%repeat[132 x S]%%repeat[16462 x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%0a]%
-[DISCONNECT]
-</protocol>
-</verify>
-</testcase>
diff --git a/tests/data/test1475 b/tests/data/test1475
new file mode 100644
index 000000000..f88ef74ee
--- /dev/null
+++ b/tests/data/test1475
@@ -0,0 +1,83 @@
+<testcase>
+# also verified by 1156 in libcurl API terms
+
+<info>
+<keywords>
+HTTP
+HTTP GET
+Resume
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+HTTP/1.1 416 Invalid range
+Connection: close
+Content-Length: 0
+Content-Range: */100
+
+</data>
+
+# The file data that exists at the start of the test must be included in
+# the verification.
+<datacheck>
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+HTTP/1.1 416 Invalid range
+Connection: close
+Content-Length: 0
+Content-Range: */100
+
+</datacheck>
+
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<killserver>
+http
+</killserver>
+<name>
+-f and 416 with Content-Range: */size
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -C - -f
+</command>
+<file name="%LOGDIR/curl%TESTNUMBER.out">
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+012345678
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Range: bytes=100-
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1476 b/tests/data/test1476
new file mode 100644
index 000000000..101fa95b0
--- /dev/null
+++ b/tests/data/test1476
@@ -0,0 +1,59 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 0
+Set-Cookie: super=oops; domain=co.UK; path=/
+Set-Cookie: fine=yesyes; domain=CURL.CO.UK; path=/
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+PSL violating cookie with mixed case domain and cookie domain property
+</name>
+<command>
+-x http://%HOSTIP:%HTTPPORT/%TESTNUMBER http://curl.co.UK -c %LOGDIR/cookies%TESTNUMBER.txt
+</command>
+<features>
+proxy
+PSL
+cookies
+</features>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET http://curl.co.UK/ HTTP/1.1
+Host: curl.co.UK
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+<file name="%LOGDIR/cookies%TESTNUMBER.txt" mode="text">
+# Netscape HTTP Cookie File
+# https://curl.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+.CURL.CO.UK TRUE / FALSE 0 fine yesyes
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test1477 b/tests/data/test1477
new file mode 100644
index 000000000..a8c4659e4
--- /dev/null
+++ b/tests/data/test1477
@@ -0,0 +1,30 @@
+<testcase>
+<info>
+<keywords>
+documentation
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+<name>
+Verify that error codes in headers and libcurl-errors.3 are in sync
+</name>
+
+<command type="perl">
+%SRCDIR/test1477.pl %SRCDIR/.. %PWD/..
+</command>
+</client>
+
+<verify>
+<stdout>
+Result
+</stdout>
+</verify>
+
+</testcase>
diff --git a/tests/data/test1478 b/tests/data/test1478
new file mode 100644
index 000000000..b489ac038
--- /dev/null
+++ b/tests/data/test1478
@@ -0,0 +1,32 @@
+<testcase>
+<info>
+<keywords>
+source analysis
+documentation
+--help
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+<name>
+src/tool_listhelp.c is in sync with docs/cmdline-opts
+</name>
+
+<command type="perl">
+%SRCDIR/../docs/cmdline-opts/gen.pl listhelp %SRCDIR/../docs/cmdline-opts/*.md
+</command>
+</client>
+
+<verify>
+<stdout mode="text">
+%include %SRCDIR/../src/tool_listhelp.c%
+</stdout>
+</verify>
+
+</testcase>
diff --git a/tests/data/test1506 b/tests/data/test1506
index 9eb38cf6d..0a62c0c2a 100644
--- a/tests/data/test1506
+++ b/tests/data/test1506
@@ -86,7 +86,6 @@ Accept: */*
* Connection #0 to host server1.example.com left intact
* Connection #1 to host server2.example.com left intact
* Connection #2 to host server3.example.com left intact
-* Closing connection
* Connection #3 to host server4.example.com left intact
</file>
<stripfile>
diff --git a/tests/data/test1538 b/tests/data/test1538
index 59cd1628e..c0f038be4 100644
--- a/tests/data/test1538
+++ b/tests/data/test1538
@@ -132,7 +132,8 @@ e96: QUIC connection error
e97: proxy handshake error
e98: SSL Client Certificate required
e99: Unrecoverable error in select/poll
-e100: Unknown error
+e100: A value or data field grew larger than allowed
+e101: Unknown error
m-1: Please call curl_multi_perform() soon
m0: No error
m1: Invalid multi handle
@@ -186,7 +187,8 @@ u27: Bad scheme
u28: Unsupported number of slashes following scheme
u29: Bad user
u30: libcurl lacks IDN support
-u31: CURLUcode unknown
+u31: A value or data field is larger than allowed
+u32: CURLUcode unknown
</stdout>
</verify>
diff --git a/tests/data/test1544 b/tests/data/test1544
index f658f5a74..037caa0ac 100644
--- a/tests/data/test1544
+++ b/tests/data/test1544
@@ -17,7 +17,7 @@ Verify all string options are translated by OS/400 wrapper
</name>
<command type="perl">
-%SRCDIR/check-translatable-options.pl %SRCDIR/..
+%SRCDIR/test1544.pl %SRCDIR/..
</command>
</client>
diff --git a/tests/data/test1545 b/tests/data/test1545
new file mode 100644
index 000000000..477b5bf44
--- /dev/null
+++ b/tests/data/test1545
@@ -0,0 +1,38 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+</reply>
+
+# Client-side
+<client>
+<features>
+form-api
+</features>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<name>
+use curl_formadd() data twice with unreadable file
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+</verify>
+</testcase>
diff --git a/tests/data/test1683 b/tests/data/test1683
index 178b4054d..581470dfc 100644
--- a/tests/data/test1683
+++ b/tests/data/test1683
@@ -40,11 +40,9 @@ to stay the same
</file>
<precheck>
perl -e 'for my $i ((1..100)) { my $filename = "%LOGDIR/exist%TESTNUMBER.$i"; open(FH, ">", $filename) or die $!; print FH "to stay the same" ; close(FH) }'
-# python3 -c 'for i in range(1, 101): open("%LOGDIR/exist%TESTNUMBER.{}".format(i), mode="w").write("to stay the same")'
</precheck>
<postcheck>
perl -e 'for my $i ((1..100)) { my $filename = "%LOGDIR/exist%TESTNUMBER.$i"; open(FH, "<", $filename) or die $!; (<FH> eq "to stay the same" and <FH> eq "") or die "incorrect $filename" ; close(FH) }'
-# python3 -c 'for i in range(1, 101): assert open("%LOGDIR/exist%TESTNUMBER.{}".format(i), mode="r").read(17) == "to stay the same"'
</postcheck>
</client>
diff --git a/tests/data/test1704 b/tests/data/test1704
new file mode 100644
index 000000000..a8f285eea
--- /dev/null
+++ b/tests/data/test1704
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP/2
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/2 101 OK
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+
+-maa-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+h2c
+</features>
+<server>
+http
+</server>
+<name>
+HTTP/1 doing HTTP/2 Upgrade: getting a HTTP/2 101 response
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --http2
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^X-Forwarded-Proto:.*
+^Via:.*
+</strip>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Connection: Upgrade, HTTP2-Settings
+Upgrade: h2c
+HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA
+
+</protocol>
+
+# CURLE_WEIRD_SERVER_REPLY (8)
+<errorcode>
+8
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test19 b/tests/data/test19
index 265a74ad8..cf735a42f 100644
--- a/tests/data/test19
+++ b/tests/data/test19
@@ -24,7 +24,7 @@ http
attempt connect to non-listening socket
</name>
<command>
-%HOSTIP:%NOLISTENPORT
+--trace-config all %HOSTIP:%NOLISTENPORT
</command>
</client>
diff --git a/tests/data/test1900 b/tests/data/test1900
new file mode 100644
index 000000000..f04e7e2af
--- /dev/null
+++ b/tests/data/test1900
@@ -0,0 +1,38 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HSTS
+</keywords>
+</info>
+
+# Server-side
+<reply>
+</reply>
+
+# Client-side
+<client>
+<features>
+HSTS
+http
+</features>
+<server>
+none
+</server>
+
+<name>
+HSTS curl_easy_duphandle
+</name>
+<tool>
+lib%TESTNUMBER
+</tool>
+
+<command>
+http://%HOSTIP:%NOLISTENPORT/not-there/%TESTNUMBER
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+</verify>
+</testcase>
diff --git a/tests/data/test194 b/tests/data/test194
index 4de767e3a..074348950 100644
--- a/tests/data/test194
+++ b/tests/data/test194
@@ -64,9 +64,8 @@ User-Agent: curl/%VERSION
Accept: */*
</protocol>
-# CURLE_HTTP_RETURNED_ERROR
<errorcode>
-22
+0
</errorcode>
</verify>
</testcase>
diff --git a/tests/data/test1940 b/tests/data/test1940
index 7f621b428..f4c6dd1a1 100644
--- a/tests/data/test1940
+++ b/tests/data/test1940
@@ -19,6 +19,8 @@ Content-Length: 0
Set-Cookie: onecookie=data;
Set-Cookie: secondcookie=2data;
Set-Cookie: cookie3=data3;
+Blank:
+Blank2:
Location: /%TESTNUMBER0002
</data>
@@ -57,6 +59,8 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER
- Set-Cookie == secondcookie=2data; (1/3)
- Set-Cookie == cookie3=data3; (2/3)
Fold == is folding a line
+ Blank ==
+ Blank2 ==
</stdout>
</verify>
</testcase>
diff --git a/tests/data/test2307 b/tests/data/test2307
new file mode 100644
index 000000000..ce260ac1c
--- /dev/null
+++ b/tests/data/test2307
@@ -0,0 +1,71 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+# Sends a PING with overlong payload
+<reply>
+<data nocheck="yes" nonewline="yes">
+HTTP/1.1 101 Switching to WebSockets
+Server: test-server/fake
+Upgrade: websocket
+Connection: Upgrade
+Something: else
+Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs=
+
+%hex[%19%7f%ff%30%30%30%30%30%30%30%30%30%30%30%30]hex%
+</data>
+# allow upgrade
+<servercmd>
+upgrade
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# require debug for the forced CURL_ENTROPY
+<features>
+debug
+ws
+!hyper
+</features>
+<server>
+http
+</server>
+<name>
+WebSockets, overlong PING payload
+</name>
+<tool>
+lib2302
+</tool>
+<command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# PONG with no data and the 32 bit mask
+#
+<verify>
+<protocol nocheck="yes" nonewline="yes">
+GET /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: webbie-sox/3
+Accept: */*
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Version: 13
+Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==
+
+
+</protocol>
+# 56 == CURLE_RECV_ERROR
+<errorcode>
+56
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test250 b/tests/data/test250
index 3c16fcd7b..455d9ea1a 100644
--- a/tests/data/test250
+++ b/tests/data/test250
@@ -38,7 +38,7 @@ ftp
<name>
FTP dir list PASV with slow response
</name>
-<command>
+<command option="binary-trace">
ftp://%HOSTIP:%FTPPORT/
</command>
</client>
diff --git a/tests/data/test268 b/tests/data/test268
new file mode 100644
index 000000000..3a1ab6a9b
--- /dev/null
+++ b/tests/data/test268
@@ -0,0 +1,59 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+variables
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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>
+JSON encoding of unicode string
+</name>
+<file name="%LOGDIR/junk" nonewline="yes">
+%hex[%e2%80%9c]hex%
+</file>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --variable hello@%LOGDIR/junk --expand-data {{hello:json}}
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes" nonewline="yes">
+POST /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+%hex[%e2%80%9c]hex%
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test285 b/tests/data/test285
index 7968e1a34..03dc96f6a 100644
--- a/tests/data/test285
+++ b/tests/data/test285
@@ -16,7 +16,7 @@ tftp
TFTP send
</name>
<command>
--T %LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT// --connect-time 549
+-T %LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT// --connect-timeout 549
</command>
<file name="%LOGDIR/test%TESTNUMBER.txt">
a chunk of
diff --git a/tests/data/test3012 b/tests/data/test3012
index 2bd329455..a9c950587 100644
--- a/tests/data/test3012
+++ b/tests/data/test3012
@@ -4,6 +4,7 @@
-O
-J
--output-dir
+--remote-time
</keywords>
</info>
#
@@ -36,10 +37,10 @@ http
http
</features>
<name>
---output-dir with -J
+--output-dir with -J and -R
</name>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -OJ --output-dir %PWD/%LOGDIR
+http://%HOSTIP:%HTTPPORT/this/is/the/%TESTNUMBER -OJR --output-dir %PWD/%LOGDIR
</command>
</client>
diff --git a/tests/data/test3103 b/tests/data/test3103
index 23a0fea17..423c4adaa 100644
--- a/tests/data/test3103
+++ b/tests/data/test3103
@@ -48,7 +48,7 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER
#
# Verify data after the test has been "shot"
<verify>
-<protocol crlf=yes>
+<protocol crlf="yes">
GET http://localhost/ HTTP/1.1
Host: localhost
Accept: */*
diff --git a/tests/data/test421 b/tests/data/test421
index 0e4130b06..2c79c1f8f 100644
--- a/tests/data/test421
+++ b/tests/data/test421
@@ -71,7 +71,7 @@ Accept: */*
"access-control-allow-methods":["GET, POST, PUT, DELETE, OPTIONS"],
"access-control-max-age":["1728000"],
"access-control-allow-headers":["Authorization, Content-Type, AuthorizationOauth, X-EARLY-ACCESS"],
-"access-control-expose-headers":["\r"],
+"access-control-expose-headers":[""],
"etag":["W/\"2678f9ab2ba550d164e7cc014aefd31e\""],
"cache-control":["max-age=0, private, must-revalidate"],
"x-request-id":["375b343b3d2ecf9b442c0daf00fc4a9a"],
diff --git a/tests/data/test439 b/tests/data/test439
index da1261531..c997a397a 100644
--- a/tests/data/test439
+++ b/tests/data/test439
@@ -38,7 +38,7 @@ debug
aws-sigv4 with query
</name>
<command>
-"http://fake.fake.fake:8000/%TESTNUMBER/?name=me%&aim=b%aad&&&weirdo=*.//-" -u user:secret --aws-sigv4 "aws:amz:us-east-2:es" --connect-to fake.fake.fake:8000:%HOSTIP:%HTTPPORT
+"http://fake.fake.fake:8000/%TESTNUMBER/?name=me%&noval&aim=b%aad&&&weirdo=*.//-" -u user:secret --aws-sigv4 "aws:amz:us-east-2:es" --connect-to fake.fake.fake:8000:%HOSTIP:%HTTPPORT
</command>
</client>
@@ -46,9 +46,9 @@ aws-sigv4 with query
# Verify data after the test has been "shot"
<verify>
<protocol crlf="yes">
-GET /%TESTNUMBER/?name=me%&aim=b%aad&&&weirdo=*.//- HTTP/1.1
+GET /439/?name=me%&noval&aim=b%aad&&&weirdo=*.//- HTTP/1.1
Host: fake.fake.fake:8000
-Authorization: AWS4-HMAC-SHA256 Credential=user/19700101/us-east-2/es/aws4_request, SignedHeaders=host;x-amz-date, Signature=88884e3b3142133685b2092d29d8b522b785b1a9ec9e4a90cbea83e882f8dcb6
+Authorization: AWS4-HMAC-SHA256 Credential=user/19700101/us-east-2/es/aws4_request, SignedHeaders=host;x-amz-date, Signature=cbbf4a72764e27e396730f5e56cea046d4ce862a2d91db4856fb086b92f49270
X-Amz-Date: 19700101T000000Z
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/data/test457 b/tests/data/test457
index 77eb9c855..aa391d7fd 100644
--- a/tests/data/test457
+++ b/tests/data/test457
@@ -20,7 +20,8 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
30
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
21;heresatest=moooo
-cccccccccccccccccccccccccccccccc
+cccccccccccccccccccccccccccccc
+c
0
@@ -31,7 +32,7 @@ Server: fakeit/0.9 fakeitbad/1.0
Transfer-Encoding: chunked
Connection: mooo
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccc
</datacheck>
</reply>
diff --git a/tests/data/test459 b/tests/data/test459
new file mode 100644
index 000000000..e46d02973
--- /dev/null
+++ b/tests/data/test459
@@ -0,0 +1,63 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+--config
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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>
+config file with argument using whitespace missing quotes
+</name>
+<file name="%LOGDIR/config">
+data = arg with space
+</file>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --config %LOGDIR/config --silent
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes" nonewline="yes">
+POST /%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+arg
+</protocol>
+<stderr mode="text">
+Warning: %LOGDIR/config:1: warning: 'data' uses unquoted whitespace
+Warning: This may cause side-effects. Consider using double quotes?
+</stderr>
+</verify>
+</testcase>
diff --git a/tests/data/test460 b/tests/data/test460
new file mode 100644
index 000000000..824166a81
--- /dev/null
+++ b/tests/data/test460
@@ -0,0 +1,28 @@
+<testcase>
+<info>
+<keywords>
+variables
+expand
+</keywords>
+</info>
+
+# Client-side
+<client>
+<server>
+none
+</server>
+<name>
+try --expand without an argument
+</name>
+<command>
+--expand-url
+</command>
+</client>
+
+#
+<verify>
+<errorcode>
+2
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test461 b/tests/data/test461
new file mode 100644
index 000000000..03d7c7a22
--- /dev/null
+++ b/tests/data/test461
@@ -0,0 +1,48 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+--header
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+disable Host: when specified as lower case
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER -H host:
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER HTTP/1.1
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test498 b/tests/data/test498
index 457c28043..b1fc02380 100644
--- a/tests/data/test498
+++ b/tests/data/test498
@@ -35,7 +35,7 @@ http
Reject too large HTTP response headers on endless redirects
</name>
<command>
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER --max-redir 400 --location
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER --max-redirs 400 --location
</command>
</client>
diff --git a/tests/data/test689 b/tests/data/test689
new file mode 100644
index 000000000..821556dec
--- /dev/null
+++ b/tests/data/test689
@@ -0,0 +1,53 @@
+<testcase>
+
+#Informational
+<info>
+<keywords>
+RTSP
+OPTIONS
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+RTSP/7.1 786
+
+RTSP/
+</data>
+<datacheck>
+</datacheck>
+</reply>
+
+# Client-Side
+<client>
+<server>
+rtsp
+</server>
+<tool>
+lib567
+</tool>
+
+<name>
+fuzzing crash issue #12701
+</name>
+<command>
+rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER
+</command>
+</client>
+
+<verify>
+<protocol>
+OPTIONS rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER RTSP/1.0
+CSeq: 1
+User-Agent: test567
+Test-Number: 567
+
+</protocol>
+# 8 == CURLE_WEIRD_SERVER_REPLY
+<errorcode>
+8
+</errorcode>
+</verify>
+
+</testcase>
diff --git a/tests/data/test722 b/tests/data/test722
index 674efd14a..c5b8d8610 100644
--- a/tests/data/test722
+++ b/tests/data/test722
@@ -8,7 +8,7 @@ IPFS
#
# Server-side
<reply>
-<data>
+<data nocheck="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -34,7 +34,7 @@ http
IPFS
</name>
<command>
---ipfs-gateway http://%HOSTIP:%HTTPPORT/%TESTNUMBER ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx
+--ipfs-gateway http://%HOSTIP:%HTTPPORT ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
</command>
</client>
@@ -42,7 +42,7 @@ IPFS
# Verify data after the test has been "shot"
<verify>
<protocol crlf="yes">
-GET /ipfs/QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx HTTP/1.1
+GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/data/test723 b/tests/data/test723
index aaf4d27a3..dac78fc54 100644
--- a/tests/data/test723
+++ b/tests/data/test723
@@ -20,7 +20,7 @@ http
IPFS with malformed gateway URL (bad function argument error)
</name>
<command>
---ipfs-gateway http://nonexisting,local:8080/%TESTNUMBER ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx
+--ipfs-gateway http://nonexisting,local:8080 ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
</command>
</client>
diff --git a/tests/data/test724 b/tests/data/test724
index 692046b31..c97354b0d 100644
--- a/tests/data/test724
+++ b/tests/data/test724
@@ -8,7 +8,7 @@ IPFS
#
# Server-side
<reply>
-<data>
+<data nocheck="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -37,10 +37,10 @@ HOME=%PWD/%LOGDIR
IPFS with gateway URL from gateway file
</name>
<command>
-ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
</command>
<file name="%LOGDIR/.ipfs/gateway" >
-http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+http://%HOSTIP:%HTTPPORT
</file>
</client>
@@ -48,7 +48,7 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER
# Verify data after the test has been "shot"
<verify>
<protocol crlf="yes">
-GET /ipfs/QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx HTTP/1.1
+GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/data/test725 b/tests/data/test725
index cf3c19664..de7c39493 100644
--- a/tests/data/test725
+++ b/tests/data/test725
@@ -23,10 +23,10 @@ HOME=%PWD/%LOGDIR
IPFS with malformed gateway URL from gateway file
</name>
<command>
-ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
</command>
<file name="%LOGDIR/.ipfs/gateway" >
-http://nonexisting,local:8080/%TESTNUMBER
+http://nonexisting,local:8080
</file>
</client>
diff --git a/tests/data/test726 b/tests/data/test726
index c0abbf29c..f51adf594 100644
--- a/tests/data/test726
+++ b/tests/data/test726
@@ -26,7 +26,7 @@ HOME=%PWD
IPFS with no gateway URL (no environment or home file either)
</name>
<command>
-ipfs://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
</command>
</client>
diff --git a/tests/data/test727 b/tests/data/test727
index e71ef5f44..aa2c84fbc 100644
--- a/tests/data/test727
+++ b/tests/data/test727
@@ -8,7 +8,7 @@ IPNS
#
# Server-side
<reply>
-<data>
+<data nocheck="yes">
HTTP/1.1 200 OK
Date: Tue, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
@@ -34,7 +34,7 @@ http
IPNS
</name>
<command>
---ipfs-gateway http://%HOSTIP:%HTTPPORT/%TESTNUMBER ipns://QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx
+--ipfs-gateway http://%HOSTIP:%HTTPPORT ipns://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
</command>
</client>
@@ -42,7 +42,7 @@ IPNS
# Verify data after the test has been "shot"
<verify>
<protocol crlf="yes">
-GET /ipns/QmV5JejrpgUxnkZeFZYMxVCqAbKy3KdPXWXyuEDiMNZwUx HTTP/1.1
+GET /ipns/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/data/test729 b/tests/data/test729
new file mode 100644
index 000000000..805758921
--- /dev/null
+++ b/tests/data/test729
@@ -0,0 +1,41 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+SOCKS4
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+socks4
+</server>
+<name>
+SOCKS4 with very long proxy user name
+</name>
+<command>
+http://fake --limit-rate 1 -x socks4a://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@%HOSTIP:%SOCKSPORT
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# CURLE_PROXY
+<errorcode>
+97
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test730 b/tests/data/test730
new file mode 100644
index 000000000..138f85086
--- /dev/null
+++ b/tests/data/test730
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+IPFS arg gateway with path
+</name>
+<command>
+--ipfs-gateway http://%HOSTIP:%HTTPPORT/foo/bar ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /foo/bar/ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test731 b/tests/data/test731
new file mode 100644
index 000000000..9e135dbec
--- /dev/null
+++ b/tests/data/test731
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<setenv>
+HOME=%PWD/%LOGDIR
+</setenv>
+<name>
+IPFS with gateway URL and path from gateway file
+</name>
+<command>
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
+</command>
+<file name="%LOGDIR/.ipfs/gateway" >
+http://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /%TESTNUMBER/ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test732 b/tests/data/test732
new file mode 100644
index 000000000..9adaedb93
--- /dev/null
+++ b/tests/data/test732
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+IPFS with path
+</name>
+<command>
+--ipfs-gateway http://%HOSTIP:%HTTPPORT "ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test733 b/tests/data/test733
new file mode 100644
index 000000000..ad17cd4bf
--- /dev/null
+++ b/tests/data/test733
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+IPFS with path and query args
+</name>
+<command>
+--ipfs-gateway http://%HOSTIP:%HTTPPORT "ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test734 b/tests/data/test734
new file mode 100644
index 000000000..03f571cc6
--- /dev/null
+++ b/tests/data/test734
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+IPFS with path, query args and gateway with path
+</name>
+<command>
+--ipfs-gateway http://%HOSTIP:%HTTPPORT/some/path "ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /some/path/ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u/a/b?foo=bar&aaa=bbb HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test735 b/tests/data/test735
new file mode 100644
index 000000000..da1aac4dd
--- /dev/null
+++ b/tests/data/test735
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+IPNS with path, query args and gateway with path
+</name>
+<command>
+--ipfs-gateway http://%HOSTIP:%HTTPPORT/some/path "ipns://fancy.tld/a/b?foo=bar&aaa=bbb"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /some/path/ipns/fancy.tld/a/b?foo=bar&aaa=bbb HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test736 b/tests/data/test736
new file mode 100644
index 000000000..45d9a055a
--- /dev/null
+++ b/tests/data/test736
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<setenv>
+IPFS_PATH=%LOGDIR/.ipfs
+</setenv>
+<name>
+IPFS with IPFS_PATH set, no trailing slash
+</name>
+<command>
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
+</command>
+<file name="%LOGDIR/.ipfs/gateway" >
+http://%HOSTIP:%HTTPPORT
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test737 b/tests/data/test737
new file mode 100644
index 000000000..bc6e8576a
--- /dev/null
+++ b/tests/data/test737
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<setenv>
+IPFS_PATH=%LOGDIR/.ipfs/
+</setenv>
+<name>
+IPFS with IPFS_PATH set, with trailing slash
+</name>
+<command>
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
+</command>
+<file name="%LOGDIR/.ipfs/gateway" >
+http://%HOSTIP:%HTTPPORT
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test738 b/tests/data/test738
new file mode 100644
index 000000000..5c05137dc
--- /dev/null
+++ b/tests/data/test738
@@ -0,0 +1,37 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<setenv>
+IPFS_PATH=%LOGDIR/.ipfs/
+</setenv>
+<name>
+IPFS with IPFS_PATH, no gateway file
+</name>
+<command>
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
+</command>
+</client>
+
+#
+# Verify error code with no gateway file (detection fails)
+<verify>
+<errorcode>
+37
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test739 b/tests/data/test739
new file mode 100644
index 000000000..fe78c41bb
--- /dev/null
+++ b/tests/data/test739
@@ -0,0 +1,34 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+IPNS path and query args for gateway and IPFS url (malformed gateway url)
+</name>
+<command>
+--ipfs-gateway "http://%HOSTIP:%HTTPPORT/some/path?biz=baz" "ipns://fancy.tld/a/b?foo=bar&aaa=bbb"
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+3
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test740 b/tests/data/test740
new file mode 100644
index 000000000..97258d384
--- /dev/null
+++ b/tests/data/test740
@@ -0,0 +1,60 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Tue, 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: 21
+Connection: close
+Content-Type: text/plain
+Funny-head: yesyes
+
+Hello curl from IPFS
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<setenv>
+HOME=%PWD/%LOGDIR
+</setenv>
+<name>
+IPFS with gateway URL from multiline gateway file
+</name>
+<command>
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
+</command>
+<file name="%LOGDIR/.ipfs/gateway" >
+http://%HOSTIP:%HTTPPORT
+foo
+bar
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="yes">
+GET /ipfs/bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test741 b/tests/data/test741
new file mode 100644
index 000000000..e773cd08a
--- /dev/null
+++ b/tests/data/test741
@@ -0,0 +1,42 @@
+<testcase>
+<info>
+<keywords>
+IPFS
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<setenv>
+HOME=%PWD/%LOGDIR
+</setenv>
+<name>
+IPFS with malformed gateway URL from multiline gateway file, first line no url
+</name>
+<command>
+ipfs://bafybeidecnvkrygux6uoukouzps5ofkeevoqland7kopseiod6pzqvjg7u
+</command>
+<file name="%LOGDIR/.ipfs/gateway" >
+foo
+bar
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# malformed gateway URL, first line in file must be a gateway URL
+<errorcode>
+3
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test742 b/tests/data/test742
new file mode 100644
index 000000000..34e284d18
--- /dev/null
+++ b/tests/data/test742
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+SOCKS5
+all_proxy
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Tue, 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>
+# method 2 is SOCKS5 asking for user+password
+<servercmd>
+method 2
+user aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+password bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+backendport %HTTPPORT
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+socks5
+http
+</server>
+<name>
+SOCKS5-hostname with max length credentials and max host name length
+</name>
+
+# target a port that won't work without the SOCKS magic
+<command>
+http://cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc:%HTTPPORT -x socks5h://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb@%HOSTIP:%SOCKSPORT
+</command>
+<features>
+proxy
+</features>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET / HTTP/1.1
+Host: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test80 b/tests/data/test80
index 21d9fd2ea..c6aa05b17 100644
--- a/tests/data/test80
+++ b/tests/data/test80
@@ -53,7 +53,7 @@ http-proxy
HTTP 1.0 CONNECT with proxytunnel and proxy+host Basic authentication
</name>
<command>
-http://test.%TESTNUMBER:%HTTPPORT/we/want/that/page/%TESTNUMBER -p --proxy1.0 %HOSTIP:%PROXYPORT --user iam:myself --proxy-user youare:yourself
+http://test.%TESTNUMBER:%HTTPPORT/we/want/that/page/%TESTNUMBER -p --proxy1.0 %HOSTIP:%PROXYPORT --user iam:myself --proxy-user youare:yourself -A ""
</command>
<features>
proxy
@@ -67,7 +67,6 @@ proxy
CONNECT test.%TESTNUMBER:%HTTPPORT HTTP/1.0
Host: test.%TESTNUMBER:%HTTPPORT
Proxy-Authorization: Basic eW91YXJlOnlvdXJzZWxm
-User-Agent: curl/%VERSION
Proxy-Connection: Keep-Alive
</proxy>
@@ -75,7 +74,6 @@ Proxy-Connection: Keep-Alive
GET /we/want/that/page/%TESTNUMBER HTTP/1.1
Host: test.%TESTNUMBER:%HTTPPORT
Authorization: Basic aWFtOm15c2VsZg==
-User-Agent: curl/%VERSION
Accept: */*
</protocol>
diff --git a/tests/data/test971 b/tests/data/test971
index 19260dfdf..6c6b95058 100644
--- a/tests/data/test971
+++ b/tests/data/test971
@@ -18,7 +18,7 @@ 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
+%SRCDIR/test971.pl %SRCDIR/../docs/options-in-versions %SRCDIR/../docs/cmdline-opts
</command>
</client>
diff --git a/tests/data/test992 b/tests/data/test992
new file mode 100644
index 000000000..dad0aa51a
--- /dev/null
+++ b/tests/data/test992
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+SASL
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+AUTH OAUTHBEARER XOAUTH2
+REPLY AUTH 334 XOAUTH2 supported
+REPLY dXNlcj11c2VyAWF1dGg9QmVhcmVyIG1GXzkuQjVmLTQuMUpxTQEB 235 Authenticated
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<name>
+SASL verify default mechanisms are reset by login options
+</name>
+<stdin>
+mail body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -u user --oauth2-bearer mF_9.B5f-4.1JqM --login-options "AUTH=XOAUTH2" -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO %TESTNUMBER
+AUTH XOAUTH2
+dXNlcj11c2VyAWF1dGg9QmVhcmVyIG1GXzkuQjVmLTQuMUpxTQEB
+MAIL FROM:<sender@example.com>
+RCPT TO:<recipient@example.com>
+DATA
+QUIT
+</protocol>
+<upload>
+mail body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/disable-scan.pl b/tests/disable-scan.pl
deleted file mode 100755
index 99f5436af..000000000
--- a/tests/disable-scan.pl
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-#
-
-use strict;
-use warnings;
-
-# the DISABLE options that can be set by configure
-my %disable;
-# the DISABLE options that are used in C files
-my %file;
-# the DISABLE options that are documented
-my %docs;
-
-# we may get the dir root pointed out
-my $root=$ARGV[0] || ".";
-my $DOCS="CURL-DISABLE.md";
-
-sub scanconf {
- my ($f)=@_;
- open S, "<$f";
- while(<S>) {
- if(/(CURL_DISABLE_[A-Z_]+)/g) {
- my ($sym)=($1);
- $disable{$sym} = 1;
- }
- }
- close S;
-}
-
-sub scan_configure {
- opendir(my $m, "$root/m4") || die "Can't opendir $root/m4: $!";
- my @m4 = grep { /\.m4$/ } readdir($m);
- closedir $m;
- scanconf("$root/configure.ac");
- # scan all m4 files too
- for my $e (@m4) {
- scanconf("$root/m4/$e");
- }
-}
-
-sub scan_file {
- my ($source)=@_;
- open F, "<$source";
- while(<F>) {
- while(s/(CURL_DISABLE_[A-Z_]+)//) {
- my ($sym)=($1);
- $file{$sym} = $source;
- }
- }
- close F;
-}
-
-sub scan_dir {
- my ($dir)=@_;
- opendir(my $dh, $dir) || die "Can't opendir $dir: $!";
- my @cfiles = grep { /\.[ch]\z/ && -f "$dir/$_" } readdir($dh);
- closedir $dh;
- for my $f (sort @cfiles) {
- scan_file("$dir/$f");
- }
-}
-
-sub scan_sources {
- scan_dir("$root/src");
- scan_dir("$root/lib");
- scan_dir("$root/lib/vtls");
- scan_dir("$root/lib/vauth");
-}
-
-sub scan_docs {
- open F, "<$root/docs/$DOCS";
- my $line = 0;
- while(<F>) {
- $line++;
- if(/^## `(CURL_DISABLE_[A-Z_]+)/g) {
- my ($sym)=($1);
- $docs{$sym} = $line;
- }
- }
- close F;
-}
-
-scan_configure();
-scan_sources();
-scan_docs();
-
-
-my $error = 0;
-# Check the configure symbols for use in code
-for my $s (sort keys %disable) {
- if(!$file{$s}) {
- printf "Present in configure.ac, not used by code: %s\n", $s;
- $error++;
- }
- if(!$docs{$s}) {
- printf "Present in configure.ac, not documented in $DOCS: %s\n", $s;
- $error++;
- }
-}
-
-# Check the code symbols for use in configure
-for my $s (sort keys %file) {
- if(!$disable{$s}) {
- printf "Not set by configure: %s (%s)\n", $s, $file{$s};
- $error++;
- }
- if(!$docs{$s}) {
- printf "Used in code, not documented in $DOCS: %s\n", $s;
- $error++;
- }
-}
-
-# Check the documented symbols
-for my $s (sort keys %docs) {
- if(!$disable{$s}) {
- printf "Documented but not in configure: %s\n", $s;
- $error++;
- }
- if(!$file{$s}) {
- printf "Documented, but not used by code: %s\n", $s;
- $error++;
- }
-}
-
-exit $error;
diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl
index d0be36f15..e250aa1cb 100755
--- a/tests/ftpserver.pl
+++ b/tests/ftpserver.pl
@@ -412,7 +412,7 @@ sub sysread_or_die {
sub startsf {
my @mainsockfcmd = ("./server/sockfilt".exe_ext('SRV'),
"--ipv$ipvnum",
- "--port", $port,
+ "--port", $port,
"--pidfile", $mainsockf_pidfile,
"--portfile", $portfile,
"--logfile", $mainsockf_logfile);
@@ -2258,6 +2258,7 @@ sub SIZE_ftp {
my $size = $data[0];
if($size) {
+ $size += 0; # make it a number
if($size > -1) {
sendcontrol "213 $size\r\n";
}
diff --git a/tests/http/clients/.gitignore b/tests/http/clients/.gitignore
index 8d885e16e..f461524b3 100644
--- a/tests/http/clients/.gitignore
+++ b/tests/http/clients/.gitignore
@@ -8,4 +8,4 @@ ws-data
ws-pingpong
h2-upgrade-extreme
tls-session-reuse
-h2-pausing \ No newline at end of file
+h2-pausing
diff --git a/tests/http/clients/h2-download.c b/tests/http/clients/h2-download.c
index 24ccedbdd..e6f001c7c 100644
--- a/tests/http/clients/h2-download.c
+++ b/tests/http/clients/h2-download.c
@@ -56,10 +56,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -76,6 +73,8 @@ int my_trace(CURL *handle, curl_infotype type,
return 0;
text = "<= Recv data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
fprintf(stderr, "%s, %lu bytes (0x%lx)\n",
@@ -113,11 +112,11 @@ static size_t my_write_cb(char *buf, size_t nitems, size_t buflen,
void *userdata)
{
struct transfer *t = userdata;
- ssize_t nwritten;
+ size_t nwritten;
if(!t->resumed &&
t->recv_size < t->pause_at &&
- ((curl_off_t)(t->recv_size + (nitems * buflen)) >= t->pause_at)) {
+ ((t->recv_size + (curl_off_t)(nitems * buflen)) >= t->pause_at)) {
fprintf(stderr, "[t-%d] PAUSE\n", t->idx);
t->paused = 1;
return CURL_WRITEFUNC_PAUSE;
@@ -132,11 +131,11 @@ static size_t my_write_cb(char *buf, size_t nitems, size_t buflen,
}
nwritten = fwrite(buf, nitems, buflen, t->out);
- if(nwritten < 0) {
+ if(nwritten < buflen) {
fprintf(stderr, "[t-%d] write failure\n", t->idx);
return 0;
}
- t->recv_size += nwritten;
+ t->recv_size += (curl_off_t)nwritten;
return (size_t)nwritten;
}
@@ -172,7 +171,7 @@ static void usage(const char *msg)
" download a url with following options:\n"
" -m number max parallel downloads\n"
" -n number total downloads\n"
- " -p number pause transfer after `number` response bytes\n"
+ " -P number pause transfer after `number` response bytes\n"
);
}
@@ -186,7 +185,7 @@ int main(int argc, char *argv[])
const char *url;
size_t i, n, max_parallel = 1;
size_t active_transfers;
- long pause_offset = 0;
+ size_t pause_offset = 0;
int abort_paused = 0;
struct transfer *t;
int ch;
@@ -196,7 +195,6 @@ int main(int argc, char *argv[])
case 'h':
usage(NULL);
return 2;
- break;
case 'a':
abort_paused = 1;
break;
@@ -207,7 +205,7 @@ int main(int argc, char *argv[])
transfer_count = (size_t)strtol(optarg, NULL, 10);
break;
case 'P':
- pause_offset = strtol(optarg, NULL, 10);
+ pause_offset = (size_t)strtol(optarg, NULL, 10);
break;
default:
usage("invalid option");
@@ -236,7 +234,7 @@ int main(int argc, char *argv[])
for(i = 0; i < transfer_count; ++i) {
t = &transfers[i];
t->idx = (int)i;
- t->pause_at = (curl_off_t)pause_offset * i;
+ t->pause_at = (curl_off_t)(pause_offset * i);
}
n = (max_parallel < transfer_count)? max_parallel : transfer_count;
diff --git a/tests/http/clients/h2-serverpush.c b/tests/http/clients/h2-serverpush.c
index 742a67e59..13f804aa2 100644
--- a/tests/http/clients/h2-serverpush.c
+++ b/tests/http/clients/h2-serverpush.c
@@ -102,10 +102,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -124,6 +121,8 @@ int my_trace(CURL *handle, curl_infotype type,
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
dump(text, (unsigned char *)data, size, 1);
diff --git a/tests/http/requirements.txt b/tests/http/requirements.txt
index ff49a9629..fb0e01383 100644
--- a/tests/http/requirements.txt
+++ b/tests/http/requirements.txt
@@ -27,3 +27,4 @@ pytest
cryptography
multipart
websockets
+psutil
diff --git a/tests/http/scorecard.py b/tests/http/scorecard.py
index ae466129c..446a1bc5c 100644
--- a/tests/http/scorecard.py
+++ b/tests/http/scorecard.py
@@ -33,7 +33,7 @@ import sys
from statistics import mean
from typing import Dict, Any, Optional, List
-from testenv import Env, Httpd, Nghttpx, CurlClient, Caddy, ExecResult, NghttpxFwd
+from testenv import Env, Httpd, Nghttpx, CurlClient, Caddy, ExecResult, NghttpxQuic, RunProfile
log = logging.getLogger(__name__)
@@ -122,57 +122,65 @@ class ScoreCard:
count = 1
samples = []
errors = []
+ profiles = []
self.info(f'single...')
for i in range(sample_size):
curl = CurlClient(env=self.env, silent=self._silent_curl)
r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
- with_headers=False)
+ with_headers=False, with_profile=True)
err = self._check_downloads(r, count)
if err:
errors.append(err)
else:
total_size = sum([s['size_download'] for s in r.stats])
samples.append(total_size / r.duration.total_seconds())
+ profiles.append(r.profile)
return {
'count': count,
'samples': sample_size,
'speed': mean(samples) if len(samples) else -1,
- 'errors': errors
+ 'errors': errors,
+ 'stats': RunProfile.AverageStats(profiles),
}
def transfer_serial(self, url: str, proto: str, count: int):
sample_size = 1
samples = []
errors = []
+ profiles = []
url = f'{url}?[0-{count - 1}]'
self.info(f'serial...')
for i in range(sample_size):
curl = CurlClient(env=self.env, silent=self._silent_curl)
r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
- with_headers=False)
+ with_headers=False, with_profile=True)
err = self._check_downloads(r, count)
if err:
errors.append(err)
else:
total_size = sum([s['size_download'] for s in r.stats])
samples.append(total_size / r.duration.total_seconds())
+ profiles.append(r.profile)
return {
'count': count,
'samples': sample_size,
'speed': mean(samples) if len(samples) else -1,
- 'errors': errors
+ 'errors': errors,
+ 'stats': RunProfile.AverageStats(profiles),
}
def transfer_parallel(self, url: str, proto: str, count: int):
sample_size = 1
samples = []
errors = []
+ profiles = []
url = f'{url}?[0-{count - 1}]'
self.info(f'parallel...')
for i in range(sample_size):
curl = CurlClient(env=self.env, silent=self._silent_curl)
r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
with_headers=False,
+ with_profile=True,
extra_args=['--parallel',
'--parallel-max', str(count)])
err = self._check_downloads(r, count)
@@ -181,21 +189,25 @@ class ScoreCard:
else:
total_size = sum([s['size_download'] for s in r.stats])
samples.append(total_size / r.duration.total_seconds())
+ profiles.append(r.profile)
return {
'count': count,
'samples': sample_size,
'speed': mean(samples) if len(samples) else -1,
- 'errors': errors
+ 'errors': errors,
+ 'stats': RunProfile.AverageStats(profiles),
}
def download_url(self, label: str, url: str, proto: str, count: int):
self.info(f' {count}x{label}: ')
props = {
'single': self.transfer_single(url=url, proto=proto, count=10),
- 'serial': self.transfer_serial(url=url, proto=proto, count=count),
- 'parallel': self.transfer_parallel(url=url, proto=proto,
- count=count),
}
+ if count > 1:
+ props['serial'] = self.transfer_serial(url=url, proto=proto,
+ count=count)
+ props['parallel'] = self.transfer_parallel(url=url, proto=proto,
+ count=count)
self.info(f'ok.\n')
return props
@@ -216,8 +228,7 @@ class ScoreCard:
'description': descr,
}
for fsize in fsizes:
- label = f'{int(fsize / 1024)}KB' if fsize < 1024*1024 else \
- f'{int(fsize / (1024 * 1024))}MB'
+ label = self.fmt_size(fsize)
fname = f'score{label}.data'
self._make_docs_file(docs_dir=self.httpd.docs_dir,
fname=fname, fsize=fsize)
@@ -234,8 +245,7 @@ class ScoreCard:
'description': descr,
}
for fsize in fsizes:
- label = f'{int(fsize / 1024)}KB' if fsize < 1024*1024 else \
- f'{int(fsize / (1024 * 1024))}MB'
+ label = self.fmt_size(fsize)
fname = f'score{label}.data'
self._make_docs_file(docs_dir=self.caddy.docs_dir,
fname=fname, fsize=fsize)
@@ -250,6 +260,7 @@ class ScoreCard:
sample_size = 1
samples = []
errors = []
+ profiles = []
url = f'{url}?[0-{count - 1}]'
extra_args = ['--parallel', '--parallel-max', str(max_parallel)] \
if max_parallel > 1 else []
@@ -257,7 +268,7 @@ class ScoreCard:
for i in range(sample_size):
curl = CurlClient(env=self.env, silent=self._silent_curl)
r = curl.http_download(urls=[url], alpn_proto=proto, no_save=True,
- with_headers=False,
+ with_headers=False, with_profile=True,
extra_args=extra_args)
err = self._check_downloads(r, count)
if err:
@@ -265,30 +276,32 @@ class ScoreCard:
else:
for _ in r.stats:
samples.append(count / r.duration.total_seconds())
+ profiles.append(r.profile)
return {
'count': count,
'samples': sample_size,
'speed': mean(samples) if len(samples) else -1,
- 'errors': errors
+ 'errors': errors,
+ 'stats': RunProfile.AverageStats(profiles),
}
def requests_url(self, url: str, proto: str, count: int):
self.info(f' {url}: ')
props = {
- 'serial': self.do_requests(url=url, proto=proto, count=count),
- 'par-6': self.do_requests(url=url, proto=proto, count=count,
- max_parallel=6),
- 'par-25': self.do_requests(url=url, proto=proto, count=count,
- max_parallel=25),
- 'par-50': self.do_requests(url=url, proto=proto, count=count,
- max_parallel=50),
- 'par-100': self.do_requests(url=url, proto=proto, count=count,
- max_parallel=100),
+ '1': self.do_requests(url=url, proto=proto, count=count),
+ '6': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=6),
+ '25': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=25),
+ '50': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=50),
+ '100': self.do_requests(url=url, proto=proto, count=count,
+ max_parallel=100),
}
self.info(f'ok.\n')
return props
- def requests(self, proto: str) -> Dict[str, Any]:
+ def requests(self, proto: str, req_count) -> Dict[str, Any]:
scores = {}
if self.httpd:
if proto == 'h3':
@@ -305,7 +318,8 @@ class ScoreCard:
url1 = f'https://{self.env.domain1}:{port}/reqs10.data'
scores[via] = {
'description': descr,
- '10KB': self.requests_url(url=url1, proto=proto, count=10000),
+ 'count': req_count,
+ '10KB': self.requests_url(url=url1, proto=proto, count=req_count),
}
if self.caddy:
port = self.caddy.port
@@ -317,7 +331,8 @@ class ScoreCard:
url1 = f'https://{self.env.domain1}:{port}/req10.data'
scores[via] = {
'description': descr,
- '10KB': self.requests_url(url=url1, proto=proto, count=5000),
+ 'count': req_count,
+ '10KB': self.requests_url(url=url1, proto=proto, count=req_count),
}
return scores
@@ -325,6 +340,7 @@ class ScoreCard:
handshakes: bool = True,
downloads: Optional[List[int]] = None,
download_count: int = 50,
+ req_count=5000,
requests: bool = True):
self.info(f"scoring {proto}\n")
p = {}
@@ -332,7 +348,7 @@ class ScoreCard:
p['name'] = 'h3'
if not self.env.have_h3_curl():
raise ScoreCardException('curl does not support HTTP/3')
- for lib in ['ngtcp2', 'quiche', 'msh3']:
+ for lib in ['ngtcp2', 'quiche', 'msh3', 'nghttp3']:
if self.env.curl_uses_lib(lib):
p['implementation'] = lib
break
@@ -368,15 +384,22 @@ class ScoreCard:
count=download_count,
fsizes=downloads)
if requests:
- score['requests'] = self.requests(proto=proto)
+ score['requests'] = self.requests(proto=proto, req_count=req_count)
self.info("\n")
return score
def fmt_ms(self, tval):
return f'{int(tval*1000)} ms' if tval >= 0 else '--'
- def fmt_mb(self, val):
- return f'{val/(1024*1024):0.000f} MB' if val >= 0 else '--'
+ def fmt_size(self, val):
+ if val >= (1024*1024*1024):
+ return f'{val / (1024*1024*1024):0.000f}GB'
+ elif val >= (1024 * 1024):
+ return f'{val / (1024*1024):0.000f}MB'
+ elif val >= 1024:
+ return f'{val / 1024:0.000f}KB'
+ else:
+ return f'{val:0.000f}B'
def fmt_mbs(self, val):
return f'{val/(1024*1024):0.000f} MB/s' if val >= 0 else '--'
@@ -398,46 +421,93 @@ class ScoreCard:
f'{"/".join(val["ipv4-errors"] + val["ipv6-errors"]):<20}'
)
if 'downloads' in score:
+ # get the key names of all sizes and measurements made
+ sizes = []
+ measures = []
+ m_names = {}
+ mcol_width = 12
+ mcol_sw = 17
+ for server, server_score in score['downloads'].items():
+ for sskey, ssval in server_score.items():
+ if isinstance(ssval, str):
+ continue
+ if sskey not in sizes:
+ sizes.append(sskey)
+ for mkey, mval in server_score[sskey].items():
+ if mkey not in measures:
+ measures.append(mkey)
+ m_names[mkey] = f'{mkey}({mval["count"]}x)'
+
print('Downloads')
- print(f' {"Server":<8} {"Size":>8} {"Single":>12} {"Serial":>12}'
- f' {"Parallel":>12} {"Errors":<20}')
- skeys = {}
- for dkey, dval in score["downloads"].items():
- for k in dval.keys():
- skeys[k] = True
- for skey in skeys:
- for dkey, dval in score["downloads"].items():
- if skey in dval:
- sval = dval[skey]
- if isinstance(sval, str):
- continue
- errors = []
- for key, val in sval.items():
- if 'errors' in val:
- errors.extend(val['errors'])
- print(f' {dkey:<8} {skey:>8} '
- f'{self.fmt_mbs(sval["single"]["speed"]):>12} '
- f'{self.fmt_mbs(sval["serial"]["speed"]):>12} '
- f'{self.fmt_mbs(sval["parallel"]["speed"]):>12} '
- f' {"/".join(errors):<20}')
+ print(f' {"Server":<8} {"Size":>8}', end='')
+ for m in measures: print(f' {m_names[m]:>{mcol_width}} {"[cpu/rss]":<{mcol_sw}}', end='')
+ print(f' {"Errors":^20}')
+
+ for server in score['downloads']:
+ for size in sizes:
+ size_score = score['downloads'][server][size]
+ print(f' {server:<8} {size:>8}', end='')
+ errors = []
+ for key, val in size_score.items():
+ if 'errors' in val:
+ errors.extend(val['errors'])
+ for m in measures:
+ if m in size_score:
+ print(f' {self.fmt_mbs(size_score[m]["speed"]):>{mcol_width}}', end='')
+ s = f'[{size_score[m]["stats"]["cpu"]:>.1f}%'\
+ f'/{self.fmt_size(size_score[m]["stats"]["rss"])}]'
+ print(f' {s:<{mcol_sw}}', end='')
+ else:
+ print(' '*mcol_width, end='')
+ if len(errors):
+ print(f' {"/".join(errors):<20}')
+ else:
+ print(f' {"-":^20}')
+
if 'requests' in score:
- print('Requests, max in parallel')
- print(f' {"Server":<8} {"Size":>8} '
- f'{"1 ":>12} {"6 ":>12} {"25 ":>12} '
- f'{"50 ":>12} {"100 ":>12} {"Errors":<20}')
- for dkey, dval in score["requests"].items():
- for skey, sval in dval.items():
- if isinstance(sval, str):
+ sizes = []
+ measures = []
+ m_names = {}
+ mcol_width = 9
+ mcol_sw = 13
+ for server in score['requests']:
+ server_score = score['requests'][server]
+ for sskey, ssval in server_score.items():
+ if isinstance(ssval, str) or isinstance(ssval, int):
continue
+ if sskey not in sizes:
+ sizes.append(sskey)
+ for mkey, mval in server_score[sskey].items():
+ if mkey not in measures:
+ measures.append(mkey)
+ m_names[mkey] = f'{mkey}'
+
+ print('Requests, max in parallel')
+ print(f' {"Server":<8} {"Size":>6} {"Reqs":>6}', end='')
+ for m in measures: print(f' {m_names[m]:>{mcol_width}} {"[cpu/rss]":<{mcol_sw}}', end='')
+ print(f' {"Errors":^10}')
+
+ for server in score['requests']:
+ for size in sizes:
+ size_score = score['requests'][server][size]
+ count = score['requests'][server]['count']
+ print(f' {server:<8} {size:>6} {count:>6}', end='')
errors = []
- for key, val in sval.items():
+ for key, val in size_score.items():
if 'errors' in val:
errors.extend(val['errors'])
- line = f' {dkey:<8} {skey:>8} '
- for k in sval.keys():
- line += f'{self.fmt_reqs(sval[k]["speed"]):>12} '
- line += f' {"/".join(errors):<20}'
- print(line)
+ for m in measures:
+ if m in size_score:
+ print(f' {self.fmt_reqs(size_score[m]["speed"]):>{mcol_width}}', end='')
+ s = f'[{size_score[m]["stats"]["cpu"]:>.1f}%'\
+ f'/{self.fmt_size(size_score[m]["stats"]["rss"])}]'
+ print(f' {s:<{mcol_sw}}', end='')
+ else:
+ print(' '*mcol_width, end='')
+ if len(errors):
+ print(f' {"/".join(errors):<10}')
+ else:
+ print(f' {"-":^10}')
def parse_size(s):
@@ -445,7 +515,9 @@ def parse_size(s):
if m is None:
raise Exception(f'unrecognized size: {s}')
size = int(m.group(1))
- if m.group(2).lower() == 'kb':
+ if not m.group(2):
+ pass
+ elif m.group(2).lower() == 'kb':
size *= 1024
elif m.group(2).lower() == 'mb':
size *= 1024 * 1024
@@ -466,13 +538,15 @@ def main():
parser.add_argument("-H", "--handshakes", action='store_true',
default=False, help="evaluate handshakes only")
parser.add_argument("-d", "--downloads", action='store_true',
- default=False, help="evaluate downloads only")
+ default=False, help="evaluate downloads")
parser.add_argument("--download", action='append', type=str,
default=None, help="evaluate download size")
parser.add_argument("--download-count", action='store', type=int,
default=50, help="perform that many downloads")
parser.add_argument("-r", "--requests", action='store_true',
- default=False, help="evaluate requests only")
+ default=False, help="evaluate requests")
+ parser.add_argument("--request-count", action='store', type=int,
+ default=5000, help="perform that many requests")
parser.add_argument("--httpd", action='store_true', default=False,
help="evaluate httpd server only")
parser.add_argument("--caddy", action='store_true', default=False,
@@ -491,29 +565,23 @@ def main():
protocol = args.protocol
handshakes = True
- downloads = [1024*1024, 10*1024*1024, 100*1024*1024]
+ downloads = [1024 * 1024, 10 * 1024 * 1024, 100 * 1024 * 1024]
+ if args.download is not None:
+ downloads = []
+ for x in args.download:
+ downloads.extend([parse_size(s) for s in x.split(',')])
requests = True
+ if args.downloads or args.requests or args.handshakes:
+ handshakes = args.handshakes
+ if not args.downloads:
+ downloads = None
+ requests = args.requests
+
test_httpd = protocol != 'h3'
test_caddy = True
- if args.handshakes:
- downloads = None
- requests = False
- if args.downloads:
- handshakes = False
- requests = False
- if args.download:
- downloads = sorted([parse_size(x) for x in args.download])
- handshakes = False
- requests = False
- if args.requests:
- handshakes = False
- downloads = None
- if args.caddy:
- test_caddy = True
- test_httpd = False
- if args.httpd:
- test_caddy = False
- test_httpd = True
+ if args.caddy or args.httpd:
+ test_caddy = args.caddy
+ test_httpd = args.httpd
rv = 0
env = Env()
@@ -530,7 +598,7 @@ def main():
httpd.clear_logs()
assert httpd.start()
if 'h3' == protocol:
- nghttpx = NghttpxFwd(env=env)
+ nghttpx = NghttpxQuic(env=env)
nghttpx.clear_logs()
assert nghttpx.start()
if test_caddy and env.caddy:
@@ -544,6 +612,7 @@ def main():
handshakes=handshakes,
downloads=downloads,
download_count=args.download_count,
+ req_count=args.request_count,
requests=requests)
if args.json:
print(json.JSONEncoder(indent=2).encode(score))
diff --git a/tests/http/test_01_basic.py b/tests/http/test_01_basic.py
index 7c1792d37..3902b75b7 100644
--- a/tests/http/test_01_basic.py
+++ b/tests/http/test_01_basic.py
@@ -84,3 +84,18 @@ class TestBasic:
r = curl.http_get(url=url, extra_args=['--http3-only'])
r.check_response(http_status=200, protocol='HTTP/3')
assert r.json['server'] == env.domain1
+
+ # simple download, check connect/handshake timings
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_01_06_timings(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/data.json'
+ r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True)
+ r.check_stats(http_status=200, count=1)
+ assert r.stats[0]['time_connect'] > 0, f'{r.stats[0]}'
+ assert r.stats[0]['time_appconnect'] > 0, f'{r.stats[0]}'
+
+
diff --git a/tests/http/test_02_download.py b/tests/http/test_02_download.py
index 22fa32cd2..4db9c9d36 100644
--- a/tests/http/test_02_download.py
+++ b/tests/http/test_02_download.py
@@ -108,16 +108,17 @@ class TestDownload:
# download 500 files sequential
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
- def test_02_05_download_500_sequential(self, env: Env,
- httpd, nghttpx, repeat, proto):
+ def test_02_05_download_many_sequential(self, env: Env,
+ httpd, nghttpx, repeat, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
if proto == 'h3' and env.curl_uses_lib('msh3'):
pytest.skip("msh3 shaky here")
+ count = 200
curl = CurlClient(env=env)
- urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-499]'
+ urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[0-{count-1}]'
r = curl.http_download(urls=[urln], alpn_proto=proto)
- r.check_response(http_status=200, count=500)
+ r.check_response(http_status=200, count=count)
if proto == 'http/1.1':
# http/1.1 parallel transfers will open multiple connections
assert r.total_connects > 1, r.dump_logs()
@@ -127,11 +128,11 @@ class TestDownload:
# download 500 files parallel
@pytest.mark.parametrize("proto", ['h2', 'h3'])
- def test_02_06_download_500_parallel(self, env: Env,
- httpd, nghttpx, repeat, proto):
+ def test_02_06_download_many_parallel(self, env: Env,
+ httpd, nghttpx, repeat, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
- count = 500
+ count = 200
max_parallel = 50
curl = CurlClient(env=env)
urln = f'https://{env.authority_for(env.domain1, proto)}/data.json?[000-{count-1}]'
@@ -207,7 +208,7 @@ class TestDownload:
httpd, nghttpx, repeat, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
- count = 20
+ count = 10
urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]'
curl = CurlClient(env=env)
r = curl.http_download(urls=[urln], alpn_proto=proto)
@@ -222,7 +223,7 @@ class TestDownload:
pytest.skip("h3 not supported")
if proto == 'h3' and env.curl_uses_lib('msh3'):
pytest.skip("msh3 stalls here")
- count = 20
+ count = 10
urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]'
curl = CurlClient(env=env)
r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
@@ -235,7 +236,7 @@ class TestDownload:
httpd, nghttpx, repeat, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
- count = 100
+ count = 50
urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]'
curl = CurlClient(env=env)
r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
@@ -248,7 +249,7 @@ class TestDownload:
httpd, nghttpx, repeat, proto):
if proto == 'h3' and not env.have_h3():
pytest.skip("h3 not supported")
- count = 100
+ count = 50
urln = f'http://{env.domain1}:{env.http_port}/data-10m?[0-{count-1}]'
curl = CurlClient(env=env)
r = curl.http_download(urls=[urln], alpn_proto=proto, extra_args=[
@@ -385,13 +386,10 @@ class TestDownload:
r.check_exit_code(0)
# test on paused transfers, based on issue #11982
- @pytest.mark.parametrize("proto", ['h2', 'h3'])
- def test_02_27_paused_no_cl(self, env: Env, httpd, nghttpx, proto, repeat):
- if proto == 'h3' and not env.have_h3():
- pytest.skip("h3 not supported")
+ def test_02_27_paused_no_cl(self, env: Env, httpd, nghttpx, repeat):
+ proto = 'h2'
url = f'https://{env.authority_for(env.domain1, proto)}' \
- f'/tweak?'\
- '&chunks=2&chunk_size=16000'
+ '/tweak?&chunks=2&chunk_size=16000'
client = LocalClient(env=env, name='h2-pausing')
r = client.run(args=[url])
r.check_exit_code(0)
diff --git a/tests/http/test_07_upload.py b/tests/http/test_07_upload.py
index 5aee3ea26..94534ffb1 100644
--- a/tests/http/test_07_upload.py
+++ b/tests/http/test_07_upload.py
@@ -28,6 +28,7 @@ import difflib
import filecmp
import logging
import os
+import time
import pytest
from testenv import Env, CurlClient
@@ -124,7 +125,7 @@ class TestUpload:
if proto == 'h3' and env.curl_uses_lib('msh3'):
pytest.skip("msh3 stalls here")
fdata = os.path.join(env.gen_dir, 'data-100k')
- count = 50
+ count = 20
curl = CurlClient(env=env)
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto)
@@ -161,7 +162,7 @@ class TestUpload:
if proto == 'h3' and env.curl_uses_lib('msh3'):
pytest.skip("msh3 stalls here")
# limit since we use a separate connection in h1
- count = 50
+ count = 20
data = '0123456789'
curl = CurlClient(env=env)
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
@@ -181,7 +182,7 @@ class TestUpload:
pytest.skip("msh3 stalls here")
fdata = os.path.join(env.gen_dir, 'data-100k')
# limit since we use a separate connection in h1
- count = 50
+ count = 20
curl = CurlClient(env=env)
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-{count-1}]'
r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto,
@@ -189,6 +190,23 @@ class TestUpload:
r.check_response(count=count, http_status=200)
self.check_download(count, fdata, curl)
+ # upload large data parallel to a URL that denies uploads
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_07_22_upload_parallel_fail(self, env: Env, httpd, nghttpx, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ fdata = os.path.join(env.gen_dir, 'data-10m')
+ count = 100
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}'\
+ f'/curltest/tweak?status=400&delay=5ms&chunks=1&body_error=reset&id=[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto,
+ extra_args=['--parallel'])
+ exp_exit = 92 if proto == 'h2' else 95
+ r.check_stats(count=count, exitcode=exp_exit)
+
# PUT 100k
@pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
def test_07_30_put_100k(self, env: Env, httpd, nghttpx, repeat, proto):
@@ -219,7 +237,7 @@ class TestUpload:
fdata = os.path.join(env.gen_dir, 'data-10m')
count = 1
curl = CurlClient(env=env)
- url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]&chunk_delay=10ms'
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]&chunk_delay=2ms'
r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto,
extra_args=['--parallel'])
r.check_stats(count=count, http_status=200, exitcode=0)
@@ -444,3 +462,42 @@ class TestUpload:
tofile=dfile,
n=1))
assert False, f'download {dfile} differs:\n{diff}'
+
+ # speed limited on put handler
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_50_put_speed_limit(self, env: Env, httpd, nghttpx, proto, repeat):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 1
+ fdata = os.path.join(env.gen_dir, 'data-100k')
+ up_len = 100 * 1024
+ speed_limit = 20 * 1024
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-0]'
+ r = curl.http_put(urls=[url], fdata=fdata, alpn_proto=proto,
+ with_headers=True, extra_args=[
+ '--limit-rate', f'{speed_limit}'
+ ])
+ r.check_response(count=count, http_status=200)
+ assert r.responses[0]['header']['received-length'] == f'{up_len}', f'{r.responses[0]}'
+ up_speed = r.stats[0]['speed_upload']
+ assert (speed_limit * 0.5) <= up_speed <= (speed_limit * 1.5), f'{r.stats[0]}'
+
+ # speed limited on echo handler
+ @pytest.mark.parametrize("proto", ['http/1.1', 'h2', 'h3'])
+ def test_07_51_echo_speed_limit(self, env: Env, httpd, nghttpx, proto, repeat):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ count = 1
+ fdata = os.path.join(env.gen_dir, 'data-100k')
+ speed_limit = 20 * 1024
+ curl = CurlClient(env=env)
+ url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]'
+ r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto,
+ with_headers=True, extra_args=[
+ '--limit-rate', f'{speed_limit}'
+ ])
+ r.check_response(count=count, http_status=200)
+ up_speed = r.stats[0]['speed_upload']
+ assert (speed_limit * 0.5) <= up_speed <= (speed_limit * 1.5), f'{r.stats[0]}'
+
diff --git a/tests/http/test_08_caddy.py b/tests/http/test_08_caddy.py
index c95d8457a..c35bd27b7 100644
--- a/tests/http/test_08_caddy.py
+++ b/tests/http/test_08_caddy.py
@@ -163,3 +163,20 @@ class TestCaddy:
assert r.total_connects > 1, r.dump_logs()
else:
assert r.total_connects == 1, r.dump_logs()
+
+ # upload data parallel, check that they were echoed
+ @pytest.mark.skipif(condition=Env().ci_run, reason="not suitable for CI runs")
+ @pytest.mark.parametrize("proto", ['h2', 'h3'])
+ def test_08_06_upload_parallel(self, env: Env, caddy, repeat, proto):
+ if proto == 'h3' and not env.have_h3():
+ pytest.skip("h3 not supported")
+ if proto == 'h3' and env.curl_uses_lib('msh3'):
+ pytest.skip("msh3 stalls here")
+ # limit since we use a separate connection in h1
+ count = 20
+ data = '0123456789'
+ curl = CurlClient(env=env)
+ url = f'https://{env.domain1}:{caddy.port}/data10.data?[0-{count-1}]'
+ r = curl.http_upload(urls=[url], data=data, alpn_proto=proto,
+ extra_args=['--parallel'])
+ r.check_stats(count=count, http_status=200, exitcode=0)
diff --git a/tests/http/test_10_proxy.py b/tests/http/test_10_proxy.py
index df234013c..0e4060b67 100644
--- a/tests/http/test_10_proxy.py
+++ b/tests/http/test_10_proxy.py
@@ -247,3 +247,105 @@ class TestProxy:
assert r.total_connects == 2
else:
assert r.total_connects == 2
+
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ def test_10_10_reuse_proxy(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
+ # url twice via https: proxy separated with '--next', will reuse
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/data.json'
+ proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=proxy_args)
+ r1.check_response(count=1, http_status=200)
+ assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ # get the args, duplicate separated with '--next'
+ x2_args = r1.args[1:]
+ x2_args.append('--next')
+ x2_args.extend(proxy_args)
+ r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=x2_args)
+ r2.check_response(count=2, http_status=200)
+ assert r2.total_connects == 1
+
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ @pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
+ def test_10_11_noreuse_proxy_https(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
+ # different --proxy-tls13-ciphers, no reuse of connection for https:
+ curl = CurlClient(env=env)
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ url = f'https://localhost:{env.https_port}/data.json'
+ proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=proxy_args)
+ r1.check_response(count=1, http_status=200)
+ assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ # get the args, duplicate separated with '--next'
+ x2_args = r1.args[1:]
+ x2_args.append('--next')
+ x2_args.extend(proxy_args)
+ x2_args.extend(['--proxy-tls13-ciphers', 'TLS_AES_128_GCM_SHA256'])
+ r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=x2_args)
+ r2.check_response(count=2, http_status=200)
+ assert r2.total_connects == 2
+
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ @pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
+ def test_10_12_noreuse_proxy_http(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
+ # different --proxy-tls13-ciphers, no reuse of connection for http:
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url = f'http://localhost:{env.http_port}/data.json'
+ proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=proxy_args)
+ r1.check_response(count=1, http_status=200)
+ assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ # get the args, duplicate separated with '--next'
+ x2_args = r1.args[1:]
+ x2_args.append('--next')
+ x2_args.extend(proxy_args)
+ x2_args.extend(['--proxy-tls13-ciphers', 'TLS_AES_128_GCM_SHA256'])
+ r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=x2_args)
+ r2.check_response(count=2, http_status=200)
+ assert r2.total_connects == 2
+
+ @pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
+ @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
+ @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
+ @pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
+ def test_10_13_noreuse_https(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
+ # different --tls13-ciphers on https: same proxy config
+ if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
+ pytest.skip('only supported with nghttp2')
+ curl = CurlClient(env=env)
+ url = f'https://localhost:{env.https_port}/data.json'
+ proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
+ r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=proxy_args)
+ r1.check_response(count=1, http_status=200)
+ assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
+ if tunnel == 'h2' else 'HTTP/1.1'
+ # get the args, duplicate separated with '--next'
+ x2_args = r1.args[1:]
+ x2_args.append('--next')
+ x2_args.extend(proxy_args)
+ x2_args.extend(['--tls13-ciphers', 'TLS_AES_128_GCM_SHA256'])
+ r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
+ extra_args=x2_args)
+ r2.check_response(count=2, http_status=200)
+ assert r2.total_connects == 2
diff --git a/tests/http/test_14_auth.py b/tests/http/test_14_auth.py
index 0cc0f925f..6d3db5931 100644
--- a/tests/http/test_14_auth.py
+++ b/tests/http/test_14_auth.py
@@ -133,5 +133,7 @@ class TestAuth:
r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto, extra_args=[
'--basic', '--user', f'test:{password}'
])
- # request was never sent
- r.check_response(exitcode=55, http_status=0)
+ # Depending on protocl, we might have an error sending or
+ # the server might shutdown the connection and we see the error
+ # on receiving
+ assert r.exit_code in [55, 56], f'{self.dump_logs()}'
diff --git a/tests/http/testenv/__init__.py b/tests/http/testenv/__init__.py
index 2195634fd..c4c032028 100644
--- a/tests/http/testenv/__init__.py
+++ b/tests/http/testenv/__init__.py
@@ -32,7 +32,7 @@ from .env import Env
from .certs import TestCA, Credentials
from .caddy import Caddy
from .httpd import Httpd
-from .curl import CurlClient, ExecResult
+from .curl import CurlClient, ExecResult, RunProfile
from .client import LocalClient
from .nghttpx import Nghttpx
from .nghttpx import Nghttpx, NghttpxQuic, NghttpxFwd
diff --git a/tests/http/testenv/curl.py b/tests/http/testenv/curl.py
index 9f92f629c..45fef7fd9 100644
--- a/tests/http/testenv/curl.py
+++ b/tests/http/testenv/curl.py
@@ -27,11 +27,13 @@
import json
import logging
import os
+import psutil
import re
import shutil
import subprocess
+from statistics import mean, fmean
from datetime import timedelta, datetime
-from typing import List, Optional, Dict, Union
+from typing import List, Optional, Dict, Union, Any
from urllib.parse import urlparse
from .env import Env
@@ -40,18 +42,81 @@ from .env import Env
log = logging.getLogger(__name__)
+class RunProfile:
+
+ STAT_KEYS = ['cpu', 'rss', 'vsz']
+
+ @classmethod
+ def AverageStats(cls, profiles: List['RunProfile']):
+ avg = {}
+ stats = [p.stats for p in profiles]
+ for key in cls.STAT_KEYS:
+ avg[key] = mean([s[key] for s in stats])
+ return avg
+
+ def __init__(self, pid: int, started_at: datetime, run_dir):
+ self._pid = pid
+ self._started_at = started_at
+ self._duration = timedelta(seconds=0)
+ self._run_dir = run_dir
+ self._samples = []
+ self._psu = None
+ self._stats = None
+
+ @property
+ def duration(self) -> timedelta:
+ return self._duration
+
+ @property
+ def stats(self) -> Optional[Dict[str,Any]]:
+ return self._stats
+
+ def sample(self):
+ elapsed = datetime.now() - self._started_at
+ try:
+ if self._psu is None:
+ self._psu = psutil.Process(pid=self._pid)
+ mem = self._psu.memory_info()
+ self._samples.append({
+ 'time': elapsed,
+ 'cpu': self._psu.cpu_percent(),
+ 'vsz': mem.vms,
+ 'rss': mem.rss,
+ })
+ except psutil.NoSuchProcess:
+ pass
+
+ def finish(self):
+ self._duration = datetime.now() - self._started_at
+ if len(self._samples) > 0:
+ weights = [s['time'].total_seconds() for s in self._samples]
+ self._stats = {}
+ for key in self.STAT_KEYS:
+ self._stats[key] = fmean([s[key] for s in self._samples], weights)
+ else:
+ self._stats = None
+ self._psu = None
+
+ def __repr__(self):
+ return f'RunProfile[pid={self._pid}, '\
+ f'duration={self.duration.total_seconds():.3f}s, '\
+ f'stats={self.stats}]'
+
+
class ExecResult:
def __init__(self, args: List[str], exit_code: int,
stdout: List[str], stderr: List[str],
duration: Optional[timedelta] = None,
with_stats: bool = False,
- exception: Optional[str] = None):
+ exception: Optional[str] = None,
+ profile: Optional[RunProfile] = None):
self._args = args
self._exit_code = exit_code
self._exception = exception
self._stdout = stdout
self._stderr = stderr
+ self._profile = profile
self._duration = duration if duration is not None else timedelta()
self._response = None
self._responses = []
@@ -117,6 +182,10 @@ class ExecResult:
return self._duration
@property
+ def profile(self) -> Optional[RunProfile]:
+ return self._profile
+
+ @property
def response(self) -> Optional[Dict]:
return self._response
@@ -247,7 +316,7 @@ class ExecResult:
if exitcode is not None:
for idx, x in enumerate(self.stats):
if 'exitcode' in x:
- assert x['exitcode'] == 0, \
+ assert x['exitcode'] == exitcode, \
f'status #{idx} exitcode: expected {exitcode}, '\
f'got {x["exitcode"]}\n{self.dump_stat(x)}'
@@ -344,14 +413,15 @@ class CurlClient:
return xargs
def http_get(self, url: str, extra_args: Optional[List[str]] = None,
- def_tracing: bool = True):
+ def_tracing: bool = True, with_profile: bool = False):
return self._raw(url, options=extra_args, with_stats=False,
- def_tracing=def_tracing)
+ def_tracing=def_tracing, with_profile=with_profile)
def http_download(self, urls: List[str],
alpn_proto: Optional[str] = None,
with_stats: bool = True,
with_headers: bool = False,
+ with_profile: bool = False,
no_save: bool = False,
extra_args: List[str] = None):
if extra_args is None:
@@ -373,12 +443,14 @@ class CurlClient:
])
return self._raw(urls, alpn_proto=alpn_proto, options=extra_args,
with_stats=with_stats,
- with_headers=with_headers)
+ with_headers=with_headers,
+ with_profile=with_profile)
def http_upload(self, urls: List[str], data: str,
alpn_proto: Optional[str] = None,
with_stats: bool = True,
with_headers: bool = False,
+ with_profile: bool = False,
extra_args: Optional[List[str]] = None):
if extra_args is None:
extra_args = []
@@ -391,12 +463,14 @@ class CurlClient:
])
return self._raw(urls, alpn_proto=alpn_proto, options=extra_args,
with_stats=with_stats,
- with_headers=with_headers)
+ with_headers=with_headers,
+ with_profile=with_profile)
def http_put(self, urls: List[str], data=None, fdata=None,
alpn_proto: Optional[str] = None,
with_stats: bool = True,
with_headers: bool = False,
+ with_profile: bool = False,
extra_args: Optional[List[str]] = None):
if extra_args is None:
extra_args = []
@@ -414,7 +488,8 @@ class CurlClient:
return self._raw(urls, intext=data,
alpn_proto=alpn_proto, options=extra_args,
with_stats=with_stats,
- with_headers=with_headers)
+ with_headers=with_headers,
+ with_profile=with_profile)
def http_form(self, urls: List[str], form: Dict[str, str],
alpn_proto: Optional[str] = None,
@@ -439,7 +514,7 @@ class CurlClient:
def response_file(self, idx: int):
return os.path.join(self._run_dir, f'download_{idx}.data')
- def run_direct(self, args, with_stats: bool = False):
+ def run_direct(self, args, with_stats: bool = False, with_profile: bool = False):
my_args = [self._curl]
if with_stats:
my_args.extend([
@@ -449,22 +524,48 @@ class CurlClient:
'-o', 'download.data',
])
my_args.extend(args)
- return self._run(args=my_args, with_stats=with_stats)
+ return self._run(args=my_args, with_stats=with_stats, with_profile=with_profile)
- def _run(self, args, intext='', with_stats: bool = False):
+ def _run(self, args, intext='', with_stats: bool = False, with_profile: bool = True):
self._rmf(self._stdoutfile)
self._rmf(self._stderrfile)
self._rmf(self._headerfile)
- start = datetime.now()
+ started_at = datetime.now()
exception = None
+ profile = None
try:
with open(self._stdoutfile, 'w') as cout:
with open(self._stderrfile, 'w') as cerr:
- p = subprocess.run(args, stderr=cerr, stdout=cout,
- cwd=self._run_dir, shell=False,
- input=intext.encode() if intext else None,
- timeout=self._timeout)
- exitcode = p.returncode
+ if with_profile:
+ started_at = datetime.now()
+ end_at = started_at + timedelta(seconds=self._timeout) \
+ if self._timeout else None
+ log.info(f'starting: {args}')
+ p = subprocess.Popen(args, stderr=cerr, stdout=cout,
+ cwd=self._run_dir, shell=False)
+ profile = RunProfile(p.pid, started_at, self._run_dir)
+ if intext is not None and False:
+ p.communicate(input=intext.encode(), timeout=1)
+ ptimeout = 0.0
+ while True:
+ try:
+ p.wait(timeout=ptimeout)
+ break
+ except subprocess.TimeoutExpired:
+ if end_at and datetime.now() >= end_at:
+ p.kill()
+ raise subprocess.TimeoutExpired(cmd=args, timeout=self._timeout)
+ profile.sample()
+ ptimeout = 0.01
+ exitcode = p.returncode
+ profile.finish()
+ log.info(f'done: exit={exitcode}, profile={profile}')
+ else:
+ p = subprocess.run(args, stderr=cerr, stdout=cout,
+ cwd=self._run_dir, shell=False,
+ input=intext.encode() if intext else None,
+ timeout=self._timeout)
+ exitcode = p.returncode
except subprocess.TimeoutExpired:
log.warning(f'Timeout after {self._timeout}s: {args}')
exitcode = -1
@@ -473,20 +574,23 @@ class CurlClient:
cerrput = open(self._stderrfile).readlines()
return ExecResult(args=args, exit_code=exitcode, exception=exception,
stdout=coutput, stderr=cerrput,
- duration=datetime.now() - start,
- with_stats=with_stats)
+ duration=datetime.now() - started_at,
+ with_stats=with_stats,
+ profile=profile)
def _raw(self, urls, intext='', timeout=None, options=None, insecure=False,
alpn_proto: Optional[str] = None,
force_resolve=True,
with_stats=False,
with_headers=True,
- def_tracing=True):
+ def_tracing=True,
+ with_profile=False):
args = self._complete_args(
urls=urls, timeout=timeout, options=options, insecure=insecure,
alpn_proto=alpn_proto, force_resolve=force_resolve,
with_headers=with_headers, def_tracing=def_tracing)
- r = self._run(args, intext=intext, with_stats=with_stats)
+ r = self._run(args, intext=intext, with_stats=with_stats,
+ with_profile=with_profile)
if r.exit_code == 0 and with_headers:
self._parse_headerfile(self._headerfile, r=r)
if r.json:
@@ -504,14 +608,20 @@ class CurlClient:
args = [self._curl, "-s", "--path-as-is"]
if with_headers:
args.extend(["-D", self._headerfile])
- if def_tracing is not False:
- args.extend(['-v', '--trace-config', 'ids,time'])
+ if def_tracing is not False and not self._silent:
+ args.extend(['-v', '--trace-ids', '--trace-time'])
if self.env.verbose > 1:
args.extend(['--trace-config', 'http/2,http/3,h2-proxy,h1-proxy'])
pass
+ active_options = options
+ if options is not None and '--next' in options:
+ active_options = options[options.index('--next') + 1:]
+
for url in urls:
u = urlparse(urls[0])
+ if options:
+ args.extend(options)
if alpn_proto is not None:
if alpn_proto not in self.ALPN_ARG:
raise Exception(f'unknown ALPN protocol: "{alpn_proto}"')
@@ -521,7 +631,7 @@ class CurlClient:
pass
elif insecure:
args.append('--insecure')
- elif options and "--cacert" in options:
+ elif active_options and "--cacert" in active_options:
pass
elif u.hostname:
args.extend(["--cacert", self.env.ca.cert_file])
@@ -532,8 +642,6 @@ class CurlClient:
args.extend(["--resolve", f"{u.hostname}:{port}:127.0.0.1"])
if timeout is not None and int(timeout) > 0:
args.extend(["--connect-timeout", str(int(timeout))])
- if options:
- args.extend(options)
args.append(url)
return args
diff --git a/tests/http/testenv/mod_curltest/mod_curltest.c b/tests/http/testenv/mod_curltest/mod_curltest.c
index 30fb765ae..ff1983d17 100644
--- a/tests/http/testenv/mod_curltest/mod_curltest.c
+++ b/tests/http/testenv/mod_curltest/mod_curltest.c
@@ -423,6 +423,7 @@ static int curltest_put_handler(request_rec *r)
char buffer[16*1024];
const char *ct;
apr_off_t rbody_len = 0;
+ const char *s_rbody_len;
const char *request_id = "none";
apr_time_t chunk_delay = 0;
apr_array_header_t *args = NULL;
@@ -491,7 +492,9 @@ static int curltest_put_handler(request_rec *r)
}
}
/* we are done */
- rv = apr_brigade_printf(bb, NULL, NULL, "%"APR_OFF_T_FMT, rbody_len);
+ s_rbody_len = apr_psprintf(r->pool, "%"APR_OFF_T_FMT, rbody_len);
+ apr_table_setn(r->headers_out, "Received-Length", s_rbody_len);
+ rv = apr_brigade_puts(bb, NULL, NULL, s_rbody_len);
if(APR_SUCCESS != rv) goto cleanup;
b = apr_bucket_eos_create(c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
diff --git a/tests/http/testenv/nghttpx.py b/tests/http/testenv/nghttpx.py
index 4be060b56..9544ce05d 100644
--- a/tests/http/testenv/nghttpx.py
+++ b/tests/http/testenv/nghttpx.py
@@ -129,7 +129,9 @@ class Nghttpx:
try_until = datetime.now() + timeout
while datetime.now() < try_until:
check_url = f'https://{self.env.domain1}:{self._port}/'
- r = curl.http_get(url=check_url, extra_args=['--http3-only'])
+ r = curl.http_get(url=check_url, extra_args=[
+ '--http3-only', '--connect-timeout', '1'
+ ])
if r.exit_code != 0:
return True
log.debug(f'waiting for nghttpx to stop responding: {r}')
@@ -143,7 +145,8 @@ class Nghttpx:
while datetime.now() < try_until:
check_url = f'https://{self.env.domain1}:{self._port}/'
r = curl.http_get(url=check_url, extra_args=[
- '--http3-only', '--trace', 'curl.trace', '--trace-time'
+ '--http3-only', '--trace', 'curl.trace', '--trace-time',
+ '--connect-timeout', '1'
])
if r.exit_code == 0:
return True
@@ -193,6 +196,7 @@ class NghttpxQuic(Nghttpx):
f'--frontend-http3-max-window-size=10M',
f'--frontend-http3-connection-window-size=10M',
f'--frontend-http3-max-connection-window-size=100M',
+ # f'--frontend-quic-debug-log',
]
ngerr = open(self._stderr, 'a')
self._process = subprocess.Popen(args=args, stderr=ngerr)
diff --git a/tests/libtest/CMakeLists.txt b/tests/libtest/CMakeLists.txt
index 98f5b9c67..b6450ff3a 100644
--- a/tests/libtest/CMakeLists.txt
+++ b/tests/libtest/CMakeLists.txt
@@ -67,7 +67,7 @@ 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 EXCLUDE_FROM_ALL sethostname.c sethostname.h)
+ add_library(hostname MODULE EXCLUDE_FROM_ALL sethostname.c)
add_dependencies(testdeps hostname)
# Output to .libs for compatibility with autotools, the test data expects a
# library at (tests)/libtest/.libs/libhostname.so
diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am
index 09a13914a..8ae972a24 100644
--- a/tests/libtest/Makefile.am
+++ b/tests/libtest/Makefile.am
@@ -103,7 +103,7 @@ libhostname_la_CPPFLAGS = $(AM_CPPFLAGS) $(libhostname_la_CPPFLAGS_EXTRA)
libhostname_la_LDFLAGS = $(AM_LDFLAGS) $(libhostname_la_LDFLAGS_EXTRA)
libhostname_la_CFLAGS = $(AM_CFLAGS) $(libhostname_la_CFLAGS_EXTRA)
-libhostname_la_SOURCES = sethostname.c sethostname.h
+libhostname_la_SOURCES = sethostname.c
libhostname_la_LIBADD =
libhostname_la_DEPENDENCIES =
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 85801e002..c4d36a26b 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -58,13 +58,14 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect libprereq \
lib1518 lib1520 lib1521 lib1522 lib1523 \
lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \
lib1534 lib1535 lib1536 lib1537 lib1538 lib1539 \
- lib1540 lib1542 lib1543 \
+ lib1540 lib1542 lib1543 lib1545 \
lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 \
lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 \
\
lib1662 \
\
+ lib1900 \
lib1903 lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \
lib1915 lib1916 lib1917 lib1918 lib1919 \
lib1933 lib1934 lib1935 lib1936 lib1937 lib1938 lib1939 lib1940 \
@@ -466,6 +467,9 @@ lib1542_LDADD = $(TESTUTIL_LIBS)
lib1543_SOURCES = lib1518.c $(SUPPORTFILES)
lib1543_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1543
+lib1545_SOURCES = lib1545.c $(SUPPORTFILES)
+lib1545_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_DISABLE_DEPRECATION
+
lib1550_SOURCES = lib1550.c $(SUPPORTFILES)
lib1551_SOURCES = lib1551.c $(SUPPORTFILES)
@@ -530,6 +534,8 @@ lib1597_LDADD = $(TESTUTIL_LIBS)
lib1662_SOURCES = lib1662.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1662_LDADD = $(TESTUTIL_LIBS)
+lib1900_SOURCES = lib1900.c $(SUPPORTFILES)
+
lib1903_SOURCES = lib1903.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1903_LDADD = $(TESTUTIL_LIBS)
diff --git a/tests/libtest/first.c b/tests/libtest/first.c
index 7bd129ab3..42c53c694 100644
--- a/tests/libtest/first.c
+++ b/tests/libtest/first.c
@@ -65,12 +65,16 @@ int select_wrapper(int nfds, fd_set *rd, fd_set *wr, fd_set *exc,
void wait_ms(int ms)
{
+ if(ms < 0)
+ return;
#ifdef USE_WINSOCK
- Sleep(ms);
+ Sleep((DWORD)ms);
#else
- struct timeval t;
- curlx_mstotv(&t, ms);
- select_wrapper(0, NULL, NULL, NULL, &t);
+ {
+ struct timeval t;
+ curlx_mstotv(&t, ms);
+ select_wrapper(0, NULL, NULL, NULL, &t);
+ }
#endif
}
@@ -174,7 +178,7 @@ int main(int argc, char **argv)
result = test(URL);
fprintf(stderr, "Test ended with result %d\n", result);
-#ifdef WIN32
+#ifdef _WIN32
/* flush buffers of all streams regardless of mode */
_flushall();
#endif
diff --git a/tests/libtest/lib1156.c b/tests/libtest/lib1156.c
index aae2893ef..b512ef67a 100644
--- a/tests/libtest/lib1156.c
+++ b/tests/libtest/lib1156.c
@@ -68,7 +68,7 @@ static const struct testparams params[] = {
{ F_RESUME | F_HTTP416 | F_CONTENTRANGE | F_IGNOREBODY, CURLE_OK },
{ F_RESUME | F_HTTP416 | F_FAIL | F_IGNOREBODY, CURLE_OK },
{ F_RESUME | F_HTTP416 | F_FAIL | F_CONTENTRANGE | F_IGNOREBODY,
- CURLE_HTTP_RETURNED_ERROR }
+ CURLE_OK }
};
static int hasbody;
diff --git a/tests/libtest/lib1517.c b/tests/libtest/lib1517.c
index 706b5567c..126792017 100644
--- a/tests/libtest/lib1517.c
+++ b/tests/libtest/lib1517.c
@@ -61,7 +61,7 @@ int test(char *URL)
struct WriteThis pooh;
if(!strcmp(URL, "check")) {
-#if (defined(WIN32) || defined(__CYGWIN__))
+#if (defined(_WIN32) || defined(__CYGWIN__))
printf("Windows TCP does not deliver response data but reports "
"CONNABORTED\n");
return 1; /* skip since test will fail on Windows without workaround */
diff --git a/tests/libtest/lib1531.c b/tests/libtest/lib1531.c
index 703400178..b64e16603 100644
--- a/tests/libtest/lib1531.c
+++ b/tests/libtest/lib1531.c
@@ -110,7 +110,7 @@ int test(char *URL)
curl_multi_fdset() doc. */
if(maxfd == -1) {
-#if defined(WIN32) || defined(_WIN32)
+#if defined(_WIN32)
Sleep(100);
rc = 0;
#else
diff --git a/tests/libtest/lib1545.c b/tests/libtest/lib1545.c
new file mode 100644
index 000000000..f31baa0c4
--- /dev/null
+++ b/tests/libtest/lib1545.c
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#ifndef CURL_DISABLE_DEPRECATION
+#define CURL_DISABLE_DEPRECATION /* Using and testing the form api */
+#endif
+#include "test.h"
+
+int test(char *URL)
+{
+ CURL *eh = NULL;
+ int res = 0;
+ struct curl_httppost *lastptr = NULL;
+ struct curl_httppost *m_formpost = NULL;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ easy_init(eh);
+
+ easy_setopt(eh, CURLOPT_URL, URL);
+ curl_formadd(&m_formpost, &lastptr, CURLFORM_COPYNAME, "file",
+ CURLFORM_FILE, "missing-file", CURLFORM_END);
+ curl_easy_setopt(eh, CURLOPT_HTTPPOST, m_formpost);
+
+ (void)curl_easy_perform(eh);
+ (void)curl_easy_perform(eh);
+
+test_cleanup:
+
+ curl_formfree(m_formpost);
+
+ curl_easy_cleanup(eh);
+ curl_global_cleanup();
+
+ return res;
+}
diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c
index 765df0a27..1509c76a7 100644
--- a/tests/libtest/lib1560.c
+++ b/tests/libtest/lib1560.c
@@ -151,6 +151,9 @@ struct clearurlcase {
};
static const struct testcase get_parts_list[] ={
+ {"https://curl.se/# ",
+ "https | [11] | [12] | [13] | curl.se | [15] | / | [16] | %20%20",
+ CURLU_URLENCODE|CURLU_ALLOW_SPACE, 0, CURLUE_OK},
{"", "", 0, 0, CURLUE_MALFORMED_INPUT},
{" ", "", 0, 0, CURLUE_MALFORMED_INPUT},
{"1h://example.net", "", 0, 0, CURLUE_BAD_SCHEME},
@@ -316,7 +319,7 @@ static const struct testcase get_parts_list[] ={
"http | ftp.user | moo | [13] | example.com | [15] | /color/ | [16] | "
"green?no-red",
CURLU_GUESS_SCHEME, 0, CURLUE_OK },
-#ifdef WIN32
+#ifdef _WIN32
{"file:/C:\\programs\\foo",
"file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
@@ -785,6 +788,18 @@ static const struct setgetcase setget_parts_list[] = {
/* !checksrc! disable SPACEBEFORECOMMA 1 */
static const struct setcase set_parts_list[] = {
+ {"https://example.com/?param=value",
+ "query=\"\",",
+ "https://example.com/",
+ 0, CURLU_APPENDQUERY | CURLU_URLENCODE, CURLUE_OK, CURLUE_OK},
+ {"https://example.com/",
+ "host=\"\",",
+ "https://example.com/",
+ 0, CURLU_URLENCODE, CURLUE_OK, CURLUE_BAD_HOSTNAME},
+ {"https://example.com/",
+ "host=\"\",",
+ "https://example.com/",
+ 0, 0, CURLUE_OK, CURLUE_BAD_HOSTNAME},
{"https://example.com",
"path=get,",
"https://example.com/get",
@@ -1030,7 +1045,7 @@ static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
while(p) {
char *e = strchr(p, ',');
if(e) {
- size_t n = e-p;
+ size_t n = (size_t)(e - p);
char buf[80];
char part[80];
char value[80];
@@ -1624,7 +1639,6 @@ static char bigpart[120000];
*/
static int huge(void)
{
- const char *url = "%s://%s:%s@%s/%s?%s#%s";
const char *smallpart = "c";
int i;
CURLU *urlp = curl_url();
@@ -1648,7 +1662,7 @@ static int huge(void)
for(i = 0; i < 7; i++) {
char *partp;
msnprintf(total, sizeof(total),
- url,
+ "%s://%s:%s@%s/%s?%s#%s",
(i == 0)? &bigpart[1] : smallpart,
(i == 1)? &bigpart[1] : smallpart,
(i == 2)? &bigpart[1] : smallpart,
diff --git a/tests/libtest/lib1900.c b/tests/libtest/lib1900.c
new file mode 100644
index 000000000..92f89c4c4
--- /dev/null
+++ b/tests/libtest/lib1900.c
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 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.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.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "test.h"
+
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURLcode res = CURLE_OK;
+ CURL *hnd = NULL;
+ CURL *second = NULL;
+
+ global_init(CURL_GLOBAL_ALL);
+
+ easy_init(hnd);
+ easy_setopt(hnd, CURLOPT_URL, URL);
+ easy_setopt(hnd, CURLOPT_HSTS, "first-hsts.txt");
+ easy_setopt(hnd, CURLOPT_HSTS, "second-hsts.txt");
+
+ second = curl_easy_duphandle(hnd);
+
+ curl_easy_cleanup(hnd);
+ curl_easy_cleanup(second);
+ curl_global_cleanup();
+ return 0;
+
+test_cleanup:
+ curl_easy_cleanup(hnd);
+ curl_easy_cleanup(second);
+ curl_global_cleanup();
+ return (int)res;
+}
diff --git a/tests/libtest/lib1940.c b/tests/libtest/lib1940.c
index 8bc094362..05da9de30 100644
--- a/tests/libtest/lib1940.c
+++ b/tests/libtest/lib1940.c
@@ -35,6 +35,8 @@ static const char *show[]={
"set-cookie",
"silly-thing",
"fold",
+ "blank",
+ "Blank2",
NULL
};
diff --git a/tests/libtest/lib1947.c b/tests/libtest/lib1947.c
index b7a013127..c81345f9d 100644
--- a/tests/libtest/lib1947.c
+++ b/tests/libtest/lib1947.c
@@ -39,7 +39,7 @@ int test(char *URL)
CURLcode res = CURLE_OK;
struct curl_header *h;
int count = 0;
- int origins;
+ unsigned int origins;
global_init(CURL_GLOBAL_DEFAULT);
diff --git a/tests/libtest/lib1960.c b/tests/libtest/lib1960.c
index fc2f4b0af..9b82128e9 100644
--- a/tests/libtest/lib1960.c
+++ b/tests/libtest/lib1960.c
@@ -25,12 +25,6 @@
#ifdef HAVE_INET_PTON
-#ifdef WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#endif
-
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
diff --git a/tests/libtest/lib2305.c b/tests/libtest/lib2305.c
index 0778e0b58..374423f0f 100644
--- a/tests/libtest/lib2305.c
+++ b/tests/libtest/lib2305.c
@@ -71,8 +71,6 @@ static void websocket(CURL *curl)
websocket_close(curl);
}
-extern struct libtest_trace_cfg libtest_debug_config;
-
int test(char *URL)
{
CURL *curl;
diff --git a/tests/libtest/lib3026.c b/tests/libtest/lib3026.c
index 42b44c890..6f31dabde 100644
--- a/tests/libtest/lib3026.c
+++ b/tests/libtest/lib3026.c
@@ -28,7 +28,7 @@
#define NUM_THREADS 100
-#ifdef WIN32
+#ifdef _WIN32
#ifdef _WIN32_WCE
static DWORD WINAPI run_thread(LPVOID ptr)
#else
@@ -84,7 +84,7 @@ int test(char *URL)
th = _beginthreadex(NULL, 0, run_thread, &results[i], 0, NULL);
#endif
if(!th) {
- fprintf(stderr, "%s:%d Couldn't create thread, errno %d\n",
+ fprintf(stderr, "%s:%d Couldn't create thread, errno %lu\n",
__FILE__, __LINE__, GetLastError());
tid_count = i;
test_failure = -1;
diff --git a/tests/libtest/lib517.c b/tests/libtest/lib517.c
index 7c65a659c..0d1ea2eb4 100644
--- a/tests/libtest/lib517.c
+++ b/tests/libtest/lib517.c
@@ -164,7 +164,7 @@ int test(char *URL)
time_t out = curl_getdate(dates[i].input, NULL);
if(out != dates[i].output) {
printf("WRONGLY %s => %ld (instead of %ld)\n",
- dates[i].input, out, dates[i].output);
+ dates[i].input, (long)out, (long)dates[i].output);
error++;
}
}
diff --git a/tests/libtest/lib518.c b/tests/libtest/lib518.c
index 87b6f2d88..200041239 100644
--- a/tests/libtest/lib518.c
+++ b/tests/libtest/lib518.c
@@ -42,7 +42,7 @@
#define NUM_OPEN (FD_SETSIZE + 10)
#define NUM_NEEDED (NUM_OPEN + SAFETY_MARGIN)
-#if defined(WIN32) || defined(_WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
#define DEV_NULL "NUL"
#else
#define DEV_NULL "/dev/null"
@@ -99,25 +99,35 @@ static int fopen_works(void)
return ret;
}
+static void rlim2str(char *buf, size_t len, rlim_t val)
+{
+#ifdef RLIM_INFINITY
+ if(val == RLIM_INFINITY) {
+ msnprintf(buf, len, "INFINITY");
+ return;
+ }
+#endif
+#ifdef HAVE_LONGLONG
+ if(sizeof(rlim_t) > sizeof(long))
+ msnprintf(buf, len, "%llu", (unsigned long long)val);
+ else
+#endif
+ {
+ if(sizeof(rlim_t) < sizeof(long))
+ msnprintf(buf, len, "%u", (unsigned int)val);
+ else
+ msnprintf(buf, len, "%lu", (unsigned long)val);
+ }
+}
+
static int rlimit(int keep_open)
{
- int nitems, i;
+ rlim_t nitems, i;
int *memchunk = NULL;
- char *fmt;
struct rlimit rl;
char strbuff[256];
char strbuff1[81];
char strbuff2[81];
- char fmt_u[] = "%u";
- char fmt_lu[] = "%lu";
-#ifdef HAVE_LONGLONG
- char fmt_llu[] = "%llu";
-
- if(sizeof(rl.rlim_max) > sizeof(long))
- fmt = fmt_llu;
- else
-#endif
- fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu;
/* get initial open file limits */
@@ -129,20 +139,10 @@ static int rlimit(int keep_open)
/* show initial open file limits */
-#ifdef RLIM_INFINITY
- if(rl.rlim_cur == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_cur);
fprintf(stderr, "initial soft limit: %s\n", strbuff);
-#ifdef RLIM_INFINITY
- if(rl.rlim_max == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_max);
fprintf(stderr, "initial hard limit: %s\n", strbuff);
/* show our constants */
@@ -195,20 +195,10 @@ static int rlimit(int keep_open)
/* show current open file limits */
-#ifdef RLIM_INFINITY
- if(rl.rlim_cur == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_cur);
fprintf(stderr, "current soft limit: %s\n", strbuff);
-#ifdef RLIM_INFINITY
- if(rl.rlim_max == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_max);
fprintf(stderr, "current hard limit: %s\n", strbuff);
} /* (rl.rlim_cur != rl.rlim_max) */
@@ -235,8 +225,8 @@ static int rlimit(int keep_open)
(rl.rlim_cur != RLIM_INFINITY) &&
#endif
(rl.rlim_cur <= num_open.rlim_cur)) {
- msnprintf(strbuff2, sizeof(strbuff2), fmt, rl.rlim_cur);
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
+ rlim2str(strbuff2, sizeof(strbuff2), rl.rlim_cur);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur);
msnprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s",
strbuff1, strbuff2);
store_errmsg(strbuff, 0);
@@ -258,8 +248,8 @@ static int rlimit(int keep_open)
if(nitems > 0x7fff)
nitems = 0x40000;
do {
- num_open.rlim_max = sizeof(*memchunk) * (size_t)nitems;
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ num_open.rlim_max = sizeof(*memchunk) * nitems;
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "allocating memchunk %s byte array\n", strbuff);
memchunk = malloc(sizeof(*memchunk) * (size_t)nitems);
if(!memchunk) {
@@ -287,7 +277,7 @@ static int rlimit(int keep_open)
/* verify that we won't overflow size_t in malloc() */
if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) {
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max);
msnprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s "
"file descriptors, would overflow size_t", strbuff1);
store_errmsg(strbuff, 0);
@@ -298,7 +288,7 @@ static int rlimit(int keep_open)
/* allocate array for file descriptors */
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "allocating array for %s file descriptors\n", strbuff);
fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max));
@@ -318,7 +308,7 @@ static int rlimit(int keep_open)
num_open.rlim_cur++)
fd[num_open.rlim_cur] = -1;
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "trying to open %s file descriptors\n", strbuff);
/* open a dummy descriptor */
@@ -346,21 +336,21 @@ static int rlimit(int keep_open)
fd[num_open.rlim_cur] = -1;
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur);
msnprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1);
fprintf(stderr, "%s\n", strbuff);
- msnprintf(strbuff1, sizeof(strbuff), fmt, num_open.rlim_cur);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur);
msnprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s",
- strbuff1);
+ strbuff1);
fprintf(stderr, "%s\n", strbuff);
num_open.rlim_max = NUM_NEEDED;
- msnprintf(strbuff2, sizeof(strbuff2), fmt, num_open.rlim_max);
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
+ rlim2str(strbuff2, sizeof(strbuff2), num_open.rlim_max);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur);
msnprintf(strbuff, sizeof(strbuff), "fds needed %s > system limit %s",
- strbuff2, strbuff1);
+ strbuff2, strbuff1);
store_errmsg(strbuff, 0);
fprintf(stderr, "%s\n", msgbuff);
@@ -372,12 +362,10 @@ static int rlimit(int keep_open)
fd = NULL;
free(memchunk);
return -9;
-
}
-
}
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "%s file descriptors open\n", strbuff);
#if !defined(HAVE_POLL_FINE) && !defined(USE_WINSOCK)
@@ -396,7 +384,7 @@ static int rlimit(int keep_open)
num_open.rlim_cur = FD_SETSIZE - SAFETY_MARGIN;
if(num_open.rlim_max > num_open.rlim_cur) {
msnprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
- FD_SETSIZE);
+ FD_SETSIZE);
store_errmsg(strbuff, 0);
fprintf(stderr, "%s\n", msgbuff);
close_file_descriptors();
@@ -411,7 +399,7 @@ static int rlimit(int keep_open)
if((fd[rl.rlim_cur] > 0) &&
((unsigned int)fd[rl.rlim_cur] > num_open.rlim_cur)) {
msnprintf(strbuff, sizeof(strbuff), "select limit is FD_SETSIZE %d",
- FD_SETSIZE);
+ FD_SETSIZE);
store_errmsg(strbuff, 0);
fprintf(stderr, "%s\n", msgbuff);
close_file_descriptors();
@@ -432,13 +420,11 @@ static int rlimit(int keep_open)
*/
if(!fopen_works()) {
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
- msnprintf(strbuff, sizeof(strbuff),
- "fopen fails with %s fds open()",
- strbuff1);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max);
+ msnprintf(strbuff, sizeof(strbuff), "fopen fails with %s fds open",
+ strbuff1);
fprintf(stderr, "%s\n", msgbuff);
- msnprintf(strbuff, sizeof(strbuff),
- "fopen fails with lots of fds open()");
+ msnprintf(strbuff, sizeof(strbuff), "fopen fails with lots of fds open");
store_errmsg(strbuff, 0);
close_file_descriptors();
free(memchunk);
diff --git a/tests/libtest/lib537.c b/tests/libtest/lib537.c
index 3782282b8..b83e3ce31 100644
--- a/tests/libtest/lib537.c
+++ b/tests/libtest/lib537.c
@@ -42,7 +42,7 @@
#define SAFETY_MARGIN (11)
-#if defined(WIN32) || defined(_WIN32) || defined(MSDOS)
+#if defined(_WIN32) || defined(MSDOS)
#define DEV_NULL "NUL"
#else
#define DEV_NULL "/dev/null"
@@ -59,8 +59,8 @@ static void store_errmsg(const char *msg, int err)
if(!err)
msnprintf(msgbuff, sizeof(msgbuff), "%s", msg);
else
- msnprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg, err,
- strerror(err));
+ msnprintf(msgbuff, sizeof(msgbuff), "%s, errno %d, %s", msg,
+ err, strerror(err));
}
static void close_file_descriptors(void)
@@ -99,25 +99,35 @@ static int fopen_works(void)
return ret;
}
+static void rlim2str(char *buf, size_t len, rlim_t val)
+{
+#ifdef RLIM_INFINITY
+ if(val == RLIM_INFINITY) {
+ msnprintf(buf, len, "INFINITY");
+ return;
+ }
+#endif
+#ifdef HAVE_LONGLONG
+ if(sizeof(rlim_t) > sizeof(long))
+ msnprintf(buf, len, "%llu", (unsigned long long)val);
+ else
+#endif
+ {
+ if(sizeof(rlim_t) < sizeof(long))
+ msnprintf(buf, len, "%u", (unsigned int)val);
+ else
+ msnprintf(buf, len, "%lu", (unsigned long)val);
+ }
+}
+
static int rlimit(int keep_open)
{
int *tmpfd;
rlim_t nitems, i;
int *memchunk = NULL;
- char *fmt;
struct rlimit rl;
char strbuff[256];
char strbuff1[81];
- char fmt_u[] = "%u";
- char fmt_lu[] = "%lu";
-#ifdef HAVE_LONGLONG
- char fmt_llu[] = "%llu";
-
- if(sizeof(rl.rlim_max) > sizeof(long))
- fmt = fmt_llu;
- else
-#endif
- fmt = (sizeof(rl.rlim_max) < sizeof(long))?fmt_u:fmt_lu;
/* get initial open file limits */
@@ -129,20 +139,10 @@ static int rlimit(int keep_open)
/* show initial open file limits */
-#ifdef RLIM_INFINITY
- if(rl.rlim_cur == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_cur);
fprintf(stderr, "initial soft limit: %s\n", strbuff);
-#ifdef RLIM_INFINITY
- if(rl.rlim_max == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_max);
fprintf(stderr, "initial hard limit: %s\n", strbuff);
/*
@@ -158,7 +158,7 @@ static int rlimit(int keep_open)
#ifdef OPEN_MAX
if((rl.rlim_cur > 0) &&
- (rl.rlim_cur < OPEN_MAX)) {
+ (rl.rlim_cur < OPEN_MAX)) {
fprintf(stderr, "raising soft limit up to OPEN_MAX\n");
rl.rlim_cur = OPEN_MAX;
if(setrlimit(RLIMIT_NOFILE, &rl) != 0) {
@@ -189,20 +189,10 @@ static int rlimit(int keep_open)
/* show current open file limits */
-#ifdef RLIM_INFINITY
- if(rl.rlim_cur == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_cur);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_cur);
fprintf(stderr, "current soft limit: %s\n", strbuff);
-#ifdef RLIM_INFINITY
- if(rl.rlim_max == RLIM_INFINITY)
- strcpy(strbuff, "INFINITY");
- else
-#endif
- msnprintf(strbuff, sizeof(strbuff), fmt, rl.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), rl.rlim_max);
fprintf(stderr, "current hard limit: %s\n", strbuff);
} /* (rl.rlim_cur != rl.rlim_max) */
@@ -232,7 +222,7 @@ static int rlimit(int keep_open)
nitems = 0x40000;
do {
num_open.rlim_max = sizeof(*memchunk) * nitems;
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "allocating memchunk %s byte array\n", strbuff);
memchunk = malloc(sizeof(*memchunk) * (size_t)nitems);
if(!memchunk) {
@@ -275,7 +265,7 @@ static int rlimit(int keep_open)
/* verify that we won't overflow size_t in malloc() */
if((size_t)(num_open.rlim_max) > ((size_t)-1) / sizeof(*fd)) {
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max);
msnprintf(strbuff, sizeof(strbuff), "unable to allocate an array for %s "
"file descriptors, would overflow size_t", strbuff1);
store_errmsg(strbuff, 0);
@@ -287,8 +277,9 @@ static int rlimit(int keep_open)
/* allocate array for file descriptors */
do {
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "allocating array for %s file descriptors\n", strbuff);
+
fd = malloc(sizeof(*fd) * (size_t)(num_open.rlim_max));
if(!fd) {
fprintf(stderr, "fd, malloc() failed\n");
@@ -311,7 +302,7 @@ static int rlimit(int keep_open)
num_open.rlim_cur++)
fd[num_open.rlim_cur] = -1;
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "trying to open %s file descriptors\n", strbuff);
/* open a dummy descriptor */
@@ -339,11 +330,11 @@ static int rlimit(int keep_open)
fd[num_open.rlim_cur] = -1;
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur);
msnprintf(strbuff, sizeof(strbuff), "dup() attempt %s failed", strbuff1);
fprintf(stderr, "%s\n", strbuff);
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur);
msnprintf(strbuff, sizeof(strbuff), "fds system limit seems close to %s",
strbuff1);
fprintf(stderr, "%s\n", strbuff);
@@ -351,7 +342,7 @@ static int rlimit(int keep_open)
num_open.rlim_max = num_open.rlim_cur - SAFETY_MARGIN;
num_open.rlim_cur -= num_open.rlim_max;
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_cur);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_cur);
msnprintf(strbuff, sizeof(strbuff), "closing %s file descriptors",
strbuff1);
fprintf(stderr, "%s\n", strbuff);
@@ -363,7 +354,7 @@ static int rlimit(int keep_open)
fd[num_open.rlim_cur] = -1;
}
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "shrinking array for %s file descriptors\n", strbuff);
/* we don't care if we can't shrink it */
@@ -375,12 +366,10 @@ static int rlimit(int keep_open)
}
break;
-
}
-
}
- msnprintf(strbuff, sizeof(strbuff), fmt, num_open.rlim_max);
+ rlim2str(strbuff, sizeof(strbuff), num_open.rlim_max);
fprintf(stderr, "%s file descriptors open\n", strbuff);
#if !defined(HAVE_POLL_FINE) && !defined(USE_WINSOCK)
@@ -435,7 +424,7 @@ static int rlimit(int keep_open)
*/
if(!fopen_works()) {
- msnprintf(strbuff1, sizeof(strbuff1), fmt, num_open.rlim_max);
+ rlim2str(strbuff1, sizeof(strbuff1), num_open.rlim_max);
msnprintf(strbuff, sizeof(strbuff), "fopen fails with %s fds open",
strbuff1);
fprintf(stderr, "%s\n", msgbuff);
diff --git a/tests/libtest/lib544.c b/tests/libtest/lib544.c
index 192bfb2e7..a58fa05e3 100644
--- a/tests/libtest/lib544.c
+++ b/tests/libtest/lib544.c
@@ -63,7 +63,6 @@ int test(char *URL)
/* Update the original data to detect non-copy. */
strcpy(teststring, "FAIL");
-#ifdef LIB545
{
CURL *handle2;
handle2 = curl_easy_duphandle(curl);
@@ -71,7 +70,6 @@ int test(char *URL)
curl = handle2;
}
-#endif
/* Now, this is a POST request with binary 0 embedded in POST data. */
res = curl_easy_perform(curl);
diff --git a/tests/libtest/lib552.c b/tests/libtest/lib552.c
index 13726c6b4..436b86ec0 100644
--- a/tests/libtest/lib552.c
+++ b/tests/libtest/lib552.c
@@ -96,10 +96,7 @@ int my_trace(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", (char *)data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -118,6 +115,8 @@ int my_trace(CURL *handle, curl_infotype type,
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
dump(text, stderr, (unsigned char *)data, size, config->trace_ascii);
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 6f96668da..c15769474 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -1181,12 +1181,49 @@ static int test_string_formatting(void)
return errors;
}
+static int test_pos_arguments(void)
+{
+ int errors = 0;
+ char buf[256];
+
+ curl_msnprintf(buf, sizeof(buf), "%3$d %2$d %1$d", 500, 501, 502);
+ errors += string_check(buf, "502 501 500");
+
+ curl_msnprintf(buf, sizeof(buf), "%3$d %1$d %2$d", 500, 501, 502);
+ errors += string_check(buf, "502 500 501");
+
+ /* this is in invalid sequence but the output does not match
+ what glibc does */
+ curl_msnprintf(buf, sizeof(buf), "%3$d %d %2$d", 500, 501, 502);
+ errors += string_check(buf, "");
+
+ return errors;
+}
+
static int test_weird_arguments(void)
{
int errors = 0;
char buf[256];
int rc;
+ /* verify %% */
+ rc = curl_msnprintf(buf, sizeof(buf), "%-20d%% right? %%", 500);
+ errors += string_check(buf, "500 % right? %");
+
+ /* 100 x % */
+ rc = curl_msnprintf(buf, sizeof(buf), "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+ "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+ "%%%%%%%%%%%%%%%%%%%%%%");
+ /* 50 x % */
+ errors += string_check(buf, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+ "%%%%%%%%%%%%%%%");
+
+ rc = curl_msnprintf(buf, sizeof(buf), "%2 AA %d %K", 500, 501, 502);
+ errors += string_check(buf, "%2 AA 500 %K");
+
+ rc = curl_msnprintf(buf, sizeof(buf), "%2 %d %K", 500, 501, 502);
+ errors += string_check(buf, "%2 500 %K");
+
/* MAX_PARAMETERS is 128, try exact 128! */
rc = curl_msnprintf(buf, sizeof(buf),
"%d%d%d%d%d%d%d%d%d%d" /* 10 */
@@ -1276,18 +1313,6 @@ static int test_weird_arguments(void)
errors += string_check(buf, "");
- /* Do not skip sanity checks with parameters! */
- buf[0] = 0;
- rc = curl_msnprintf(buf, sizeof(buf), "%d, %.*1$d", 500, 1);
-
- if(rc != sizeof(buf) - 1) {
- printf("curl_mprintf() returned %d and not %d!\n", rc,
- sizeof(buf) - 1);
- errors++;
- }
-
- errors += strlen_check(buf, 255);
-
if(errors)
printf("Some curl_mprintf() weird arguments tests failed!\n");
@@ -1374,9 +1399,10 @@ static int test_float_formatting(void)
123456789123456789123456789.2987654);
errors += strlen_check(buf, 325);
- /* check negative when used signed */
+ /* check negative width argument when used signed, is treated as positive
+ and maxes out the internal float width == 325 */
curl_msnprintf(buf, sizeof(buf), "%*f", INT_MIN, 9.1);
- errors += string_check(buf, "9.100000");
+ errors += string_check(buf, "9.100000 ");
/* curl_msnprintf() limits a single float output to 325 bytes maximum
width */
@@ -1451,6 +1477,8 @@ int test(char *URL)
setlocale(LC_NUMERIC, "C");
#endif
+ errors += test_pos_arguments();
+
errors += test_weird_arguments();
errors += test_unsigned_short_formatting();
diff --git a/tests/libtest/lib567.c b/tests/libtest/lib567.c
index 00937e71d..a912b1663 100644
--- a/tests/libtest/lib567.c
+++ b/tests/libtest/lib567.c
@@ -49,6 +49,7 @@ int test(char *URL)
/* Dump data to stdout for protocol verification */
test_setopt(curl, CURLOPT_HEADERDATA, stdout);
test_setopt(curl, CURLOPT_WRITEDATA, stdout);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_URL, URL);
test_setopt(curl, CURLOPT_RTSP_STREAM_URI, URL);
diff --git a/tests/libtest/lib568.c b/tests/libtest/lib568.c
index 97304fa58..044527499 100644
--- a/tests/libtest/lib568.c
+++ b/tests/libtest/lib568.c
@@ -93,6 +93,7 @@ int test(char *URL)
test_setopt(curl, CURLOPT_READDATA, sdpf);
test_setopt(curl, CURLOPT_UPLOAD, 1L);
test_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) file_info.st_size);
+ test_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Do the ANNOUNCE */
res = curl_easy_perform(curl);
diff --git a/tests/libtest/lib670.c b/tests/libtest/lib670.c
index 700b908cf..b348343c2 100644
--- a/tests/libtest/lib670.c
+++ b/tests/libtest/lib670.c
@@ -215,7 +215,7 @@ int test(char *URL)
mres = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcept, &maxfd);
if(mres)
break;
-#if defined(WIN32) || defined(_WIN32)
+#if defined(_WIN32)
if(maxfd == -1)
Sleep(100);
else
diff --git a/tests/libtest/sethostname.c b/tests/libtest/sethostname.c
index 9dcad976c..1e07d26bc 100644
--- a/tests/libtest/sethostname.c
+++ b/tests/libtest/sethostname.c
@@ -23,8 +23,6 @@
***************************************************************************/
#include "curl_setup.h"
-#include "sethostname.h"
-
/*
* we force our own host name, in order to make some tests machine independent
*/
diff --git a/tests/libtest/sethostname.h b/tests/libtest/sethostname.h
deleted file mode 100644
index 1ffcba110..000000000
--- a/tests/libtest/sethostname.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 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.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.
- *
- * SPDX-License-Identifier: curl
- *
- ***************************************************************************/
-
-#ifdef CURL_STATICLIB
-# define LIBHOSTNAME_EXTERN
-#elif defined(WIN32)
-# define LIBHOSTNAME_EXTERN __declspec(dllexport)
-#elif defined(CURL_HIDDEN_SYMBOLS)
-# define LIBHOSTNAME_EXTERN CURL_EXTERN_SYMBOL
-#else
-# define LIBHOSTNAME_EXTERN
-#endif
-
-#ifdef USE_WINSOCK
-# define FUNCALLCONV __stdcall
-#else
-# define FUNCALLCONV
-#endif
-
-LIBHOSTNAME_EXTERN int FUNCALLCONV
- gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen);
diff --git a/tests/libtest/stub_gssapi.c b/tests/libtest/stub_gssapi.c
index 634dddfd0..d581a91d5 100644
--- a/tests/libtest/stub_gssapi.c
+++ b/tests/libtest/stub_gssapi.c
@@ -91,8 +91,8 @@ OM_uint32 gss_init_sec_context(OM_uint32 *min,
OM_uint32 *time_rec)
{
/* The token will be encoded in base64 */
- int length = APPROX_TOKEN_LEN * 3 / 4;
- int used = 0;
+ size_t length = APPROX_TOKEN_LEN * 3 / 4;
+ size_t used = 0;
char *token = NULL;
const char *creds = NULL;
gss_ctx_id_t ctx = NULL;
@@ -183,7 +183,7 @@ OM_uint32 gss_init_sec_context(OM_uint32 *min,
return GSS_S_FAILURE;
}
- ctx = (gss_ctx_id_t) calloc(sizeof(*ctx), 1);
+ ctx = (gss_ctx_id_t) calloc(1, sizeof(*ctx));
if(!ctx) {
*min = GSS_NO_MEMORY;
return GSS_S_FAILURE;
@@ -219,8 +219,8 @@ OM_uint32 gss_init_sec_context(OM_uint32 *min,
/* Token format: creds:target:type:padding */
/* Note: this is using the *real* snprintf() and not the curl provided
one */
- used = snprintf(token, length, "%s:%s:%d:", creds,
- (char *) target_name, ctx->sent);
+ used = (size_t) snprintf(token, length, "%s:%s:%d:", creds,
+ (char *) target_name, ctx->sent);
if(used >= length) {
free(token);
diff --git a/tests/libtest/test.h b/tests/libtest/test.h
index 7eb7fdaa2..7f29db117 100644
--- a/tests/libtest/test.h
+++ b/tests/libtest/test.h
@@ -42,7 +42,7 @@
#include "curl_printf.h"
-#ifdef WIN32
+#ifdef _WIN32
#define sleep(sec) Sleep ((sec)*1000)
#endif
diff --git a/tests/libtest/test613.pl b/tests/libtest/test613.pl
index 3ad7805af..dee3b1754 100755
--- a/tests/libtest/test613.pl
+++ b/tests/libtest/test613.pl
@@ -81,7 +81,7 @@ elsif ($ARGV[0] eq "postprocess")
rmdir $dirname || die "$!";
- if ($logfile) {
+ if ($logfile && -s $logfile) {
# Process the directory file to remove all information that
# could be inconsistent from one test run to the next (e.g.
# file date) or may be unsupported on some platforms (e.g.
diff --git a/tests/libtest/testtrace.c b/tests/libtest/testtrace.c
index f78a9b943..49ff8ae20 100644
--- a/tests/libtest/testtrace.c
+++ b/tests/libtest/testtrace.c
@@ -117,10 +117,7 @@ int libtest_debug_cb(CURL *handle, curl_infotype type,
switch(type) {
case CURLINFO_TEXT:
fprintf(stderr, "%s== Info: %s", timestr, (char *)data);
- /* FALLTHROUGH */
- default: /* in case a new one is introduced to shock us */
return 0;
-
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
@@ -139,6 +136,8 @@ int libtest_debug_cb(CURL *handle, curl_infotype type,
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
+ default: /* in case a new one is introduced to shock us */
+ return 0;
}
libtest_debug_dump(timebuf, text, stderr, data, size, trace_cfg->nohex);
diff --git a/tests/libtest/testutil.c b/tests/libtest/testutil.c
index 1a1e689e7..efbbf9019 100644
--- a/tests/libtest/testutil.c
+++ b/tests/libtest/testutil.c
@@ -26,7 +26,7 @@
#include "testutil.h"
#include "memdebug.h"
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32)
struct timeval tutil_tvnow(void)
{
@@ -37,8 +37,8 @@ struct timeval tutil_tvnow(void)
*/
struct timeval now;
DWORD milliseconds = GetTickCount();
- now.tv_sec = milliseconds / 1000;
- now.tv_usec = (milliseconds % 1000) * 1000;
+ now.tv_sec = (long)(milliseconds / 1000);
+ now.tv_usec = (long)((milliseconds % 1000) * 1000);
return now;
}
@@ -130,7 +130,7 @@ double tutil_tvdiff_secs(struct timeval newer, struct timeval older)
return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
}
-#ifdef WIN32
+#ifdef _WIN32
HMODULE win32_load_system_library(const TCHAR *filename)
{
size_t filenamelen = _tcslen(filename);
diff --git a/tests/libtest/testutil.h b/tests/libtest/testutil.h
index 36b944834..9f063795a 100644
--- a/tests/libtest/testutil.h
+++ b/tests/libtest/testutil.h
@@ -42,7 +42,7 @@ long tutil_tvdiff(struct timeval t1, struct timeval t2);
*/
double tutil_tvdiff_secs(struct timeval t1, struct timeval t2);
-#ifdef WIN32
+#ifdef _WIN32
HMODULE win32_load_system_library(const TCHAR *filename);
#endif
diff --git a/tests/manpage-scan.pl b/tests/manpage-scan.pl
deleted file mode 100755
index c09e979d0..000000000
--- a/tests/manpage-scan.pl
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-#
-# Scan symbols-in-version (which is verified to be correct by test 1119), then
-# verify that each option mention in there that should have its own man page
-# actually does.
-#
-# In addition, make sure that every current option to curl_easy_setopt,
-# curl_easy_getinfo and curl_multi_setopt are also mentioned in their
-# corresponding main (index) man page.
-#
-# src/tool_getparam.c lists all options curl can parse
-# docs/curl.1 documents all command line options
-# src/tool_listhelp.c outputs all options with curl -h
-# - make sure they're all in sync
-#
-# Output all deviances to stderr.
-
-use strict;
-use warnings;
-
-# we may get the dir roots pointed out
-my $root=$ARGV[0] || ".";
-my $buildroot=$ARGV[1] || ".";
-my $syms = "$root/docs/libcurl/symbols-in-versions";
-my $curlh = "$root/include/curl/curl.h";
-my $errors=0;
-
-# the prepopulated alias list is the CURLINFO_* defines that are used for the
-# debug function callback and the fact that they use the same prefix as the
-# curl_easy_getinfo options was a mistake.
-my %alias = (
- 'CURLINFO_DATA_IN' => 'none',
- 'CURLINFO_DATA_OUT' => 'none',
- 'CURLINFO_END' => 'none',
- 'CURLINFO_HEADER_IN' => 'none',
- 'CURLINFO_HEADER_OUT' => 'none',
- 'CURLINFO_LASTONE' => 'none',
- 'CURLINFO_NONE' => 'none',
- 'CURLINFO_SSL_DATA_IN' => 'none',
- 'CURLINFO_SSL_DATA_OUT' => 'none',
- 'CURLINFO_TEXT' => 'none'
- );
-
-sub scanmanpage {
- my ($file, @words) = @_;
-
- open(my $mh, "<", "$file");
- my @m;
- while(<$mh>) {
- if($_ =~ /^\.IP (.*)/) {
- my $w = $1;
- # "unquote" minuses
- $w =~ s/\\-/-/g;
- push @m, $w;
- }
- }
- close($mh);
-
- foreach my $m (@words) {
- my @g = grep(/$m/, @m);
- if(!$g[0]) {
- print STDERR "Missing mention of $m in $file\n";
- $errors++;
- }
- }
-}
-
-my $r;
-
-# check for define aliases
-open($r, "<", "$curlh") ||
- die "no curl.h";
-while(<$r>) {
- if(/^\#define (CURL(OPT|INFO|MOPT)_\w+) (.*)/) {
- $alias{$1}=$3;
- }
-}
-close($r);
-
-my @curlopt;
-my @curlinfo;
-my @curlmopt;
-open($r, "<", "$syms") ||
- die "no input file";
-while(<$r>) {
- chomp;
- my $l= $_;
- if($l =~ /(CURL(OPT|INFO|MOPT)_\w+) *([0-9.]*) *([0-9.-]*) *([0-9.]*)/) {
- my ($opt, $type, $add, $dep, $rem) = ($1, $2, $3, $4, $5);
-
- if($alias{$opt}) {
- #print "$opt => $alias{$opt}\n";
- }
- elsif($rem) {
- # $opt was removed in $rem
- # so don't check for that
- }
- else {
- if($type eq "OPT") {
- push @curlopt, $opt,
- }
- elsif($type eq "INFO") {
- push @curlinfo, $opt,
- }
- elsif($type eq "MOPT") {
- push @curlmopt, $opt,
- }
- if(! -f "$root/docs/libcurl/opts/$opt.3") {
- print STDERR "Missing $opt.3\n";
- $errors++;
- }
- }
- }
-}
-close($r);
-
-scanmanpage("$root/docs/libcurl/curl_easy_setopt.3", @curlopt);
-scanmanpage("$root/docs/libcurl/curl_easy_getinfo.3", @curlinfo);
-scanmanpage("$root/docs/libcurl/curl_multi_setopt.3", @curlmopt);
-
-# using this hash array, we can skip specific options
-my %opts = (
- # pretend these --no options exists in tool_getparam.c
- '--no-alpn' => 1,
- '--no-npn' => 1,
- '-N, --no-buffer' => 1,
- '--no-sessionid' => 1,
- '--no-keepalive' => 1,
- '--no-progress-meter' => 1,
- '--no-clobber' => 1,
-
- # pretend these options without -no exist in curl.1 and tool_listhelp.c
- '--alpn' => 6,
- '--npn' => 6,
- '--eprt' => 6,
- '--epsv' => 6,
- '--keepalive' => 6,
- '-N, --buffer' => 6,
- '--sessionid' => 6,
- '--progress-meter' => 6,
- '--clobber' => 6,
-
- # deprecated options do not need to be in tool_help.c nor curl.1
- '--krb4' => 6,
- '--ftp-ssl' => 6,
- '--ftp-ssl-reqd' => 6,
-
- # for tests and debug only, can remain hidden
- '--test-event' => 6,
- '--wdebug' => 6,
- );
-
-
-#########################################################################
-# parse the curl code that parses the command line arguments!
-open($r, "<", "$root/src/tool_getparam.c") ||
- die "no input file";
-my $list;
-my @getparam; # store all parsed parameters
-
-while(<$r>) {
- chomp;
- my $l= $_;
- if(/struct LongShort aliases/) {
- $list=1;
- }
- elsif($list) {
- if( /^ \{([^,]*), *([^ ]*)/) {
- my ($s, $l)=($1, $2);
- my $sh;
- my $lo;
- my $title;
- if($l =~ /\"(.*)\"/) {
- # long option
- $lo = $1;
- $title="--$lo";
- }
- if($s =~ /\"(.)\"/) {
- # a short option
- $sh = $1;
- $title="-$sh, $title";
- }
- push @getparam, $title;
- $opts{$title} |= 1;
- }
- }
-}
-close($r);
-
-#########################################################################
-# parse the curl.1 man page, extract all documented command line options
-# The man page may or may not be rebuilt, so check both possible locations
-open($r, "<", "$buildroot/docs/curl.1") || open($r, "<", "$root/docs/curl.1") ||
- die "no input file";
-my @manpage; # store all parsed parameters
-while(<$r>) {
- chomp;
- my $l= $_;
- $l =~ s/\\-/-/g;
- if($l =~ /^\.IP \"(-[^\"]*)\"/) {
- my $str = $1;
- my $combo;
- if($str =~ /^-(.), --([a-z0-9.-]*)/) {
- # figure out the -short, --long combo
- $combo = "-$1, --$2";
- }
- elsif($str =~ /^--([a-z0-9.-]*)/) {
- # figure out the --long name
- $combo = "--$1";
- }
- if($combo) {
- push @manpage, $combo;
- $opts{$combo} |= 2;
- }
- }
-}
-close($r);
-
-
-#########################################################################
-# parse the curl code that outputs the curl -h list
-open($r, "<", "$root/src/tool_listhelp.c") ||
- die "no input file";
-my @toolhelp; # store all parsed parameters
-while(<$r>) {
- chomp;
- my $l= $_;
- if(/^ \{\" *(.*)/) {
- my $str=$1;
- my $combo;
- if($str =~ /^-(.), --([a-z0-9.-]*)/) {
- # figure out the -short, --long combo
- $combo = "-$1, --$2";
- }
- elsif($str =~ /^--([a-z0-9.-]*)/) {
- # figure out the --long name
- $combo = "--$1";
- }
- if($combo) {
- push @toolhelp, $combo;
- $opts{$combo} |= 4;
- }
-
- }
-}
-close($r);
-
-#
-# Now we have three arrays with options to cross-reference.
-
-foreach my $o (keys %opts) {
- my $where = $opts{$o};
-
- if($where != 7) {
- # this is not in all three places
- $errors++;
- my $exists;
- my $missing;
- if($where & 1) {
- $exists=" tool_getparam.c";
- }
- else {
- $missing=" tool_getparam.c";
- }
- if($where & 2) {
- $exists.= " curl.1";
- }
- else {
- $missing.= " curl.1";
- }
- if($where & 4) {
- $exists .= " tool_listhelp.c";
- }
- else {
- $missing .= " tool_listhelp.c";
- }
-
- print STDERR "$o is not in$missing (but in$exists)\n";
- }
-}
-
-print STDERR "$errors\n";
diff --git a/tests/markdown-uppercase.pl b/tests/markdown-uppercase.pl
deleted file mode 100755
index 707f286cc..000000000
--- a/tests/markdown-uppercase.pl
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-
-my $root=$ARGV[0] || "..";
-
-my @m = `git ls-files -- $root`;
-
-my $errors;
-
-my %accepted=('curl' => 1,
- 'libcurl' => 1);
-
-sub checkfile {
- my ($f) = @_;
- chomp $f;
- if($f !~ /\.md\z/) {
- return;
- }
- open(my $fh, "<", "$f");
- my $l = 1;
- my $prevl;
- my $ignore = 0;
- while(<$fh>) {
- my $line = $_;
- chomp $line;
- if($line =~ /^(\`\`\`|\~\~\~)/) {
- # start or stop ignore-mode
- $ignore ^= 1;
- }
- if(!$ignore) {
- if(($prevl =~ /\.\z/) && ($line =~ /^( *)([a-z]+)/)) {
- my ($prefix, $word) = ($1, $2);
- if(!$accepted{$word}) {
- my $c = length($prefix);
- print STDERR
- "$f:$l:$c:error: lowercase $word after period\n";
- print STDERR "$line\n";
- print STDERR ' ' x $c;
- print STDERR "^\n";
- $errors++;
- }
- }
- elsif($line =~ /^(.*)\. +([a-z]+)/) {
- my ($prefix, $word) = ($1, $2);
-
- if(($prefix =~ /\.\.\z/) ||
- ($prefix =~ /[0-9]\z/) ||
- ($prefix =~ /e.g\z/) ||
- ($prefix =~ /i.e\z/) ||
- ($prefix =~ /etc\z/) ||
- $accepted{$word}) {
- }
- else {
- my $c = length($prefix) + 2;
- print STDERR
- "$f:$l:$c:error: lowercase $word after period\n";
- print STDERR "$line\n";
- print STDERR ' ' x $c;
- print STDERR "^\n";
- $errors++;
- }
- }
- }
- $prevl = $line;
- $l++;
- }
- close($fh);
-}
-
-
-for my $f (@m) {
- checkfile($f);
-}
-
-if($errors) {
- exit 1;
-}
-print "ok\n";
diff --git a/tests/nroff-scan.pl b/tests/nroff-scan.pl
deleted file mode 100755
index 4dddf7cf1..000000000
--- a/tests/nroff-scan.pl
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-#
-# scan nroff pages to find basic syntactic problems such as unbalanced \f
-# codes or references to non-existing curl man pages.
-
-my $docsroot = $ARGV[0];
-
-if(!$docsroot || ($docsroot eq "-g")) {
- print "Usage: nroff-scan.pl <docs root dir> [nroff files]\n";
- exit;
-}
-
-
-shift @ARGV;
-
-my @f = @ARGV;
-
-my %manp;
-
-sub manpresent {
- my ($man) = @_;
- if($manp{$man}) {
- return 1;
- }
- elsif(-r "$docsroot/$man" ||
- -r "$docsroot/libcurl/$man" ||
- -r "$docsroot/libcurl/opts/$man") {
- $manp{$man}=1;
- return 1;
- }
- return 0;
-}
-
-sub file {
- my ($f) = @_;
- open(my $fh, "<", "$f") ||
- die "no file";
- my $line = 1;
- while(<$fh>) {
- chomp;
- my $l = $_;
- while($l =~ s/\\f(.)([^ ]*)\\f(.)//) {
- my ($pre, $str, $post)=($1, $2, $3);
- if($str =~ /^\\f[ib]/i) {
- print "error: $f:$line: double-highlight\n";
- $errors++;
- }
- if($post ne "P") {
- print "error: $f:$line: missing \\fP after $str\n";
- $errors++;
- }
- if($str =~ /((libcurl|curl)([^ ]*))\(3\)/i) {
- my $man = "$1.3";
- if(!manpresent($man)) {
- print "error: $f:$line: referring to non-existing man page $man\n";
- $errors++;
- }
- if($pre ne "I") {
- print "error: $f:$line: use \\fI before $str\n";
- $errors++;
- }
- }
- }
- if($l =~ /(curl([^ ]*)\(3\))/i) {
- print "error: $f:$line: non-referencing $1\n";
- $errors++;
- }
- if($l =~ /^\.BR (.*)/) {
- my $i= $1;
- while($i =~ s/((lib|)curl([^ ]*)) *\"\(3\)(,|) *\" *//i ) {
- my $man = "$1.3";
- if(!manpresent($man)) {
- print "error: $f:$line: referring to non-existing man page $man\n";
- $errors++;
- }
- }
- }
- $line++;
- }
- close($fh);
-}
-
-foreach my $f (@f) {
- file($f);
-}
-
-print "OK\n" if(!$errors);
-
-exit $errors?1:0;
diff --git a/tests/options-scan.pl b/tests/options-scan.pl
deleted file mode 100755
index 2014dc4f6..000000000
--- a/tests/options-scan.pl
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-#
-#
-# - Get all options mentioned in the $cmddir.
-# - Make sure they're all mentioned in the $opts document
-# - Make sure 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(my $fh, "<", "$f");
- while(<$fh>) {
- 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;
- }
- }
- close($fh);
- return @options;
-}
-
-sub versioncheck {
- my ($f, $v)=@_;
- open(my $fh, "<", "$cmddir/$f.d");
- while(<$fh>) {
- chomp;
- if(/^Added: ([0-9.]+)/) {
- if($1 ne $v) {
- print STDERR "$f lists $v in doc but $1 in file\n";
- $error++;
- }
- last;
- }
- }
- close($fh);
-}
-
-# 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 option directory but not in $opts!\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++;
- }
-}
-
-print STDERR "ok\n" if(!$error);
-
-exit $error;
diff --git a/tests/pathhelp.pm b/tests/pathhelp.pm
index 7d924b862..3afc5dacb 100644
--- a/tests/pathhelp.pm
+++ b/tests/pathhelp.pm
@@ -789,6 +789,7 @@ sub exe_ext {
$^O eq 'dos' || $^O eq 'os2') {
return '.exe';
}
+ return '';
}
1; # End of module
diff --git a/tests/runner.pm b/tests/runner.pm
index 8b61eb4b3..c0fb40cb3 100644
--- a/tests/runner.pm
+++ b/tests/runner.pm
@@ -115,7 +115,7 @@ our $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
our $valgrind_logfile="--log-file"; # the option name for valgrind >=3
our $valgrind_tool="--tool=memcheck";
our $gdb = checktestcmd("gdb");
-our $gdbthis; # run test case with gdb debugger
+our $gdbthis = 0; # run test case with debugger (gdb or lldb)
our $gdbxwin; # use windowed gdb when using gdb
# torture test variables
@@ -945,9 +945,16 @@ sub singletest_run {
if($gdbthis) {
my $gdbinit = "$TESTDIR/gdbinit$testnum";
open(my $gdbcmd, ">", "$LOGDIR/gdbcmd") || die "Failure writing gdb file";
- print $gdbcmd "set args $cmdargs\n";
- print $gdbcmd "show args\n";
- print $gdbcmd "source $gdbinit\n" if -e $gdbinit;
+ if($gdbthis == 1) {
+ # gdb mode
+ print $gdbcmd "set args $cmdargs\n";
+ print $gdbcmd "show args\n";
+ print $gdbcmd "source $gdbinit\n" if -e $gdbinit;
+ }
+ else {
+ # lldb mode
+ print $gdbcmd "set args $cmdargs\n";
+ }
close($gdbcmd) || die "Failure writing gdb file";
}
@@ -963,11 +970,18 @@ sub singletest_run {
$testnum,
"$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " -x $LOGDIR/gdbcmd");
}
- elsif($gdbthis) {
+ elsif($gdbthis == 1) {
+ # gdb
my $GDBW = ($gdbxwin) ? "-w" : "";
runclient("$gdb --directory $LIBDIR " . shell_quote($DBGCURL) . " $GDBW -x $LOGDIR/gdbcmd");
$cmdres=0; # makes it always continue after a debugged run
}
+ elsif($gdbthis == 2) {
+ # $gdb is "lldb"
+ print "runs lldb -- $CURL $cmdargs\n";
+ runclient("lldb -- $CURL $cmdargs");
+ $cmdres=0; # makes it always continue after a debugged run
+ }
else {
# Convert the raw result code into a more useful one
($cmdres, $dumped_core) = normalize_cmdres(runclient("$CMDLINE"));
diff --git a/tests/runtests.1 b/tests/runtests.1
index 571e5ce06..01d490b2c 100644
--- a/tests/runtests.1
+++ b/tests/runtests.1
@@ -53,6 +53,35 @@ this keyword. Remember that the exclamation marks and spaces will need to be
quoted somehow when entered at many command shells.
Prefix a keyword with a tilde (~) to still run it, but ignore the results.
+
+.SH "OUTPUT"
+
+When running without -s (short output), for instance when running runtests.pl
+directly rather than via make, each test will emits a pair of lines like this:
+
+Test 0045...[simple HTTP Location: without protocol in initial URL]
+--pd---e-v- OK (45 out of 1427, remaining: 16:08, took 6.188s, duration: 00:31)
+
+the first line contains the test number and a description. On the second line,
+the characters at the beginning are flags indicating which aspects of curl's
+behavior were checked by the test:
+
+ s stdout
+ r stderr
+ p protocol
+ d data
+ u upload
+ P proxy
+ o output
+ e exit code
+ m memory
+ v valgrind
+ E the test was run event-based
+
+The remainder of the second line contains the test result, current test sequence,
+total number of tests to be run and an estimated amount of time to complete the
+test run.
+
.SH OPTIONS
.IP "-a"
Continue running the rest of the test cases even if one test fails. By
@@ -87,13 +116,15 @@ Run the given test(s) with gdb. This is best used on a single test case and
curl built --disable-shared. This then fires up gdb with command line set to
run the specified test case. Simply (set a break-point and) type 'run' to
start.
+.IP "-gl"
+Run the given test(s) with lldb. This is best used on a single test case and
+curl built --disable-shared. This then fires up lldb with command line set to
+run the specified test case. Simply (set a break-point and) type 'run' to
+start.
.IP "-gw"
Run the given test(s) with gdb as a windowed application.
.IP "-h, --help"
Displays a help text about this program's command line options.
-.IP "-k"
-Keep output and log files in log/ after a test run, even if no error was
-detected. Useful for debugging.
.IP "-j[num]"
Spawn num processes to run tests. This defaults to 0 to run tests serially
within a single process. Using a number greater than one allows multiple tests
@@ -101,6 +132,9 @@ to run in parallel, speeding up a test run. The optimum number is dependent on
the system and set of tests to run, but 7*number of CPU cores is a good figure
to start with, or 1.3*number of CPU cores if Valgrind is in use. Enabling
parallel tests is not recommended in conjunction with the \-g option.
+.IP "-k"
+Keep output and log files in log/ after a test run, even if no error was
+detected. Useful for debugging.
.IP "-L <file>"
Load and execute the specified file which should contain perl code.
This option allows one to change \fIruntests.pl\fP behaviour by overwriting
diff --git a/tests/runtests.pl b/tests/runtests.pl
index 32e068037..17b0d3986 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -23,6 +23,8 @@
#
###########################################################################
+# For documentation, run `man ./runtests.1` and see README.md.
+
# Experimental hooks are available to run tests remotely on machines that
# are able to run curl but are unable to run the test harness.
# The following sections need to be modified:
@@ -1233,6 +1235,8 @@ sub singletest_check {
# text mode when running on windows: fix line endings
s/\r\n/\n/g for @validstdout;
s/\n/\r\n/g for @validstdout;
+ s/\r\n/\n/g for @actual;
+ s/\n/\r\n/g for @actual;
}
if($hash{'nonewline'}) {
@@ -1503,7 +1507,7 @@ sub singletest_check {
}
else {
- $ok .= "-"; # protocol not checked
+ $ok .= "-"; # proxy not checked
}
my $outputok;
@@ -2213,6 +2217,10 @@ while(@ARGV) {
# run this test with gdb
$gdbthis=1;
}
+ elsif ($ARGV[0] eq "-gl") {
+ # run this test with lldb
+ $gdbthis=2;
+ }
elsif ($ARGV[0] eq "-gw") {
# run this test with windowed gdb
$gdbthis=1;
diff --git a/tests/server/getpart.c b/tests/server/getpart.c
index 7d3bff75a..9ab9e88d5 100644
--- a/tests/server/getpart.c
+++ b/tests/server/getpart.c
@@ -60,7 +60,7 @@ curl_free_callback Curl_cfree = (curl_free_callback)free;
curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
-#if defined(WIN32) && defined(UNICODE)
+#if defined(_WIN32) && defined(UNICODE)
curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
#endif
@@ -149,7 +149,7 @@ static int readline(char **buffer, size_t *bufsize, size_t *length,
char *newptr;
if(!*buffer) {
- *buffer = calloc(128, 1);
+ *buffer = calloc(1, 128);
if(!*buffer)
return GPE_OUT_OF_MEMORY;
*bufsize = 128;
diff --git a/tests/server/mqttd.c b/tests/server/mqttd.c
index 55ef02cdb..38918a065 100644
--- a/tests/server/mqttd.c
+++ b/tests/server/mqttd.c
@@ -98,7 +98,6 @@
#define MQTT_CONNACK_LEN 4
#define MQTT_SUBACK_LEN 5
#define MQTT_CLIENTID_LEN 12 /* "curl0123abcd" */
-#define MQTT_HEADER_LEN 5 /* max 5 bytes */
struct configurable {
unsigned char version; /* initial version byte in the request must match
@@ -247,7 +246,7 @@ static int connack(FILE *dump, curl_socket_t fd)
rc = swrite(fd, (char *)packet, sizeof(packet));
if(rc > 0) {
- logmsg("WROTE %d bytes [CONNACK]", rc);
+ logmsg("WROTE %zd bytes [CONNACK]", rc);
loghex(packet, rc);
logprotocol(FROM_SERVER, "CONNACK", 2, dump, packet, sizeof(packet));
}
@@ -271,7 +270,7 @@ static int suback(FILE *dump, curl_socket_t fd, unsigned short packetid)
rc = swrite(fd, (char *)packet, sizeof(packet));
if(rc == sizeof(packet)) {
- logmsg("WROTE %d bytes [SUBACK]", rc);
+ logmsg("WROTE %zd bytes [SUBACK]", rc);
loghex(packet, rc);
logprotocol(FROM_SERVER, "SUBACK", 3, dump, packet, rc);
return 0;
@@ -293,7 +292,7 @@ static int puback(FILE *dump, curl_socket_t fd, unsigned short packetid)
rc = swrite(fd, (char *)packet, sizeof(packet));
if(rc == sizeof(packet)) {
- logmsg("WROTE %d bytes [PUBACK]", rc);
+ logmsg("WROTE %zd bytes [PUBACK]", rc);
loghex(packet, rc);
logprotocol(FROM_SERVER, dump, packet, rc);
return 0;
@@ -311,7 +310,7 @@ static int disconnect(FILE *dump, curl_socket_t fd)
};
ssize_t rc = swrite(fd, (char *)packet, sizeof(packet));
if(rc == sizeof(packet)) {
- logmsg("WROTE %d bytes [DISCONNECT]", rc);
+ logmsg("WROTE %zd bytes [DISCONNECT]", rc);
loghex(packet, rc);
logprotocol(FROM_SERVER, "DISCONNECT", 0, dump, packet, rc);
return 0;
@@ -440,7 +439,7 @@ static int publish(FILE *dump,
rc = swrite(fd, (char *)packet, sendamount);
if(rc > 0) {
- logmsg("WROTE %d bytes [PUBLISH]", rc);
+ logmsg("WROTE %zd bytes [PUBLISH]", rc);
loghex(packet, rc);
logprotocol(FROM_SERVER, "PUBLISH", remaininglength, dump, packet, rc);
}
@@ -466,10 +465,10 @@ static int fixedheader(curl_socket_t fd,
ssize_t rc = sread(fd, (char *)buffer, 2);
int i;
if(rc < 2) {
- logmsg("READ %d bytes [SHORT!]", rc);
+ logmsg("READ %zd bytes [SHORT!]", rc);
return 1; /* fail */
}
- logmsg("READ %d bytes", rc);
+ logmsg("READ %zd bytes", rc);
loghex(buffer, rc);
*bytep = buffer[0];
@@ -484,7 +483,7 @@ static int fixedheader(curl_socket_t fd,
}
}
*remaining_lengthp = decode_length(&buffer[1], i, remaining_length_bytesp);
- logmsg("Remaining Length: %ld [%d bytes]", (long) *remaining_lengthp,
+ logmsg("Remaining Length: %zu [%zu bytes]", *remaining_lengthp,
*remaining_length_bytesp);
return 0;
}
@@ -498,7 +497,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
unsigned short packet_id;
size_t payload_len;
size_t client_id_length;
- unsigned int topic_len;
+ size_t topic_len;
size_t remaining_length = 0;
size_t bytes = 0; /* remaining length field size in bytes */
char client_id[MAX_CLIENT_ID_LENGTH];
@@ -547,7 +546,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
buff_size = remaining_length;
buffer = realloc(buffer, buff_size);
if(!buffer) {
- logmsg("Failed realloc of size %lu", buff_size);
+ logmsg("Failed realloc of size %zu", buff_size);
goto end;
}
}
@@ -556,7 +555,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
/* reading variable header and payload into buffer */
rc = sread(fd, (char *)buffer, remaining_length);
if(rc > 0) {
- logmsg("READ %d bytes", rc);
+ logmsg("READ %zd bytes", rc);
loghex(buffer, rc);
}
}
@@ -570,7 +569,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
goto end;
}
/* ignore the connect flag byte and two keepalive bytes */
- payload_len = (buffer[10] << 8) | buffer[11];
+ payload_len = (size_t)(buffer[10] << 8) | buffer[11];
/* first part of the payload is the client ID */
client_id_length = payload_len;
@@ -580,20 +579,22 @@ static curl_socket_t mqttit(curl_socket_t fd)
start_usr = client_id_offset + payload_len;
if(usr_flag == (unsigned char)(conn_flags & usr_flag)) {
logmsg("User flag is present in CONN flag");
- payload_len += (buffer[start_usr] << 8) | buffer[start_usr + 1];
+ payload_len += (size_t)(buffer[start_usr] << 8) |
+ buffer[start_usr + 1];
payload_len += 2; /* MSB and LSB for user length */
}
start_passwd = client_id_offset + payload_len;
if(passwd_flag == (char)(conn_flags & passwd_flag)) {
logmsg("Password flag is present in CONN flags");
- payload_len += (buffer[start_passwd] << 8) | buffer[start_passwd + 1];
+ payload_len += (size_t)(buffer[start_passwd] << 8) |
+ buffer[start_passwd + 1];
payload_len += 2; /* MSB and LSB for password length */
}
/* check the length of the payload */
if((ssize_t)payload_len != (rc - 12)) {
- logmsg("Payload length mismatch, expected %x got %x",
+ logmsg("Payload length mismatch, expected %zx got %zx",
rc - 12, payload_len);
goto end;
}
@@ -632,9 +633,9 @@ static curl_socket_t mqttit(curl_socket_t fd)
packet_id = (unsigned short)((buffer[0] << 8) | buffer[1]);
/* two bytes topic length */
- topic_len = (buffer[2] << 8) | buffer[3];
+ topic_len = (size_t)(buffer[2] << 8) | buffer[3];
if(topic_len != (remaining_length - 5)) {
- logmsg("Wrong topic length, got %d expected %d",
+ logmsg("Wrong topic length, got %zu expected %zu",
topic_len, remaining_length - 5);
goto end;
}
@@ -677,8 +678,8 @@ static curl_socket_t mqttit(curl_socket_t fd)
logprotocol(FROM_CLIENT, "PUBLISH", remaining_length,
dump, buffer, rc);
- topiclen = (buffer[1 + bytes] << 8) | buffer[2 + bytes];
- logmsg("Got %d bytes topic", topiclen);
+ topiclen = (size_t)(buffer[1 + bytes] << 8) | buffer[2 + bytes];
+ logmsg("Got %zu bytes topic", topiclen);
/* TODO: verify topiclen */
#ifdef QOS
@@ -689,7 +690,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
/* get the request */
rc = sread(fd, (char *)&buffer[0], 2);
- logmsg("READ %d bytes [DISCONNECT]", rc);
+ logmsg("READ %zd bytes [DISCONNECT]", rc);
loghex(buffer, rc);
logprotocol(FROM_CLIENT, "DISCONNECT", 0, dump, buffer, rc);
goto end;
@@ -768,12 +769,12 @@ static bool incoming(curl_socket_t listenfd)
curl_socket_t newfd = accept(sockfd, NULL, NULL);
if(CURL_SOCKET_BAD == newfd) {
error = SOCKERRNO;
- logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
- sockfd, error, sstrerror(error));
+ logmsg("accept(%" CURL_FORMAT_SOCKET_T ", NULL, NULL) "
+ "failed with error: (%d) %s", sockfd, error, sstrerror(error));
}
else {
- logmsg("====> Client connect, fd %d. Read config from %s",
- newfd, configfile);
+ logmsg("====> Client connect, fd %" CURL_FORMAT_SOCKET_T ". "
+ "Read config from %s", newfd, configfile);
set_advisor_read_lock(loglockfile);
(void)mqttit(newfd); /* until done */
clear_advisor_read_lock(loglockfile);
@@ -911,7 +912,7 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
rc = listen(sock, 5);
if(0 != rc) {
error = SOCKERRNO;
- logmsg("listen(%d, 5) failed with error: (%d) %s",
+ logmsg("listen(%" CURL_FORMAT_SOCKET_T ", 5) failed with error: (%d) %s",
sock, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
@@ -1017,7 +1018,7 @@ int main(int argc, char *argv[])
msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/mqtt-%s.lock",
logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
-#ifdef WIN32
+#ifdef _WIN32
win32_init();
atexit(win32_cleanup);
diff --git a/tests/server/resolve.c b/tests/server/resolve.c
index 221df64b0..8ae31bc59 100644
--- a/tests/server/resolve.c
+++ b/tests/server/resolve.c
@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
return 1;
}
-#ifdef WIN32
+#ifdef _WIN32
win32_init();
atexit(win32_cleanup);
#endif
diff --git a/tests/server/rtspd.c b/tests/server/rtspd.c
index dbe8a48b0..9c01ce871 100644
--- a/tests/server/rtspd.c
+++ b/tests/server/rtspd.c
@@ -1150,7 +1150,7 @@ int main(int argc, char *argv[])
msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/rtsp-%s.lock",
logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
-#ifdef WIN32
+#ifdef _WIN32
win32_init();
atexit(win32_cleanup);
#endif
diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c
index 7e342e330..0900f6564 100644
--- a/tests/server/sockfilt.c
+++ b/tests/server/sockfilt.c
@@ -152,7 +152,7 @@ enum sockmode {
ACTIVE_DISCONNECT /* as a client, disconnected from server */
};
-#ifdef WIN32
+#ifdef _WIN32
/*
* read-wrapper to support reading from stdin on Windows.
*/
@@ -551,14 +551,14 @@ static unsigned int WINAPI select_ws_wait_thread(void *lpParameter)
continue;
}
else {
- logmsg("[select_ws_wait_thread] PeekNamedPipe len: %d", length);
+ logmsg("[select_ws_wait_thread] PeekNamedPipe len: %lu", length);
}
}
else {
/* if the pipe has NOT been closed, sleep and continue waiting */
ret = GetLastError();
if(ret != ERROR_BROKEN_PIPE) {
- logmsg("[select_ws_wait_thread] PeekNamedPipe error: %d", ret);
+ logmsg("[select_ws_wait_thread] PeekNamedPipe error: %lu", ret);
SleepEx(0, FALSE);
continue;
}
@@ -1159,8 +1159,8 @@ static bool juggle(curl_socket_t *sockfdp,
curl_socket_t newfd = accept(sockfd, NULL, NULL);
if(CURL_SOCKET_BAD == newfd) {
error = SOCKERRNO;
- logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
- sockfd, error, sstrerror(error));
+ logmsg("accept(%" CURL_FORMAT_SOCKET_T ", NULL, NULL) "
+ "failed with error: (%d) %s", sockfd, error, sstrerror(error));
}
else {
logmsg("====> Client connect");
@@ -1335,7 +1335,7 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
rc = listen(sock, 5);
if(0 != rc) {
error = SOCKERRNO;
- logmsg("listen(%d, 5) failed with error: (%d) %s",
+ logmsg("listen(%" CURL_FORMAT_SOCKET_T ", 5) failed with error: (%d) %s",
sock, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
@@ -1461,7 +1461,7 @@ int main(int argc, char *argv[])
}
}
-#ifdef WIN32
+#ifdef _WIN32
win32_init();
atexit(win32_cleanup);
diff --git a/tests/server/socksd.c b/tests/server/socksd.c
index cf9a14fd8..b1d8220a3 100644
--- a/tests/server/socksd.c
+++ b/tests/server/socksd.c
@@ -193,8 +193,8 @@ static void getconfig(void)
logmsg("parse config file");
while(fgets(buffer, sizeof(buffer), fp)) {
char key[32];
- char value[32];
- if(2 == sscanf(buffer, "%31s %31s", key, value)) {
+ char value[260];
+ if(2 == sscanf(buffer, "%31s %259s", key, value)) {
if(!strcmp(key, "version")) {
config.version = byteval(value);
logmsg("version [%d] set", config.version);
@@ -323,7 +323,7 @@ static curl_socket_t socks4(curl_socket_t fd,
return CURL_SOCKET_BAD;
}
if(rc < 9) {
- logmsg("SOCKS4 connect message too short: %d", rc);
+ logmsg("SOCKS4 connect message too short: %zd", rc);
return CURL_SOCKET_BAD;
}
if(!config.port)
@@ -350,7 +350,7 @@ static curl_socket_t socks4(curl_socket_t fd,
logmsg("Sending SOCKS4 response failed!");
return CURL_SOCKET_BAD;
}
- logmsg("Sent %d bytes", rc);
+ logmsg("Sent %zd bytes", rc);
loghex(response, rc);
if(cd == 90)
@@ -365,8 +365,8 @@ static curl_socket_t socks4(curl_socket_t fd,
static curl_socket_t sockit(curl_socket_t fd)
{
- unsigned char buffer[256 + 16];
- unsigned char response[256 + 16];
+ unsigned char buffer[2*256 + 16];
+ unsigned char response[2*256 + 16];
ssize_t rc;
unsigned char len;
unsigned char type;
@@ -379,13 +379,22 @@ static curl_socket_t sockit(curl_socket_t fd)
getconfig();
rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
+ if(rc <= 0) {
+ logmsg("SOCKS identifier message missing, recv returned %zd", rc);
+ return CURL_SOCKET_BAD;
+ }
- logmsg("READ %d bytes", rc);
+ logmsg("READ %zd bytes", rc);
loghex(buffer, rc);
if(buffer[SOCKS5_VERSION] == 4)
return socks4(fd, buffer, rc);
+ if(rc < 3) {
+ logmsg("SOCKS5 identifier message too short: %zd", rc);
+ return CURL_SOCKET_BAD;
+ }
+
if(buffer[SOCKS5_VERSION] != config.version) {
logmsg("VERSION byte not %d", config.version);
return CURL_SOCKET_BAD;
@@ -399,7 +408,7 @@ static curl_socket_t sockit(curl_socket_t fd)
/* after NMETHODS follows that many bytes listing the methods the client
says it supports */
if(rc != (buffer[SOCKS5_NMETHODS] + 2)) {
- logmsg("Expected %d bytes, got %d", buffer[SOCKS5_NMETHODS] + 2, rc);
+ logmsg("Expected %d bytes, got %zd", buffer[SOCKS5_NMETHODS] + 2, rc);
return CURL_SOCKET_BAD;
}
logmsg("Incoming request deemed fine!");
@@ -412,13 +421,17 @@ static curl_socket_t sockit(curl_socket_t fd)
logmsg("Sending response failed!");
return CURL_SOCKET_BAD;
}
- logmsg("Sent %d bytes", rc);
+ logmsg("Sent %zd bytes", rc);
loghex(response, rc);
/* expect the request or auth */
rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
+ if(rc <= 0) {
+ logmsg("SOCKS5 request or auth message missing, recv returned %zd", rc);
+ return CURL_SOCKET_BAD;
+ }
- logmsg("READ %d bytes", rc);
+ logmsg("READ %zd bytes", rc);
loghex(buffer, rc);
if(config.responsemethod == 2) {
@@ -433,7 +446,7 @@ static curl_socket_t sockit(curl_socket_t fd)
unsigned char plen;
bool login = TRUE;
if(rc < 5) {
- logmsg("Too short auth input: %d", rc);
+ logmsg("Too short auth input: %zd", rc);
return CURL_SOCKET_BAD;
}
if(buffer[SOCKS5_VERSION] != 1) {
@@ -442,12 +455,12 @@ static curl_socket_t sockit(curl_socket_t fd)
}
ulen = buffer[SOCKS5_ULEN];
if(rc < 4 + ulen) {
- logmsg("Too short packet for username: %d", rc);
+ logmsg("Too short packet for username: %zd", rc);
return CURL_SOCKET_BAD;
}
plen = buffer[SOCKS5_ULEN + ulen + 1];
if(rc < 3 + ulen + plen) {
- logmsg("Too short packet for ulen %d plen %d: %d", ulen, plen, rc);
+ logmsg("Too short packet for ulen %d plen %d: %zd", ulen, plen, rc);
return CURL_SOCKET_BAD;
}
if((ulen != strlen(config.user)) ||
@@ -465,19 +478,23 @@ static curl_socket_t sockit(curl_socket_t fd)
logmsg("Sending auth response failed!");
return CURL_SOCKET_BAD;
}
- logmsg("Sent %d bytes", rc);
+ logmsg("Sent %zd bytes", rc);
loghex(response, rc);
if(!login)
return CURL_SOCKET_BAD;
/* expect the request */
rc = recv(fd, (char *)buffer, sizeof(buffer), 0);
+ if(rc <= 0) {
+ logmsg("SOCKS5 request message missing, recv returned %zd", rc);
+ return CURL_SOCKET_BAD;
+ }
- logmsg("READ %d bytes", rc);
+ logmsg("READ %zd bytes", rc);
loghex(buffer, rc);
}
if(rc < 6) {
- logmsg("Too short for request: %d", rc);
+ logmsg("Too short for request: %zd", rc);
return CURL_SOCKET_BAD;
}
@@ -522,7 +539,7 @@ static curl_socket_t sockit(curl_socket_t fd)
return CURL_SOCKET_BAD;
}
if(rc < (4 + len + 2)) {
- logmsg("Request too short: %d, expected %d", rc, 4 + len + 2);
+ logmsg("Request too short: %zd, expected %d", rc, 4 + len + 2);
return CURL_SOCKET_BAD;
}
logmsg("Received ATYP %d", type);
@@ -603,12 +620,12 @@ static curl_socket_t sockit(curl_socket_t fd)
memcpy(&response[SOCKS5_BNDADDR + len],
&buffer[SOCKS5_DSTADDR + len], sizeof(socksport));
- rc = (send)(fd, (char *)response, len + 6, 0);
+ rc = (send)(fd, (char *)response, (size_t)(len + 6), 0);
if(rc != (len + 6)) {
logmsg("Sending connect response failed!");
return CURL_SOCKET_BAD;
}
- logmsg("Sent %d bytes", rc);
+ logmsg("Sent %zd bytes", rc);
loghex(response, rc);
if(!rep)
@@ -737,13 +754,14 @@ static bool incoming(curl_socket_t listenfd)
curl_socket_t newfd = accept(sockfd, NULL, NULL);
if(CURL_SOCKET_BAD == newfd) {
error = SOCKERRNO;
- logmsg("accept(%d, NULL, NULL) failed with error: (%d) %s",
+ logmsg("accept(%" CURL_FORMAT_SOCKET_T ", NULL, NULL) "
+ "failed with error: (%d) %s",
sockfd, error, sstrerror(error));
}
else {
curl_socket_t remotefd;
- logmsg("====> Client connect, fd %d. Read config from %s",
- newfd, configfile);
+ logmsg("====> Client connect, fd %" CURL_FORMAT_SOCKET_T ". "
+ "Read config from %s", newfd, configfile);
remotefd = sockit(newfd); /* SOCKS until done */
if(remotefd == CURL_SOCKET_BAD) {
logmsg("====> Client disconnect");
@@ -926,7 +944,7 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
rc = listen(sock, 5);
if(0 != rc) {
error = SOCKERRNO;
- logmsg("listen(%d, 5) failed with error: (%d) %s",
+ logmsg("listen(%" CURL_FORMAT_SOCKET_T ", 5) failed with error: (%d) %s",
sock, error, sstrerror(error));
sclose(sock);
return CURL_SOCKET_BAD;
@@ -1059,7 +1077,7 @@ int main(int argc, char *argv[])
}
}
-#ifdef WIN32
+#ifdef _WIN32
win32_init();
atexit(win32_cleanup);
diff --git a/tests/server/sws.c b/tests/server/sws.c
index bea3191a2..d91258597 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -374,7 +374,7 @@ static int ProcessRequest(struct httprequest *req)
req->callcount++;
- logmsg("Process %d bytes request%s", req->offset,
+ logmsg("Process %zu bytes request%s", req->offset,
req->callcount > 1?" [CONTINUED]":"");
/* try to figure out the request characteristics as soon as possible, but
@@ -557,14 +557,14 @@ static int ProcessRequest(struct httprequest *req)
logmsg("request not complete yet");
return 0; /* not complete yet */
}
- logmsg("- request found to be complete (%d)", req->testno);
+ logmsg("- request found to be complete (%ld)", req->testno);
if(req->testno == DOCNUMBER_NOTHING) {
/* check for a Testno: header with the test case number */
char *testno = strstr(line, "\nTestno: ");
if(testno) {
req->testno = strtol(&testno[9], NULL, 10);
- logmsg("Found test number %d in Testno: header!", req->testno);
+ logmsg("Found test number %ld in Testno: header!", req->testno);
}
else {
logmsg("No Testno: header");
@@ -702,8 +702,8 @@ static int ProcessRequest(struct httprequest *req)
/* Negotiate iterations */
static long prev_testno = -1;
static long prev_partno = -1;
- logmsg("Negotiate: prev_testno: %d, prev_partno: %d",
- prev_testno, prev_partno);
+ logmsg("Negotiate: prev_testno: %ld, prev_partno: %ld",
+ prev_testno, prev_partno);
if(req->testno != prev_testno) {
prev_testno = req->testno;
prev_partno = req->partno;
@@ -1198,8 +1198,8 @@ retry:
int intervals = msecs_left / MAX_SLEEP_TIME_MS;
if(msecs_left%MAX_SLEEP_TIME_MS)
intervals++;
- logmsg("Pausing %d milliseconds after writing %d bytes",
- msecs_left, written);
+ logmsg("Pausing %d milliseconds after writing %zd bytes",
+ msecs_left, written);
while((intervals > 0) && !got_exit_signal) {
int sleep_time = msecs_left > MAX_SLEEP_TIME_MS ?
MAX_SLEEP_TIME_MS : msecs_left;
@@ -2119,7 +2119,7 @@ int main(int argc, char *argv[])
logdir, SERVERLOGS_LOCKDIR, protocol_type,
is_proxy ? "-proxy" : "", socket_type);
-#ifdef WIN32
+#ifdef _WIN32
win32_init();
atexit(win32_cleanup);
#endif
@@ -2334,7 +2334,8 @@ int main(int argc, char *argv[])
curl_socket_t msgsock;
do {
msgsock = accept_connection(sock);
- logmsg("accept_connection %d returned %d", sock, msgsock);
+ logmsg("accept_connection %" CURL_FORMAT_SOCKET_T
+ " returned %" CURL_FORMAT_SOCKET_T, sock, msgsock);
if(CURL_SOCKET_BAD == msgsock)
goto sws_cleanup;
if(req->delay)
diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c
index 670897c0d..9e839eafc 100644
--- a/tests/server/tftpd.c
+++ b/tests/server/tftpd.c
@@ -453,7 +453,7 @@ static ssize_t write_behind(struct testcase *test, int convert)
if(!test->ofile) {
char outfile[256];
msnprintf(outfile, sizeof(outfile), "%s/upload.%ld", logdir, test->testno);
-#ifdef WIN32
+#ifdef _WIN32
test->ofile = open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777);
#else
test->ofile = open(outfile, O_CREAT|O_RDWR, 0777);
@@ -642,7 +642,7 @@ int main(int argc, char **argv)
msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/tftp-%s.lock",
logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
-#ifdef WIN32
+#ifdef _WIN32
win32_init();
atexit(win32_cleanup);
#endif
@@ -1129,7 +1129,7 @@ static int validate_access(struct testcase *test,
if(!stream) {
int error = errno;
logmsg("fopen() failed with error: %d %s", error, strerror(error));
- logmsg("Couldn't open test file for test : %d", testno);
+ logmsg("Couldn't open test file for test: %ld", testno);
return EACCESS;
}
else {
diff --git a/tests/server/util.c b/tests/server/util.c
index 19faa2615..74d6d0807 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -39,9 +39,6 @@
#elif defined(HAVE_SYS_POLL_H)
#include <sys/poll.h>
#endif
-#ifdef __MINGW32__
-#include <w32api.h>
-#endif
#define ENABLE_CURLX_PRINTF
/* make the curlx header define all printf() functions to use the curlx_*
@@ -58,15 +55,6 @@
#define EINVAL 22 /* errno.h value */
#endif
-/* MinGW with w32api version < 3.6 declared in6addr_any as extern,
- but lacked the definition */
-#if defined(ENABLE_IPV6) && defined(__MINGW32__)
-#if (__W32API_MAJOR_VERSION < 3) || \
- ((__W32API_MAJOR_VERSION == 3) && (__W32API_MINOR_VERSION < 6))
-const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
-#endif /* w32api < 3.6 */
-#endif /* ENABLE_IPV6 && __MINGW32__ */
-
static struct timeval tvnow(void);
/* This function returns a pointer to STATIC memory. It converts the given
@@ -144,14 +132,14 @@ void logmsg(const char *msg, ...)
}
}
-#ifdef WIN32
+#ifdef _WIN32
/* use instead of strerror() on generic Windows */
static const char *win32_strerror(int err, char *buf, size_t buflen)
{
if(!FormatMessageA((FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err,
+ FORMAT_MESSAGE_IGNORE_INSERTS), NULL, (DWORD)err,
LANG_NEUTRAL, buf, (DWORD)buflen, NULL))
- msnprintf(buf, buflen, "Unknown error %lu (%#lx)", err, err);
+ msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err);
return buf;
}
@@ -208,7 +196,7 @@ const char *sstrerror(int err)
static char buf[512];
return win32_strerror(err, buf, sizeof(buf));
}
-#endif /* WIN32 */
+#endif /* _WIN32 */
/* set by the main code to point to where the test dir is */
const char *path = ".";
@@ -259,7 +247,7 @@ int wait_ms(int timeout_ms)
#if defined(MSDOS)
delay(timeout_ms);
#elif defined(USE_WINSOCK)
- Sleep(timeout_ms);
+ Sleep((DWORD)timeout_ms);
#else
pending_ms = timeout_ms;
initial_tv = tvnow();
@@ -292,7 +280,7 @@ curl_off_t our_getpid(void)
curl_off_t pid;
pid = (curl_off_t)getpid();
-#if defined(WIN32) || defined(_WIN32)
+#if defined(_WIN32) || defined(_WIN32)
/* store pid + 65536 to avoid conflict with Cygwin/msys PIDs, see also:
* - https://cygwin.com/git/?p=newlib-cygwin.git;a=commit; ↵
* h=b5e1003722cb14235c4f166be72c09acdffc62ea
@@ -378,7 +366,7 @@ void clear_advisor_read_lock(const char *filename)
}
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32) && !defined(MSDOS)
static struct timeval tvnow(void)
{
@@ -501,11 +489,11 @@ static SIGHANDLER_T old_sigint_handler = SIG_ERR;
static SIGHANDLER_T old_sigterm_handler = SIG_ERR;
#endif
-#if defined(SIGBREAK) && defined(WIN32)
+#if defined(SIGBREAK) && defined(_WIN32)
static SIGHANDLER_T old_sigbreak_handler = SIG_ERR;
#endif
-#ifdef WIN32
+#ifdef _WIN32
#ifdef _WIN32_WCE
static DWORD thread_main_id = 0;
#else
@@ -521,7 +509,7 @@ 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
+#ifdef _WIN32
/* event which if set indicates that the program should finish */
HANDLE exit_event = NULL;
#endif
@@ -538,7 +526,7 @@ static void exit_signal_handler(int signum)
if(got_exit_signal == 0) {
got_exit_signal = 1;
exit_signal = signum;
-#ifdef WIN32
+#ifdef _WIN32
if(exit_event)
(void)SetEvent(exit_event);
#endif
@@ -547,7 +535,7 @@ static void exit_signal_handler(int signum)
errno = old_errno;
}
-#ifdef WIN32
+#ifdef _WIN32
/* CTRL event handler for Windows Console applications to simulate
* SIGINT, SIGTERM and SIGBREAK on CTRL events and trigger signal handler.
*
@@ -567,7 +555,7 @@ static void exit_signal_handler(int signum)
static BOOL WINAPI ctrl_event_handler(DWORD dwCtrlType)
{
int signum = 0;
- logmsg("ctrl_event_handler: %d", dwCtrlType);
+ logmsg("ctrl_event_handler: %lu", dwCtrlType);
switch(dwCtrlType) {
#ifdef SIGINT
case CTRL_C_EVENT: signum = SIGINT; break;
@@ -581,7 +569,7 @@ static BOOL WINAPI ctrl_event_handler(DWORD dwCtrlType)
default: return FALSE;
}
if(signum) {
- logmsg("ctrl_event_handler: %d -> %d", dwCtrlType, signum);
+ logmsg("ctrl_event_handler: %lu -> %d", dwCtrlType, signum);
raise(signum);
}
return TRUE;
@@ -698,7 +686,7 @@ static SIGHANDLER_T set_signal(int signum, SIGHANDLER_T handler,
void install_signal_handlers(bool keep_sigalrm)
{
-#ifdef WIN32
+#ifdef _WIN32
#ifdef _WIN32_WCE
typedef HANDLE curl_win_thread_handle_t;
#else
@@ -744,13 +732,13 @@ void install_signal_handlers(bool keep_sigalrm)
if(old_sigterm_handler == SIG_ERR)
logmsg("cannot install SIGTERM handler: %s", strerror(errno));
#endif
-#if defined(SIGBREAK) && defined(WIN32)
+#if defined(SIGBREAK) && defined(_WIN32)
/* handle SIGBREAK signal with our exit_signal_handler */
old_sigbreak_handler = set_signal(SIGBREAK, exit_signal_handler, TRUE);
if(old_sigbreak_handler == SIG_ERR)
logmsg("cannot install SIGBREAK handler: %s", strerror(errno));
#endif
-#ifdef WIN32
+#ifdef _WIN32
if(!SetConsoleCtrlHandler(ctrl_event_handler, TRUE))
logmsg("cannot install CTRL event handler");
#ifdef _WIN32_WCE
@@ -792,11 +780,11 @@ void restore_signal_handlers(bool keep_sigalrm)
if(SIG_ERR != old_sigterm_handler)
(void) set_signal(SIGTERM, old_sigterm_handler, FALSE);
#endif
-#if defined(SIGBREAK) && defined(WIN32)
+#if defined(SIGBREAK) && defined(_WIN32)
if(SIG_ERR != old_sigbreak_handler)
(void) set_signal(SIGBREAK, old_sigbreak_handler, FALSE);
#endif
-#ifdef WIN32
+#ifdef _WIN32
(void)SetConsoleCtrlHandler(ctrl_event_handler, FALSE);
if(thread_main_window && thread_main_id) {
if(PostThreadMessage(thread_main_id, WM_APP, 0, 0)) {
@@ -846,7 +834,7 @@ int bind_unix_socket(curl_socket_t sock, const char *unix_socket,
return rc;
}
/* socket server is not alive, now check if it was actually a socket. */
-#ifdef WIN32
+#ifdef _WIN32
/* Windows does not have lstat function. */
rc = curlx_win32_stat(unix_socket, &statbuf);
#else
diff --git a/tests/server/util.h b/tests/server/util.h
index a12f4dbf0..a91ecf477 100644
--- a/tests/server/util.h
+++ b/tests/server/util.h
@@ -26,7 +26,7 @@
#include "server_setup.h"
char *data_to_hex(char *data, size_t len);
-void logmsg(const char *msg, ...);
+void logmsg(const char *msg, ...) CURL_PRINTF(1, 2);
long timediff(struct timeval newer, struct timeval older);
#define TEST_DATA_PATH "%s/data/test%ld"
@@ -41,7 +41,7 @@ extern const char *serverlogfile;
extern const char *cmdfile;
-#ifdef WIN32
+#ifdef _WIN32
#include <process.h>
#include <fcntl.h>
@@ -54,10 +54,10 @@ void win32_perror(const char *msg);
void win32_init(void);
void win32_cleanup(void);
const char *sstrerror(int err);
-#else /* WIN32 */
+#else /* _WIN32 */
#define sstrerror(e) strerror(e)
-#endif /* WIN32 */
+#endif /* _WIN32 */
/* fopens the test case file */
FILE *test2fopen(long testno, const char *logdir);
@@ -68,7 +68,6 @@ int write_pidfile(const char *filename);
int write_portfile(const char *filename, int port);
void set_advisor_read_lock(const char *filename);
void clear_advisor_read_lock(const char *filename);
-int strncasecompare(const char *first, const char *second, size_t max);
/* global variable which if set indicates that the program should finish */
extern volatile int got_exit_signal;
@@ -76,7 +75,7 @@ extern volatile int got_exit_signal;
/* global variable which if set indicates the first signal handled */
extern volatile int exit_signal;
-#ifdef WIN32
+#ifdef _WIN32
/* global event which if set indicates that the program should finish */
extern HANDLE exit_event;
#endif
diff --git a/tests/servers.pm b/tests/servers.pm
index 4f67432c6..d4472d509 100644
--- a/tests/servers.pm
+++ b/tests/servers.pm
@@ -153,10 +153,15 @@ our $stunnel; # path to stunnel command
#
sub checkcmd {
my ($cmd, @extrapaths)=@_;
- my @paths=(split(m/[:]/, $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
+ my $sep = '[:]';
+ if ($^O eq 'MSWin32' || $^O eq 'dos' || $^O eq 'os2') {
+ # PATH separator is different
+ $sep = '[;]';
+ }
+ my @paths=(split(m/$sep/, $ENV{'PATH'}), "/usr/sbin", "/usr/local/sbin",
"/sbin", "/usr/bin", "/usr/local/bin", @extrapaths);
for(@paths) {
- if( -x "$_/$cmd" && ! -d "$_/$cmd") {
+ if( -x "$_/$cmd" . exe_ext('SYS') && ! -d "$_/$cmd" . exe_ext('SYS')) {
# executable bit but not a directory!
return "$_/$cmd";
}
@@ -185,10 +190,10 @@ use File::Temp qw/ tempfile/;
#######################################################################
# Initialize configuration variables
sub initserverconfig {
- my ($fh, $socks) = tempfile("/tmp/curl-socksd-XXXXXXXX");
+ my ($fh, $socks) = tempfile("curl-socksd-XXXXXXXX", TMPDIR => 1);
close($fh);
unlink($socks);
- my ($f2, $http) = tempfile("/tmp/curl-http-XXXXXXXX");
+ my ($f2, $http) = tempfile("curl-http-XXXXXXXX", TMPDIR => 1);
close($f2);
unlink($http);
$SOCKSUNIXPATH = $socks; # SOCKS Unix domain socket
@@ -264,19 +269,22 @@ sub clearlocks {
if(os_is_win()) {
$dir = sys_native_abs_path($dir);
$dir =~ s/\//\\\\/g;
- my $handle = "handle.exe";
+ my $handle = "handle";
if($ENV{"PROCESSOR_ARCHITECTURE"} =~ /64$/) {
- $handle = "handle64.exe";
+ $handle = "handle64";
}
- my @handles = `$handle $dir -accepteula -nobanner`;
- for my $tryhandle (@handles) {
- if($tryhandle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) {
- logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n";
- # Ignore stunnel since we cannot do anything about its locks
- if("$3" eq "File" && "$1" ne "tstunnel.exe") {
- logmsg "Killing IMAGENAME eq $1 and PID eq $2\n";
- system("taskkill.exe -f -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1");
- $done = 1;
+ if(checkcmd($handle)) {
+ my @handles = `$handle $dir -accepteula -nobanner`;
+ for my $tryhandle (@handles) {
+ # Skip the "No matching handles found." warning when returned
+ if($tryhandle =~ /^(\S+)\s+pid:\s+(\d+)\s+type:\s+(\w+)\s+([0-9A-F]+):\s+(.+)\r\r/) {
+ logmsg "Found $3 lock of '$5' ($4) by $1 ($2)\n";
+ # Ignore stunnel since we cannot do anything about its locks
+ if("$3" eq "File" && "$1" ne "tstunnel.exe") {
+ logmsg "Killing IMAGENAME eq $1 and PID eq $2\n";
+ system("taskkill.exe -f -fi \"IMAGENAME eq $1\" -fi \"PID eq $2\" >nul 2>&1");
+ $done = 1;
+ }
}
}
}
diff --git a/tests/symbol-scan.pl b/tests/test1119.pl
index 2b9ac3759..2b9ac3759 100755
--- a/tests/symbol-scan.pl
+++ b/tests/test1119.pl
diff --git a/tests/mem-include-scan.pl b/tests/test1132.pl
index e808c2e8c..e808c2e8c 100755
--- a/tests/mem-include-scan.pl
+++ b/tests/test1132.pl
diff --git a/tests/extern-scan.pl b/tests/test1135.pl
index d8f46ee3b..d8f46ee3b 100755
--- a/tests/extern-scan.pl
+++ b/tests/test1135.pl
diff --git a/tests/test1139.pl b/tests/test1139.pl
new file mode 100755
index 000000000..c86081431
--- /dev/null
+++ b/tests/test1139.pl
@@ -0,0 +1,312 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+# Scan symbols-in-version (which is verified to be correct by test 1119), then
+# verify that each option mention in there that should have its own man page
+# actually does.
+#
+# In addition, make sure that every current option to curl_easy_setopt,
+# curl_easy_getinfo and curl_multi_setopt are also mentioned in their
+# corresponding main (index) man page.
+#
+# src/tool_getparam.c lists all options curl can parse
+# docs/curl.1 documents all command line options
+# src/tool_listhelp.c outputs all options with curl -h
+# - make sure they're all in sync
+#
+# Output all deviances to stderr.
+
+use strict;
+use warnings;
+
+# we may get the dir roots pointed out
+my $root=$ARGV[0] || ".";
+my $buildroot=$ARGV[1] || ".";
+my $syms = "$root/docs/libcurl/symbols-in-versions";
+my $curlh = "$root/include/curl/curl.h";
+my $errors=0;
+
+# the prepopulated alias list is the CURLINFO_* defines that are used for the
+# debug function callback and the fact that they use the same prefix as the
+# curl_easy_getinfo options was a mistake.
+my %alias = (
+ 'CURLINFO_DATA_IN' => 'none',
+ 'CURLINFO_DATA_OUT' => 'none',
+ 'CURLINFO_END' => 'none',
+ 'CURLINFO_HEADER_IN' => 'none',
+ 'CURLINFO_HEADER_OUT' => 'none',
+ 'CURLINFO_LASTONE' => 'none',
+ 'CURLINFO_NONE' => 'none',
+ 'CURLINFO_SSL_DATA_IN' => 'none',
+ 'CURLINFO_SSL_DATA_OUT' => 'none',
+ 'CURLINFO_TEXT' => 'none'
+ );
+
+sub scanmanpage {
+ my ($file, @words) = @_;
+
+ open(my $mh, "<", "$file") ||
+ die "could not open $file";
+ my @m;
+ while(<$mh>) {
+ if($_ =~ /^\.IP (.*)/) {
+ my $w = $1;
+ # "unquote" minuses
+ $w =~ s/\\-/-/g;
+ push @m, $w;
+ }
+ }
+ close($mh);
+
+ foreach my $m (@words) {
+ my @g = grep(/$m/, @m);
+ if(!$g[0]) {
+ print STDERR "Missing mention of $m in $file\n";
+ $errors++;
+ }
+ }
+}
+
+my $r;
+
+# check for define aliases
+open($r, "<", "$curlh") ||
+ die "no curl.h";
+while(<$r>) {
+ if(/^\#define (CURL(OPT|INFO|MOPT)_\w+) (.*)/) {
+ $alias{$1}=$3;
+ }
+}
+close($r);
+
+my @curlopt;
+my @curlinfo;
+my @curlmopt;
+open($r, "<", "$syms") ||
+ die "no input file";
+while(<$r>) {
+ chomp;
+ my $l= $_;
+ if($l =~ /(CURL(OPT|INFO|MOPT)_\w+) *([0-9.]*) *([0-9.-]*) *([0-9.]*)/) {
+ my ($opt, $type, $add, $dep, $rem) = ($1, $2, $3, $4, $5);
+
+ if($alias{$opt}) {
+ #print "$opt => $alias{$opt}\n";
+ }
+ elsif($rem) {
+ # $opt was removed in $rem
+ # so don't check for that
+ }
+ else {
+ if($type eq "OPT") {
+ push @curlopt, $opt,
+ }
+ elsif($type eq "INFO") {
+ push @curlinfo, $opt,
+ }
+ elsif($type eq "MOPT") {
+ push @curlmopt, $opt,
+ }
+ if(! -f "$buildroot/docs/libcurl/opts/$opt.3") {
+ print STDERR "Missing $opt.3\n";
+ $errors++;
+ }
+ }
+ }
+}
+close($r);
+
+scanmanpage("$buildroot/docs/libcurl/curl_easy_setopt.3", @curlopt);
+scanmanpage("$buildroot/docs/libcurl/curl_easy_getinfo.3", @curlinfo);
+scanmanpage("$buildroot/docs/libcurl/curl_multi_setopt.3", @curlmopt);
+
+# using this hash array, we can skip specific options
+my %opts = (
+ # pretend these --no options exists in tool_getparam.c
+ '--no-alpn' => 1,
+ '--no-npn' => 1,
+ '-N, --no-buffer' => 1,
+ '--no-sessionid' => 1,
+ '--no-keepalive' => 1,
+ '--no-progress-meter' => 1,
+ '--no-clobber' => 1,
+
+ # pretend these options without -no exist in curl.1 and tool_listhelp.c
+ '--alpn' => 6,
+ '--npn' => 6,
+ '--eprt' => 6,
+ '--epsv' => 6,
+ '--keepalive' => 6,
+ '-N, --buffer' => 6,
+ '--sessionid' => 6,
+ '--progress-meter' => 6,
+ '--clobber' => 6,
+
+ # deprecated options do not need to be in tool_help.c nor curl.1
+ '--krb4' => 6,
+ '--ftp-ssl' => 6,
+ '--ftp-ssl-reqd' => 6,
+
+ # for tests and debug only, can remain hidden
+ '--test-event' => 6,
+ '--wdebug' => 6,
+ );
+
+
+#########################################################################
+# parse the curl code that parses the command line arguments!
+open($r, "<", "$root/src/tool_getparam.c") ||
+ die "no input file";
+my $list;
+my @getparam; # store all parsed parameters
+
+my $prevlong = "";
+my $no = 0;
+while(<$r>) {
+ $no++;
+ chomp;
+ if(/struct LongShort aliases/) {
+ $list=1;
+ }
+ elsif($list) {
+ if( /^ \{(\"[^,]*\").*\'(.)\', (.*)\}/) {
+ my ($l, $s, $rd)=($1, $2, $3);
+ my $sh;
+ my $lo;
+ my $title;
+ if(($l cmp $prevlong) < 0) {
+ print STDERR "tool_getparam.c:$no: '$l' is NOT placed in alpha-order\n";
+ }
+ if($l =~ /\"(.*)\"/) {
+ # long option
+ $lo = $1;
+ $title="--$lo";
+ }
+ if($s ne " ") {
+ # a short option
+ $sh = $s;
+ $title="-$sh, $title";
+ }
+ push @getparam, $title;
+ $opts{$title} |= 1;
+ $prevlong = $l;
+ }
+ }
+}
+close($r);
+
+#########################################################################
+# parse the curl.1 man page, extract all documented command line options
+# The man page may or may not be rebuilt, so check both possible locations
+open($r, "<", "$buildroot/docs/curl.1") || open($r, "<", "$root/docs/curl.1") ||
+ die "no input file";
+my @manpage; # store all parsed parameters
+while(<$r>) {
+ chomp;
+ my $l= $_;
+ $l =~ s/\\-/-/g;
+ if($l =~ /^\.IP \"(-[^\"]*)\"/) {
+ my $str = $1;
+ my $combo;
+ if($str =~ /^-(.), --([a-z0-9.-]*)/) {
+ # figure out the -short, --long combo
+ $combo = "-$1, --$2";
+ }
+ elsif($str =~ /^--([a-z0-9.-]*)/) {
+ # figure out the --long name
+ $combo = "--$1";
+ }
+ if($combo) {
+ push @manpage, $combo;
+ $opts{$combo} |= 2;
+ }
+ }
+}
+close($r);
+
+
+#########################################################################
+# parse the curl code that outputs the curl -h list
+open($r, "<", "$root/src/tool_listhelp.c") ||
+ die "no input file";
+my @toolhelp; # store all parsed parameters
+while(<$r>) {
+ chomp;
+ my $l= $_;
+ if(/^ \{\" *(.*)/) {
+ my $str=$1;
+ my $combo;
+ if($str =~ /^-(.), --([a-z0-9.-]*)/) {
+ # figure out the -short, --long combo
+ $combo = "-$1, --$2";
+ }
+ elsif($str =~ /^--([a-z0-9.-]*)/) {
+ # figure out the --long name
+ $combo = "--$1";
+ }
+ if($combo) {
+ push @toolhelp, $combo;
+ $opts{$combo} |= 4;
+ }
+
+ }
+}
+close($r);
+
+#
+# Now we have three arrays with options to cross-reference.
+
+foreach my $o (keys %opts) {
+ my $where = $opts{$o};
+
+ if($where != 7) {
+ # this is not in all three places
+ $errors++;
+ my $exists;
+ my $missing;
+ if($where & 1) {
+ $exists=" tool_getparam.c";
+ }
+ else {
+ $missing=" tool_getparam.c";
+ }
+ if($where & 2) {
+ $exists.= " curl.1";
+ }
+ else {
+ $missing.= " curl.1";
+ }
+ if($where & 4) {
+ $exists .= " tool_listhelp.c";
+ }
+ else {
+ $missing .= " tool_listhelp.c";
+ }
+
+ print STDERR "$o is not in$missing (but in$exists)\n";
+ }
+}
+
+print STDERR "$errors\n";
diff --git a/tests/test1140.pl b/tests/test1140.pl
new file mode 100755
index 000000000..b9438dec0
--- /dev/null
+++ b/tests/test1140.pl
@@ -0,0 +1,114 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+# scan nroff pages to find basic syntactic problems such as unbalanced \f
+# codes or references to non-existing curl man pages.
+
+my $docsroot = $ARGV[0];
+
+if(!$docsroot || ($docsroot eq "-g")) {
+ print "Usage: nroff-scan.pl <docs root dir> [nroff files]\n";
+ exit;
+}
+
+
+shift @ARGV;
+
+my @f = @ARGV;
+
+my %manp;
+
+sub manpresent {
+ my ($man) = @_;
+ if($manp{$man}) {
+ return 1;
+ }
+ elsif(-r "$docsroot/$man" ||
+ -r "$docsroot/libcurl/$man" ||
+ -r "$docsroot/libcurl/opts/$man") {
+ $manp{$man}=1;
+ return 1;
+ }
+ return 0;
+}
+
+sub file {
+ my ($f) = @_;
+ open(my $fh, "<", "$f") ||
+ die "no file";
+ my $line = 1;
+ while(<$fh>) {
+ chomp;
+ my $l = $_;
+ while($l =~ s/\\f(.)([^ ]*)\\f(.)//) {
+ my ($pre, $str, $post)=($1, $2, $3);
+ if($str =~ /^\\f[ib]/i) {
+ print "error: $f:$line: double-highlight\n";
+ $errors++;
+ }
+ if($post ne "P") {
+ print "error: $f:$line: missing \\fP after $str\n";
+ $errors++;
+ }
+ if($str =~ /((libcurl|curl)([^ ]*))\(3\)/i) {
+ my $man = "$1.3";
+ $man =~ s/\\//g; # cut off backslashes
+ if(!manpresent($man)) {
+ print "error: $f:$line: referring to non-existing man page $man\n";
+ $errors++;
+ }
+ if($pre ne "I") {
+ print "error: $f:$line: use \\fI before $str\n";
+ $errors++;
+ }
+ }
+ }
+ if($l =~ /(curl([^ ]*)\(3\))/i) {
+ print "error: $f:$line: non-referencing $1\n";
+ $errors++;
+ }
+ if($l =~ /^\.BR (.*)/) {
+ my $i= $1;
+ while($i =~ s/((lib|)curl([^ ]*)) *\"\(3\)(,|) *\" *//i ) {
+ my $man = "$1.3";
+ $man =~ s/\\//g; # cut off backslashes
+ if(!manpresent($man)) {
+ print "error: $f:$line: referring to non-existing man page $man\n";
+ $errors++;
+ }
+ }
+ }
+ $line++;
+ }
+ close($fh);
+}
+
+foreach my $f (@f) {
+ file($f);
+}
+
+print "OK\n" if(!$errors);
+
+exit $errors?1:0;
diff --git a/tests/test1165.pl b/tests/test1165.pl
new file mode 100755
index 000000000..b6f3179cf
--- /dev/null
+++ b/tests/test1165.pl
@@ -0,0 +1,189 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+
+use strict;
+use warnings;
+
+# the DISABLE options that can be set by configure
+my %disable;
+# the DISABLE options that can be set by CMakeLists.txt
+my %disable_cmake;
+# the DISABLE options that are used in C files
+my %file;
+# the DISABLE options that are documented
+my %docs;
+
+# we may get the dir root pointed out
+my $root=$ARGV[0] || ".";
+my $DOCS="CURL-DISABLE.md";
+
+sub scanconf {
+ my ($f)=@_;
+ open S, "<$f";
+ while(<S>) {
+ if(/(CURL_DISABLE_[A-Z_]+)/g) {
+ my ($sym)=($1);
+ $disable{$sym} = 1;
+ }
+ }
+ close S;
+}
+
+sub scan_configure {
+ opendir(my $m, "$root/m4") || die "Can't opendir $root/m4: $!";
+ my @m4 = grep { /\.m4$/ } readdir($m);
+ closedir $m;
+ scanconf("$root/configure.ac");
+ # scan all m4 files too
+ for my $e (@m4) {
+ scanconf("$root/m4/$e");
+ }
+}
+
+sub scanconf_cmake {
+ my ($f)=@_;
+ open S, "<$f";
+ while(<S>) {
+ if(/(CURL_DISABLE_[A-Z_]+)/g) {
+ my ($sym)=($1);
+ if(not $sym =~ /(CURL_DISABLE_INSTALL|CURL_DISABLE_TESTS|CURL_DISABLE_SRP)/) {
+ $disable_cmake{$sym} = 1;
+ }
+ }
+ }
+ close S;
+}
+
+sub scan_cmake {
+ scanconf_cmake("$root/CMakeLists.txt");
+}
+
+sub scan_file {
+ my ($source)=@_;
+ open F, "<$source";
+ while(<F>) {
+ while(s/(CURL_DISABLE_[A-Z_]+)//) {
+ my ($sym)=($1);
+ $file{$sym} = $source;
+ }
+ }
+ close F;
+}
+
+sub scan_dir {
+ my ($dir)=@_;
+ opendir(my $dh, $dir) || die "Can't opendir $dir: $!";
+ my @cfiles = grep { /\.[ch]\z/ && -f "$dir/$_" } readdir($dh);
+ closedir $dh;
+ for my $f (sort @cfiles) {
+ scan_file("$dir/$f");
+ }
+}
+
+sub scan_sources {
+ scan_dir("$root/src");
+ scan_dir("$root/lib");
+ scan_dir("$root/lib/vtls");
+ scan_dir("$root/lib/vauth");
+}
+
+sub scan_docs {
+ open F, "<$root/docs/$DOCS";
+ my $line = 0;
+ while(<F>) {
+ $line++;
+ if(/^## `(CURL_DISABLE_[A-Z_]+)/g) {
+ my ($sym)=($1);
+ $docs{$sym} = $line;
+ }
+ }
+ close F;
+}
+
+scan_configure();
+scan_cmake();
+scan_sources();
+scan_docs();
+
+
+my $error = 0;
+# Check the configure symbols for use in code
+for my $s (sort keys %disable) {
+ if(!$file{$s}) {
+ printf "Present in configure.ac, not used by code: %s\n", $s;
+ $error++;
+ }
+ if(!$docs{$s}) {
+ printf "Present in configure.ac, not documented in $DOCS: %s\n", $s;
+ $error++;
+ }
+}
+
+# Check the CMakeLists.txt symbols for use in code
+for my $s (sort keys %disable_cmake) {
+ if(!$file{$s}) {
+ printf "Present in CMakeLists.txt, not used by code: %s\n", $s;
+ $error++;
+ }
+ if(!$docs{$s}) {
+ printf "Present in CMakeLists.txt, not documented in $DOCS: %s\n", $s;
+ $error++;
+ }
+}
+
+# Check the code symbols for use in configure
+for my $s (sort keys %file) {
+ if(!$disable{$s}) {
+ printf "Not set by configure: %s (%s)\n", $s, $file{$s};
+ $error++;
+ }
+ if(!$disable_cmake{$s}) {
+ printf "Not set by CMakeLists.txt: %s (%s)\n", $s, $file{$s};
+ $error++;
+ }
+ if(!$docs{$s}) {
+ printf "Used in code, not documented in $DOCS: %s\n", $s;
+ $error++;
+ }
+}
+
+# Check the documented symbols
+for my $s (sort keys %docs) {
+ if(!$disable{$s}) {
+ printf "Documented but not in configure: %s\n", $s;
+ $error++;
+ }
+ if(!$disable_cmake{$s}) {
+ printf "Documented but not in CMakeLists.txt: %s\n", $s;
+ $error++;
+ }
+ if(!$file{$s}) {
+ printf "Documented, but not used by code: %s\n", $s;
+ $error++;
+ }
+}
+
+exit $error;
diff --git a/tests/badsymbols.pl b/tests/test1167.pl
index a3a39d420..a3a39d420 100755
--- a/tests/badsymbols.pl
+++ b/tests/test1167.pl
diff --git a/tests/manpage-syntax.pl b/tests/test1173.pl
index 7457c7d44..7457c7d44 100755
--- a/tests/manpage-syntax.pl
+++ b/tests/test1173.pl
diff --git a/tests/error-codes.pl b/tests/test1175.pl
index 8147ef6d0..8147ef6d0 100755
--- a/tests/error-codes.pl
+++ b/tests/test1175.pl
diff --git a/tests/test1177.pl b/tests/test1177.pl
new file mode 100755
index 000000000..e989e3a89
--- /dev/null
+++ b/tests/test1177.pl
@@ -0,0 +1,94 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+# Verify that curl_version_info.3 documents all the CURL_VERSION_ bits
+# from the header.
+#
+
+use strict;
+use warnings;
+
+my $manpage=$ARGV[0];
+my $header=$ARGV[1];
+my $source=$ARGV[2];
+my %manversion;
+my %headerversion;
+my %manname;
+my %sourcename;
+my $error=0;
+
+open(my $m, "<", "$manpage");
+while(<$m>) {
+ if($_ =~ / mask bit: (CURL_VERSION_[A-Z0-9_]+)/i) {
+ $manversion{$1}++;
+ }
+ if($_ =~ /^\.ip (.*)/i) {
+ $manname{$1}++;
+ }
+}
+close($m);
+
+open(my $h, "<", "$header");
+while(<$h>) {
+ if($_ =~ /^\#define (CURL_VERSION_[A-Z0-9_]+)/i) {
+ $headerversion{$1}++;
+ }
+}
+close($h);
+
+open(my $s, "<", "$source");
+while(<$s>) {
+ if($_ =~ /FEATURE\("([^"]*)"/) {
+ $sourcename{$1}++;
+ }
+}
+close($s);
+
+for my $h (keys %headerversion) {
+ if(!$manversion{$h}) {
+ print STDERR "$manpage: missing $h\n";
+ $error++;
+ }
+}
+for my $h (keys %manversion) {
+ if(!$headerversion{$h}) {
+ print STDERR "$manpage: $h is not in the header!\n";
+ $error++;
+ }
+}
+for my $n (keys %sourcename) {
+ if(!$manname{$n}) {
+ print STDERR "$manpage: missing feature name $n\n";
+ $error++;
+ }
+}
+for my $n (keys %manname) {
+ if(!$sourcename{$n} && ($n ne "\"no name\"")) {
+ print STDERR "$manpage: $n is not in the source!\n";
+ $error++;
+ }
+}
+
+exit $error;
diff --git a/tests/check-deprecated.pl b/tests/test1222.pl
index b26aea872..b26aea872 100755
--- a/tests/check-deprecated.pl
+++ b/tests/test1222.pl
diff --git a/tests/test1275.pl b/tests/test1275.pl
new file mode 100755
index 000000000..082946a22
--- /dev/null
+++ b/tests/test1275.pl
@@ -0,0 +1,117 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+my $root=$ARGV[0] || "..";
+
+my @m = `git ls-files -- $root`;
+
+my $errors;
+
+my %accepted=('curl' => 1,
+ 'libcurl' => 1,
+ 'c-ares' => 1);
+
+sub checkfile {
+ my ($f) = @_;
+ chomp $f;
+ if($f !~ /\.md\z/) {
+ return;
+ }
+ open(my $fh, "<", "$f");
+ my $l;
+ my $prevl;
+ my $ignore = 0;
+ my $metadata = 0;
+ while(<$fh>) {
+ my $line = $_;
+ chomp $line;
+ $l++;
+ if(($l == 1) && ($line =~ /^---/)) {
+ # first line is a meta-data divider, skip to the next one
+ $metadata = 1;
+ print STDERR "skip meta-data in $f\n";
+ next;
+ }
+ elsif($metadata) {
+ if($line !~ /^---/) {
+ next;
+ }
+ $metadata = 0;
+ next;
+ }
+ if($line =~ /^(\`\`\`|\~\~\~)/) {
+ # start or stop ignore-mode
+ $ignore ^= 1;
+ }
+ if(!$ignore) {
+ if(($prevl =~ /\.\z/) && ($line =~ /^( *)([a-z-]+)/)) {
+ my ($prefix, $word) = ($1, $2);
+ if($word =~ /^[a-z]/ && !$accepted{$word}) {
+ my $c = length($prefix);
+ print STDERR
+ "$f:$l:$c:error: lowercase $word after period\n";
+ print STDERR "$line\n";
+ print STDERR ' ' x $c;
+ print STDERR "^\n";
+ $errors++;
+ }
+ }
+ elsif($line =~ /^(.*)\. +([a-z-]+)/) {
+ my ($prefix, $word) = ($1, $2);
+
+ if(($prefix =~ /\.\.\z/) ||
+ ($prefix =~ /[0-9]\z/) ||
+ ($prefix =~ /e.g\z/) ||
+ ($prefix =~ /i.e\z/) ||
+ ($prefix =~ /E.g\z/) ||
+ ($prefix =~ /etc\z/) ||
+ ($word !~ /^[a-z]/) ||
+ $accepted{$word}) {
+ }
+ else {
+ my $c = length($prefix) + 2;
+ print STDERR
+ "$f:$l:$c:error: lowercase $word after period\n";
+ print STDERR "$line\n";
+ print STDERR ' ' x $c;
+ print STDERR "^\n";
+ $errors++;
+ }
+ }
+ }
+ $prevl = $line;
+ }
+ close($fh);
+}
+
+
+for my $f (@m) {
+ checkfile($f);
+}
+
+if($errors) {
+ exit 1;
+}
+print "ok\n";
diff --git a/tests/option-check.pl b/tests/test1276.pl
index 74d465173..74d465173 100755
--- a/tests/option-check.pl
+++ b/tests/test1276.pl
diff --git a/tests/test1477.pl b/tests/test1477.pl
new file mode 100755
index 000000000..ad564b26d
--- /dev/null
+++ b/tests/test1477.pl
@@ -0,0 +1,100 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+
+# Check that libcurl-errors.3 and the public header files have the same set of
+# error codes.
+
+use strict;
+use warnings;
+
+# we may get the dir roots pointed out
+my $root=$ARGV[0] || ".";
+my $buildroot=$ARGV[1] || ".";
+my $manpge = "$buildroot/docs/libcurl/libcurl-errors.3";
+my $curlh = "$root/include/curl";
+my $errors=0;
+
+my @hnames;
+my %wherefrom;
+my @mnames;
+my %manfrom;
+
+sub scanheader {
+ my ($file)=@_;
+ open H, "<$file";
+ my $line = 0;
+ while(<H>) {
+ $line++;
+ if($_ =~ /^ (CURL(E|UE|SHE|HE|M)_[A-Z0-9_]*)/) {
+ my ($name)=($1);
+ if(($name !~ /OBSOLETE/) && ($name !~ /_LAST\z/)) {
+ push @hnames, $name;
+ if($wherefrom{$name}) {
+ print STDERR "double: $name\n";
+ }
+ $wherefrom{$name}="$file:$line";
+ }
+ }
+ }
+ close(H);
+}
+
+sub scanmanpage {
+ my ($file)=@_;
+ open H, "<$file";
+ my $line = 0;
+ while(<H>) {
+ $line++;
+ if($_ =~ /^\.IP \"(CURL(E|UE|SHE|HE|M)_[A-Z0-9_]*)/) {
+ my ($name)=($1);
+ push @mnames, $name;
+ $manfrom{$name}="$file:$line";
+ }
+ }
+ close(H);
+}
+
+
+opendir(my $dh, $curlh) || die "Can't opendir $curlh: $!";
+my @hfiles = grep { /\.h$/ } readdir($dh);
+closedir $dh;
+
+for(sort @hfiles) {
+ scanheader("$curlh/$_");
+}
+scanmanpage($manpge);
+
+print "Result\n";
+for my $h (sort @hnames) {
+ if(!$manfrom{$h}) {
+ printf "$h from %s, not in man page\n", $wherefrom{$h};
+ }
+}
+
+for my $m (sort @mnames) {
+ if(!$wherefrom{$m}) {
+ printf "$m from %s, not in any header\n", $manfrom{$m};
+ }
+}
diff --git a/tests/check-translatable-options.pl b/tests/test1544.pl
index 64d036d27..64d036d27 100755
--- a/tests/check-translatable-options.pl
+++ b/tests/test1544.pl
diff --git a/tests/test971.pl b/tests/test971.pl
new file mode 100755
index 000000000..1aeed9d48
--- /dev/null
+++ b/tests/test971.pl
@@ -0,0 +1,125 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 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.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.
+#
+# SPDX-License-Identifier: curl
+#
+###########################################################################
+#
+#
+# - Get all options mentioned in the $cmddir.
+# - Make sure they're all mentioned in the $opts document
+# - Make sure 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 { /[a-z0-9].*\.md$/ && -f "$dir/$_" } readdir($dh);
+ closedir $dh;
+
+ for(@opts) {
+ $_ =~ s/\.md$//;
+ $file{$_}=1;
+ }
+ return @opts;
+}
+
+sub mentions {
+ my ($f) = @_;
+ my @options;
+ open(my $fh, "<", "$f");
+ while(<$fh>) {
+ 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;
+ }
+ }
+ close($fh);
+ return @options;
+}
+
+sub versioncheck {
+ my ($f, $v)=@_;
+ open(my $fh, "<", "$cmddir/$f.md");
+ while(<$fh>) {
+ chomp;
+ if(/^Added: ([0-9.]+)/) {
+ if($1 ne $v) {
+ print STDERR "$f lists $v in doc but $1 in file\n";
+ $error++;
+ }
+ last;
+ }
+ }
+ close($fh);
+}
+
+# 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 option directory but not in $opts!\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++;
+ }
+}
+
+print STDERR "ok\n" if(!$error);
+
+exit $error;
diff --git a/tests/testutil.pm b/tests/testutil.pm
index ece0b6e05..1a44083e1 100644
--- a/tests/testutil.pm
+++ b/tests/testutil.pm
@@ -94,6 +94,15 @@ sub clearlogs {
#######################################################################
+
+sub includefile {
+ my ($f) = @_;
+ open(F, "<$f");
+ my @a = <F>;
+ close(F);
+ return join("", @a);
+}
+
sub subbase64 {
my ($thing) = @_;
@@ -113,6 +122,7 @@ sub subbase64 {
$d =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
$$thing =~ s/%%HEX%%/$d/;
}
+ # repeat
while($$thing =~ s/%repeat\[(\d+) x (.*?)\]%/%%REPEAT%%/i) {
# decode %NN characters
my ($d, $n) = ($2, $1);
@@ -120,6 +130,9 @@ sub subbase64 {
my $all = $d x $n;
$$thing =~ s/%%REPEAT%%/$all/;
}
+
+ # include a file
+ $$thing =~ s/%include ([^%]*)%[\n\r]+/includefile($1)/ge;
}
my $prevupdate; # module scope so it remembers the last value
diff --git a/tests/unit/curlcheck.h b/tests/unit/curlcheck.h
index 756f76e36..928964422 100644
--- a/tests/unit/curlcheck.h
+++ b/tests/unit/curlcheck.h
@@ -93,8 +93,6 @@
} while(0)
-extern int unitfail;
-
#define UNITTEST_START \
int test(char *arg) \
{ \
diff --git a/tests/unit/unit1394.c b/tests/unit/unit1394.c
index e4e998184..ef398ab22 100644
--- a/tests/unit/unit1394.c
+++ b/tests/unit/unit1394.c
@@ -61,7 +61,7 @@ UNITTEST_START
"pkcs11:foobar", "pkcs11:foobar", NULL,
"PKCS11:foobar", "PKCS11:foobar", NULL,
"PkCs11:foobar", "PkCs11:foobar", NULL,
-#ifdef WIN32
+#ifdef _WIN32
"c:\\foo:bar:baz", "c:\\foo", "bar:baz",
"c:\\foo\\:bar:baz", "c:\\foo:bar", "baz",
"c:\\foo\\\\:bar:baz", "c:\\foo\\", "bar:baz",
diff --git a/tests/unit/unit1395.c b/tests/unit/unit1395.c
index d01403f33..017b45a0e 100644
--- a/tests/unit/unit1395.c
+++ b/tests/unit/unit1395.c
@@ -83,15 +83,17 @@ UNITTEST_START
abort_unless(err == 0, "returned error");
abort_if(err && out, "returned error with output");
- if(out && strcmp(out, pairs[i].output)) {
+ if(out && pairs[i].output && strcmp(out, pairs[i].output)) {
fprintf(stderr, "Test %u: '%s' gave '%s' instead of '%s'\n",
i, pairs[i].input, out, pairs[i].output);
fail("Test case output mismatched");
fails++;
}
- else if(!out && pairs[i].output) {
- fprintf(stderr, "Test %u: '%s' gave '%s' instead of NULL\n",
- i, pairs[i].input, out);
+ else if((!out && pairs[i].output) ||
+ (out && !pairs[i].output)) {
+ fprintf(stderr, "Test %u: '%s' gave '%s' instead of '%s'\n",
+ i, pairs[i].input, out ? out : "(null)",
+ pairs[i].output ? pairs[i].output : "(null)");
fail("Test case output mismatched");
fails++;
}
diff --git a/tests/unit/unit1398.c b/tests/unit/unit1398.c
index bf8af12d3..4283a8d1b 100644
--- a/tests/unit/unit1398.c
+++ b/tests/unit/unit1398.c
@@ -92,7 +92,7 @@ fail_unless(rc == 15, "return code should be 15");
fail_unless(!strcmp(output, " 1234 567"), "wrong output");
/* double precision */
-rc = curl_msnprintf(output, 24, "%.*1$.99d", 3, 5678);
+rc = curl_msnprintf(output, 24, "%2$.*1$.99d", 3, 5678);
fail_unless(rc == 0, "return code should be 0");
UNITTEST_STOP
diff --git a/tests/unit/unit1604.c b/tests/unit/unit1604.c
index 411b94a02..cba3dfcf6 100644
--- a/tests/unit/unit1604.c
+++ b/tests/unit/unit1604.c
@@ -42,7 +42,7 @@ static void unit_stop(void)
}
-#if defined(MSDOS) || defined(WIN32)
+#if defined(_WIN32) || defined(MSDOS)
static char *getflagstr(int flags)
{
@@ -353,6 +353,6 @@ UNITTEST_START
{
fprintf(stderr, "Skipped test not for this platform\n");
}
-#endif /* MSDOS || WIN32 */
+#endif /* _WIN32 || MSDOS */
UNITTEST_STOP
diff --git a/tests/unit/unit1651.c b/tests/unit/unit1651.c
index 58d2f1076..63f339394 100644
--- a/tests/unit/unit1651.c
+++ b/tests/unit/unit1651.c
@@ -368,7 +368,7 @@ UNITTEST_START
happens */
for(byte = 1 ; byte < 255; byte += 17) {
for(i = 0; i < 45; i++) {
- char backup = cert[i];
+ unsigned char backup = cert[i];
cert[i] = (unsigned char) (byte & 0xff);
(void) Curl_extract_certinfo(data, 0, beg, end);
cert[i] = backup;
diff --git a/tests/unit/unit1652.c b/tests/unit/unit1652.c
index ef2726216..68ddec3ea 100644
--- a/tests/unit/unit1652.c
+++ b/tests/unit/unit1652.c
@@ -21,6 +21,8 @@
* SPDX-License-Identifier: curl
*
***************************************************************************/
+#define CURL_NO_FMT_CHECKS
+
#include "curlcheck.h"
#include "urldata.h"
@@ -105,7 +107,7 @@ fail_unless(verify(result, "Simple Test 42 testing 43\n") == 0,
/* Variations of empty strings */
Curl_infof(data, "");
fail_unless(strlen(result) == 1, "Empty string");
-Curl_infof(data, "%s", NULL);
+Curl_infof(data, "%s", (char *)NULL);
fail_unless(verify(result, "(nil)") == 0, "Passing NULL as string");
/* A string just long enough to not be truncated */
diff --git a/tests/unit/unit2600.c b/tests/unit/unit2600.c
index d7b1efdd7..a2089b275 100644
--- a/tests/unit/unit2600.c
+++ b/tests/unit/unit2600.c
@@ -124,7 +124,7 @@ static void cf_test_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
struct cf_test_ctx *ctx = cf->ctx;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "%04dms: cf[%s] destroyed",
- (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id);
+ (int)Curl_timediff(Curl_now(), current_tr->started), ctx->id);
#else
(void)data;
#endif
@@ -145,7 +145,7 @@ static CURLcode cf_test_connect(struct Curl_cfilter *cf,
duration_ms = Curl_timediff(Curl_now(), ctx->started);
if(duration_ms >= ctx->fail_delay_ms) {
infof(data, "%04dms: cf[%s] fail delay reached",
- (int)duration_ms, ctx->id);
+ (int)duration_ms, ctx->id);
return CURLE_COULDNT_CONNECT;
}
if(duration_ms)
@@ -162,7 +162,7 @@ static struct Curl_cftype cft_test = {
cf_test_connect,
Curl_cf_def_close,
Curl_cf_def_get_host,
- Curl_cf_def_get_select_socks,
+ Curl_cf_def_adjust_pollset,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
@@ -185,7 +185,7 @@ static CURLcode cf_test_create(struct Curl_cfilter **pcf,
(void)data;
(void)conn;
- ctx = calloc(sizeof(*ctx), 1);
+ ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
diff --git a/tests/unit/unit3200.c b/tests/unit/unit3200.c
index eff566772..0544bcc93 100644
--- a/tests/unit/unit3200.c
+++ b/tests/unit/unit3200.c
@@ -47,6 +47,7 @@ static CURLcode unit_stop(void)
}
#ifdef __GNUC__
+#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverlength-strings"
#endif
@@ -161,6 +162,10 @@ UNITTEST_START
}
UNITTEST_STOP
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
#else
static CURLcode unit_setup(void)
{
diff --git a/tests/version-scan.pl b/tests/version-scan.pl
deleted file mode 100755
index 3c055d9b3..000000000
--- a/tests/version-scan.pl
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 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.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.
-#
-# SPDX-License-Identifier: curl
-#
-###########################################################################
-#
-# Verify that curl_version_info.3 documents all the CURL_VERSION_ bits
-# from the header.
-#
-
-use strict;
-use warnings;
-
-my $manpage=$ARGV[0];
-my $header=$ARGV[1];
-my $source=$ARGV[2];
-my %manversion;
-my %headerversion;
-my %manname;
-my %sourcename;
-my $error=0;
-
-open(my $m, "<", "$manpage");
-while(<$m>) {
- if($_ =~ / mask bit: (CURL_VERSION_[A-Z0-9_]+)/i) {
- $manversion{$1}++;
- }
- if($_ =~ /^\.ip """([^"]+)"""/i) {
- $manname{$1}++;
- }
-}
-close($m);
-
-open(my $h, "<", "$header");
-while(<$h>) {
- if($_ =~ /^\#define (CURL_VERSION_[A-Z0-9_]+)/i) {
- $headerversion{$1}++;
- }
-}
-close($h);
-
-open(my $s, "<", "$source");
-while(<$s>) {
- if($_ =~ /FEATURE\("([^"]*)"/) {
- $sourcename{$1}++;
- }
-}
-close($s);
-
-for my $h (keys %headerversion) {
- if(!$manversion{$h}) {
- print STDERR "$manpage: missing $h\n";
- $error++;
- }
-}
-for my $h (keys %manversion) {
- if(!$headerversion{$h}) {
- print STDERR "$manpage: $h is not in the header!\n";
- $error++;
- }
-}
-for my $n (keys %sourcename) {
- if(!$manname{$n}) {
- print STDERR "$manpage: missing feature name $n\n";
- $error++;
- }
-}
-for my $n (keys %manname) {
- if(!$sourcename{$n}) {
- print STDERR "$manpage: $n is not in the source!\n";
- $error++;
- }
-}
-
-exit $error;